2
0

utilities.ts 4.9 KB

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