package me.txc.idiom;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Wiki文字处理引擎
* <p>
* 常用wiki体列举如下:
* <ol>
* <li>直接闭合
* <ul>
* <li> ---- 对应 </hl> </li>
* <li> > 对应 <ul> </li>
* <li> >> 对应 <li> </li>
* </ul>
* </li>
* <li>单值
* <ul>
* <li> [img[xxx.jpg]] 对应 </hr> </li>
* <li> ``xxx`` 对应 <b> xxx </b></li>
* <li> //xxx// 对应 <i> xxx </i></li>
* </ul>
* </li>
* <li>多值
* <ul>
* <li> @@color(red):xxx@@ 对应 <font color="red"> xxx </font>
* </li>
* <li> @@bgcolor(red):xxx@@ 对应 <span background="red"> xxx
* </span> </li>
* </ul>
* </li>
* <li>特殊处理
* <ul>
* <li>表格</li>
* <li>列表</li>
* </ul>
* </li>
* </ol>
* </p>
*
* @author tangxiucai2@gmail.com
*
*/
public class WikiTextEngine {
private final static int NONE_VALUE = 0;
private final static int SINGLE_VALUE = 1;
public static void main(String[] args) {
WikiTextEngine wh = new WikiTextEngine();
wh.addWikiText("``", "<b>$1</b>", "文字加粗", "", 1);
wh.addWikiText("//", "<i>$1</i>", "文字倾斜", "", 1);
wh.addWikiText("----", "<hr>", "横线", "", 0);
wh.addWikiText("@@color()", "<font color=\"$1\"/>$2</font>", "文字颜色",
"@@color\\((.+?)\\):(.+?)@@", 2);
wh.addWikiText("@@bgcolor()", "<span background=\"$1\">$2</span>",
"文本背景色", "@@bgcolor\\((.+?)\\):(.+?)@@", 2);
wh.addWikiText("--", "删除", new WikiTextHandler(){
@Override
public String process(String target) {
String regex = "--(.+?)--";
if(Pattern.matches(regex, target)){
Pattern pattern = Pattern.compile(regex);
for(Matcher matcher = pattern.matcher(target); matcher.find();){
String findStr = matcher.group();
String includedStr = matcher.group(1);
String newStr = "(已删除:" +includedStr+ ")";
target = target.replaceAll(findStr, newStr);
}
}
return target;
}});
String[] demo = new String[] { "abc----", "``hello``", "//he llo//",
"@@color(blue):This is --some-- text.@@", "@@bgcolor(red):文本 背景.@@",
"--xxx--yyy--zzz--" };
for (String str : demo)
System.out.println(wh.process(str));
}
/**
* 添加Wiki体
*
* @param symbol
* 符号 起到键的作用,需要保持唯一
* @param text
* 替代的HTML文本,$1代表发现的剔除符号外的文本的占位符 例如 要将``xxx``最终替换为
* <b>xxx</b>则这里的text设为<b>$1</b>,要将[img[xxx.jpg]]最终替换为<img
* src="xxx.jpg"/>则这里的text需设为<img src="$1"/>
* @param meaning
* 符号表示的含义
* @param regex
* 符号匹配的正则,如果存在对应的正则,则按照设定的正则进行特殊匹配 例如 [img[(\\w+)]] 可以匹配
* [img[xxx.jpg]];否则将默认按照首尾一致的原则进行匹配 例如 --(\\w+)--
* 但是所有组装出的正则中不应该在存在()
* @param valueCount
* 占位符个数:取值0/1/2/... 不可设为-1(-1表示自定义解析规则) 即例如
* <hr/>为0个,<b>xx <b>为1,< font
* color="$1">$2 </font>
*/
public void addWikiText(String symbol, String text, String meaning,
String regex, int valueCount) {
WikiTextManager.getContainer().add(
this.new WikiText(symbol, text, meaning, regex, valueCount));
}
/**
* 添加Wiki体
*
* @param symbol
* 符号
* @param meaning
* 含义
*
* @param handler
* 自定义处理规则
*
* @see #addWikiText(String, String, String, String, int)
*/
public void addWikiText(String symbol, String meaning,
WikiTextHandler handler) {
WikiTextManager.getContainer().add(
this.new WikiText(symbol, meaning, handler));
}
/**
* 移除指定的Wiki体
*
* @param symbol
* 符号
*/
public void removeWikiText(String symbol) {
WikiTextManager.getContainer().remove(symbol);
}
/**
* 处理wiki体转义为HTML
*
* @param target
* 需要处理的目标字符串
* @return 处理后的字符串
*/
public String process(String target) {
if (target == null || "".equals(target))
return "";
String result = target;
for (Iterator<WikiText> it = WikiTextManager.getContainer().iterator(); it
.hasNext();) {
result = replace(it.next(), result);
}
return result;
}
/**
* 匹配处理规则:如果存在对应的正则,则按照设定的正则进行特殊匹配 例如 [img[(\\w+)]] 可以匹配
* [img[xxx.jpg]];否则将默认按照首尾一致的原则进行匹配 例如 --(\\w+)-- 可以匹配
* --xxx--,但是所有组装出的正则中不应该在存在()
*
* @param wt
* @param target
*/
private String replace(WikiText wt, String target) {
if (wt.valueCount == -1) {
if (wt.handler == null) // 如果没有对应的处理规则实现则不做处理
return target;
else
return wt.handler.process(target);
}
String regex = currentRegex(wt);
Pattern pattern = Pattern.compile(regex);
for (Matcher matcher = pattern.matcher(target); matcher.find();) {
// 获取当前完全匹配的组
String orginalText = matcher.group();
String newText = "";
if (wt.valueCount == NONE_VALUE) {
newText = wt.text;
} else if (wt.valueCount == SINGLE_VALUE) {
// 目标文本 如 [img[xxx.jpg]]通过这步后获取到xxx.jpg
String targetText = matcher.group(1);
// 拼接新的html的串 即 <img src="$1"> 还原为 <img src="xxx.jpg">
newText = wt.text.replace("$1", targetText);
} else {
// 处理多值问题例如 <font color="$1" attr="$n">$2</font>
for (int i = 1; i <= matcher.groupCount(); i++) {
String targetText = matcher.group(i);
String tmpReg = "{1}quot; + i;
wt.text = newText = wt.text.replace(tmpReg, targetText);
}
}
target = target.replace(orginalText, newText);
}
return target;
}
private String currentRegex(WikiText wt) {
String regex = null;
// 多值情况下需要自定义正则,并且要使用占位符
if (wt.regex != null && !"".equals(wt.regex))
regex = wt.regex;
// 无值时正则本身就是符号
else if (wt.valueCount == 0)
regex = wt.symbol;
// 默认当做单值,则正则为前后一致
else
regex = wt.symbol + "(.+?)" + wt.symbol;
return regex;
}
// --------------------------------------------------------------
/**
* Wiki体管理器
*
* @author tangxiucai
*
*/
private static class WikiTextManager {
private static Set<WikiText> container = new HashSet<WikiText>();
public static synchronized Set<WikiText> getContainer() {
return container;
}
}
/**
* Wiki特殊符号自定义解析接口
* 自定义解析规则需要注意参数为整个需要处理的字符串,有可能被应用了其他规则也可能没有,这取决于规则的应用顺序。
* 通常自定义规则接口实现步骤:①进行匹配操作,只有在匹配成功的情况下对目标串进行处理否则返回原目标串,
* 而不能返回null或空串因为可能导致空指针异常; ②对匹配串进行迭代处理
* 实现示例:
* <code><pre>
* public String process(String target) {
String regex = "--(.+?)--";
if(Pattern.matches(regex, target)){
Pattern pattern = Pattern.compile(regex);
for(Matcher matcher = pattern.matcher(target); matcher.find();){
String findStr = matcher.group();
String includedStr = matcher.group(1);
String newStr = "(已删除:" +includedStr+ ")";
target = target.replaceAll(findStr, newStr);
}
}
return target;
}
*</pre></code>
* @author tangxiucai
*
*/
private interface WikiTextHandler {
/**
* 自定义处理过程,将目标字符串按照自己的解析规则转换成需要的字符串
*
* @param target
* 需要处理的目标字符串
* @return 处理后的字符串
*/
String process(String target);
}
/**
* Wiki体
*
* @author tangxiucai
*
*/
private class WikiText {
/**
* 符号 例如 --表示删除 ----表示横线
*/
public String symbol;
/**
* 对应的html,用$1代表目标串的占位符
*/
public String text;
/**
* 符号含义
*/
public String meaning;
/**
* 符号匹配正则
*/
public String regex;
/**
* 存储占位符个数 -1时说明存在自定义解析接口的实现
*/
public int valueCount;
public WikiTextHandler handler = null;
public WikiText(String symbol, String text, String meaning,
String regex, int valueCount) {
this.symbol = symbol;
this.text = text;
this.meaning = meaning;
this.regex = regex;
this.valueCount = valueCount;
}
public WikiText(String symbol, String meaning, WikiTextHandler handler) {
this.symbol = symbol;
this.meaning = meaning;
this.handler = handler;
this.valueCount = -1;
}
@Override
public int hashCode() {
return this.symbol.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof WikiText))
return false;
WikiText wt = (WikiText) obj;
if (wt.symbol.equals(this.symbol))
return true;
return false;
}
}
}
wiki文本处理引擎
最新推荐文章于 2020-06-22 22:12:49 发布