utilities.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import React from "react";
  2. import MdTpl from "./MdTpl";
  3. import { WdCtl } from "./Wd";
  4. import { roman_to_my, my_to_roman } from "../code/my";
  5. import { roman_to_si } from "../code/si";
  6. import { roman_to_thai } from "../code/thai";
  7. import { roman_to_taitham } from "../code/tai-tham";
  8. import ParserError from "../general/ParserError";
  9. export type TCodeConvertor =
  10. | "none"
  11. | "roman"
  12. | "roman_to_my"
  13. | "my_to_roman"
  14. | "roman_to_thai"
  15. | "roman_to_taitham"
  16. | "roman_to_si";
  17. export function XmlToReact(
  18. text: string,
  19. wordWidget: boolean = false,
  20. convertor?: TCodeConvertor
  21. ): React.ReactNode[] | undefined {
  22. //console.log("html string:", text);
  23. const parser = new DOMParser();
  24. const xmlDoc = parser.parseFromString(`<body>${text}</body>`, "text/html");
  25. const x = xmlDoc.documentElement;
  26. //console.log("解析成功", x);
  27. return convert(x.getElementsByTagName("body")[0], wordWidget, convertor);
  28. function getAttr(node: ChildNode, key: number): object {
  29. const ele = node as Element;
  30. const attr = ele.attributes;
  31. //console.log("attr", attr);
  32. const output: any = { key: key };
  33. for (let i = 0; i < attr.length; i++) {
  34. if (attr[i].nodeType === 2) {
  35. const key: string = attr[i].nodeName;
  36. if (key !== "style") {
  37. if (key === "class") {
  38. output["className"] = attr[i].nodeValue;
  39. } else {
  40. output[key] = attr[i].nodeValue;
  41. }
  42. } else {
  43. //TODO 把css style 转换为react style
  44. }
  45. }
  46. }
  47. return output;
  48. }
  49. function convert(
  50. node: ChildNode,
  51. wordWidget: boolean = false,
  52. convertor?: TCodeConvertor
  53. ): React.ReactNode[] | undefined {
  54. const output: React.ReactNode[] = [];
  55. for (let i = 0; i < node.childNodes.length; i++) {
  56. const value = node.childNodes[i];
  57. //console.log(value.nodeName, value.nodeType, value.nodeValue);
  58. switch (value.nodeType) {
  59. case 1: //element node
  60. const tagName = value.nodeName.toLowerCase();
  61. //console.log("tag", value.nodeName, tagName);
  62. switch (tagName) {
  63. case "parsererror":
  64. output.push(
  65. React.createElement(
  66. ParserError,
  67. getAttr(value, i),
  68. convert(value, wordWidget, convertor)
  69. )
  70. );
  71. break;
  72. case "mdtpl":
  73. output.push(
  74. React.createElement(
  75. MdTpl,
  76. getAttr(value, i),
  77. convert(value, wordWidget, convertor)
  78. )
  79. );
  80. break;
  81. case "param":
  82. output.push(
  83. React.createElement(
  84. "span",
  85. getAttr(value, i),
  86. convert(value, wordWidget, convertor)
  87. )
  88. );
  89. break;
  90. default:
  91. try {
  92. output.push(
  93. React.createElement(
  94. tagName,
  95. getAttr(value, i),
  96. convert(value, wordWidget, convertor)
  97. )
  98. );
  99. } catch (error) {
  100. console.log("ParserError", tagName);
  101. output.push(React.createElement(ParserError, { key: i }, []));
  102. }
  103. break;
  104. }
  105. break;
  106. case 2: //attribute node
  107. return [];
  108. case 3: //text node
  109. let textValue = value.nodeValue ? value.nodeValue : undefined;
  110. //编码转换
  111. if (typeof convertor !== "undefined" && textValue !== null) {
  112. switch (convertor) {
  113. case "roman_to_my":
  114. textValue = roman_to_my(textValue);
  115. break;
  116. case "my_to_roman":
  117. textValue = my_to_roman(textValue);
  118. break;
  119. case "roman_to_si":
  120. textValue = roman_to_si(textValue);
  121. break;
  122. case "roman_to_thai":
  123. textValue = roman_to_thai(textValue);
  124. break;
  125. case "roman_to_taitham":
  126. textValue = roman_to_taitham(textValue);
  127. break;
  128. }
  129. }
  130. if (wordWidget) {
  131. //将单词按照空格拆开。用组件包裹
  132. const wordList = textValue?.split(" ");
  133. const wordWidget = wordList?.map((word, id) => {
  134. const prop: any = { key: id, text: word };
  135. return React.createElement(WdCtl, prop);
  136. });
  137. output.push(wordWidget);
  138. } else {
  139. output.push(textValue);
  140. }
  141. break;
  142. case 8:
  143. return [];
  144. case 9:
  145. return [];
  146. }
  147. }
  148. if (output.length > 0) {
  149. return output;
  150. } else {
  151. return undefined;
  152. }
  153. }
  154. }