|
@@ -0,0 +1,162 @@
|
|
|
+package cn.com.qmth.examcloud.support.test;
|
|
|
+
|
|
|
+import org.apache.commons.lang.StringEscapeUtils;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.jsoup.Jsoup;
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
+import org.jsoup.nodes.Node;
|
|
|
+import org.jsoup.nodes.TextNode;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+public class Context {
|
|
|
+
|
|
|
+ private static final Map<String, String> TEXT_PARAM_MAP = new HashMap<>();
|
|
|
+
|
|
|
+ static {
|
|
|
+ TEXT_PARAM_MAP.put("b", "bold");
|
|
|
+ TEXT_PARAM_MAP.put("i", "italic");
|
|
|
+ TEXT_PARAM_MAP.put("strong", "bold");
|
|
|
+ TEXT_PARAM_MAP.put("em", "italic");
|
|
|
+ TEXT_PARAM_MAP.put("u", "underline");
|
|
|
+ TEXT_PARAM_MAP.put("sup", "sup");
|
|
|
+ TEXT_PARAM_MAP.put("sub", "sub");
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Section> sections;
|
|
|
+
|
|
|
+ private Section currentSection;
|
|
|
+
|
|
|
+ private Map<String, Object> currentTextParam;
|
|
|
+
|
|
|
+ public Context() {
|
|
|
+ this.sections = new ArrayList<>();
|
|
|
+ this.currentTextParam = new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Section> process(String input) {
|
|
|
+ Element body = Jsoup.parseBodyFragment(StringUtils.trimToEmpty(input)).body();
|
|
|
+ switchSection();
|
|
|
+ for (Node child : body.childNodes()) {
|
|
|
+ parseNode(child);
|
|
|
+ }
|
|
|
+ return sections;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void parseNode(Node node) {
|
|
|
+ if (node instanceof TextNode) {
|
|
|
+ TextNode textNode = (TextNode) node;
|
|
|
+ parseText(textNode.text());
|
|
|
+ } else if (node instanceof Element) {
|
|
|
+ Element element = (Element) node;
|
|
|
+ onElementStart(element);
|
|
|
+ for (Node child : element.childNodes()) {
|
|
|
+ parseNode(child);
|
|
|
+ }
|
|
|
+ onElementEnd(element);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void parseText(String text) {
|
|
|
+ Block block = new Block(BlockType.TEXT);
|
|
|
+ block.setValue(StringEscapeUtils.unescapeHtml(text));
|
|
|
+ block.getParam().putAll(currentTextParam);
|
|
|
+ addBlock(block);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void parseImage(Element element) {
|
|
|
+ Block block = new Block(BlockType.IMAGE);
|
|
|
+
|
|
|
+ String src = element.attr("src");
|
|
|
+ block.setValue(src);
|
|
|
+
|
|
|
+ Map<String, Object> param = new HashMap<>();
|
|
|
+ String height = element.attr("height");
|
|
|
+ String width = element.attr("width");
|
|
|
+ param.put("width", height);
|
|
|
+ param.put("height", width);
|
|
|
+ block.getParam().putAll(param);
|
|
|
+
|
|
|
+ addBlock(block);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void parseAudio(Element element) {
|
|
|
+ //todo 此处为题库特殊处理,待确认
|
|
|
+ String id = element.attr("id");
|
|
|
+ String name = element.attr("name");
|
|
|
+ if (StringUtils.isNotEmpty(id) && StringUtils.isNotEmpty(name)) {
|
|
|
+ Block block = new Block(BlockType.AUDIO);
|
|
|
+ block.setPlayTime(1);
|
|
|
+ block.setValue(element.attr("url"));
|
|
|
+ addBlock(block);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void onElementStart(Element element) {
|
|
|
+ String name = element.nodeName().toLowerCase();
|
|
|
+ switch (name) {
|
|
|
+ case "div":
|
|
|
+ case "p":
|
|
|
+ switchSection();
|
|
|
+ break;
|
|
|
+ case "br":
|
|
|
+ finishSection();
|
|
|
+ break;
|
|
|
+ case "img":
|
|
|
+ parseImage(element);
|
|
|
+ break;
|
|
|
+ case "audio":// TODO
|
|
|
+ case "a":// TODO
|
|
|
+ parseAudio(element);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ String style = TEXT_PARAM_MAP.get(name);
|
|
|
+ if (style != null) {
|
|
|
+ currentTextParam.put(style, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void onElementEnd(Element element) {
|
|
|
+ String name = element.nodeName().toLowerCase();
|
|
|
+ switch (name) {
|
|
|
+ case "div":
|
|
|
+ case "p":
|
|
|
+ case "span":
|
|
|
+ finishSection();
|
|
|
+ break;
|
|
|
+ case "img":// TODO
|
|
|
+ case "audio":// TODO
|
|
|
+ case "a":// TODO
|
|
|
+// finishSection();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ String style = TEXT_PARAM_MAP.get(name);
|
|
|
+ if (style != null) {
|
|
|
+ currentTextParam.remove(style);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addBlock(Block block) {
|
|
|
+ if (currentSection == null) {
|
|
|
+ switchSection();
|
|
|
+ }
|
|
|
+ currentSection.addBlock(block);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void finishSection() {
|
|
|
+ currentSection = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void switchSection() {
|
|
|
+ Section section = new Section();
|
|
|
+ sections.add(section);
|
|
|
+ currentSection = section;
|
|
|
+ currentTextParam.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|