handleElement.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import {
  2. Paragraph,
  3. ParagraphChild,
  4. IPropertiesOptions,
  5. Table,
  6. TextRun
  7. } from "docx"
  8. import docxTitle from "./docxTitle"
  9. import docxText from "./docxText"
  10. import docxList from "./docxList"
  11. import docxTable from "./docxTable"
  12. import docxImage from "./docxImage"
  13. // 全局标签
  14. const TagsList = [
  15. 'h1', // 标题
  16. 'h2', // 章节
  17. 'h3', 'h4', 'h5', 'h6', // 子章节
  18. // 文本标签
  19. 'p', // 段落(自动在前后添加间距)
  20. 'br', // 换行(单标签,插入换行)
  21. 'hr', // 水平线(分隔内容,常用于段落之间)
  22. // 'pre', // 预格式化文本(保留空格和换行,常用于代码块)
  23. 'strong', // 强调重要性(加粗)
  24. 'em', // 强调语气(斜体)
  25. 'b', // 粗体
  26. 'i', // 斜体
  27. 'mark', // 高亮(黄色背景)
  28. 'small', // 小字(字体变小)
  29. 'sub', // 下标
  30. 'sup', // 上标
  31. 'del', // 删除内容(删除线)
  32. 'ins', // 插入内容(下划线)
  33. 'blockquote', // 块引用(长段引用内容,默认缩进)
  34. 'q', // 行内短引用(自动加引号)
  35. 'cite', // 引用来源(常用于引用文章标题或出处)
  36. 'code', // 代码片段(等宽字体)
  37. 'kbd', // 用户输入(表示键盘输入)
  38. 'samp', // 输出结果(表示计算机输出)
  39. 'var', // 变量名(通常斜体)
  40. 'mjx-container', // 数学公式
  41. 'div', // 块 -> 可转换成特殊表格块
  42. 'details', // 描述 -> 可转换成特殊表格块
  43. 'ul', // 无序列表,子项标签<li>
  44. 'ol', // 有序列表,子项标签<li>
  45. 'table', // 表格主体标签
  46. 'img', 'canvas', // 图片
  47. ]
  48. // 可嵌套标签
  49. const NestTagsList = [
  50. // 文本标签
  51. 'p', // 段落(自动在前后添加间距)
  52. 'br', // 换行(单标签,插入换行)
  53. 'hr', // 水平线(分隔内容,常用于段落之间)
  54. // 'pre', // 预格式化文本(保留空格和换行,常用于代码块)
  55. 'strong', // 强调重要性(加粗)
  56. 'em', // 强调语气(斜体)
  57. 'b', // 粗体
  58. 'i', // 斜体
  59. 'mark', // 高亮(黄色背景)
  60. 'small', // 小字(字体变小)
  61. 'sub', // 下标
  62. 'sup', // 上标
  63. 'del', // 删除内容(删除线)
  64. 'ins', // 插入内容(下划线)
  65. 'blockquote', // 块引用(长段引用内容,默认缩进)
  66. 'q', // 行内短引用(自动加引号)
  67. 'cite', // 引用来源(常用于引用文章标题或出处)
  68. 'code', // 代码片段(等宽字体)
  69. 'kbd', // 用户输入(表示键盘输入)
  70. 'samp', // 输出结果(表示计算机输出)
  71. 'var', // 变量名(通常斜体)
  72. 'mjx-container', // 数学公式
  73. 'ul', // 无序列表,子项标签<li>
  74. 'ol', // 有序列表,子项标签<li>
  75. 'table', // 表格主体标签
  76. 'img', 'canvas', // 图片
  77. ]
  78. // 可内嵌标签(段落内部嵌套标签)
  79. const EmbeddedTagsList = [
  80. // 文本标签
  81. 'br', // 换行(单标签,插入换行)
  82. // 'pre', // 预格式化文本(保留空格和换行,常用于代码块)
  83. 'strong', // 强调重要性(加粗)
  84. 'em', // 强调语气(斜体)
  85. 'b', // 粗体
  86. 'i', // 斜体
  87. 'mark', // 高亮(黄色背景)
  88. 'small', // 小字(字体变小)
  89. 'sub', // 下标
  90. 'sup', // 上标
  91. 'del', // 删除内容(删除线)
  92. 'ins', // 插入内容(下划线)
  93. 'blockquote', // 块引用(长段引用内容,默认缩进)
  94. 'q', // 行内短引用(自动加引号)
  95. 'cite', // 引用来源(常用于引用文章标题或出处)
  96. 'code', // 代码片段(等宽字体)
  97. 'kbd', // 用户输入(表示键盘输入)
  98. 'samp', // 输出结果(表示计算机输出)
  99. 'var', // 变量名(通常斜体)
  100. 'mjx-container', // 数学公式
  101. ]
  102. let title: string | undefined = undefined
  103. export function getTitle(): string | undefined {
  104. return title
  105. }
  106. export function getConfig(): Omit<IPropertiesOptions, "sections"> {
  107. return {
  108. ...docxTitle.config,
  109. ...docxText.config,
  110. ...docxList.config,
  111. ...docxTable.config,
  112. ...docxImage.config
  113. }
  114. }
  115. export const handleElement = async (dom: Element): Promise<(Paragraph | Table)[]> => {
  116. const paragraphs: (Paragraph | Table)[] = []
  117. for (const el of dom.querySelectorAll(TagsList.toString())) {
  118. const text = el.textContent?.trim()
  119. if (!text) continue
  120. // 处理标题
  121. if (title === undefined) {
  122. title = docxTitle.handleTitle(el)
  123. }
  124. // 处理章节标题和普通文本内容
  125. const textParagraph = docxText.handleText(el)
  126. if (textParagraph) {
  127. paragraphs.push(textParagraph)
  128. continue
  129. }
  130. // 处理无序和有序列表
  131. const listParagraph = await docxList.handleList(el)
  132. if (listParagraph) {
  133. paragraphs.push(...listParagraph)
  134. continue
  135. }
  136. // 处理表格
  137. const tableParagraph = docxTable.handleTable(el)
  138. if (tableParagraph) {
  139. paragraphs.push(tableParagraph)
  140. continue
  141. }
  142. // 处理图片
  143. const imageParagraph = await docxImage.handleImage(el)
  144. if (imageParagraph) {
  145. paragraphs.push(imageParagraph)
  146. continue
  147. }
  148. console.warn(`${el.tagName} 标签未处理。`)
  149. }
  150. return paragraphs
  151. }
  152. export const handleNestElement = async (dom: Element): Promise<(Paragraph | Table)[]> => {
  153. const paragraphs: (Paragraph | Table)[] = []
  154. for (const el of dom.querySelectorAll(NestTagsList.toString())) {
  155. const text = el.textContent?.trim()
  156. if (!text) continue
  157. // 处理章节标题和普通文本内容
  158. const textParagraph = docxText.handleText(el)
  159. if (textParagraph) {
  160. paragraphs.push(textParagraph)
  161. continue
  162. }
  163. // 处理无序和有序列表
  164. const listParagraph = await docxList.handleList(el)
  165. if (listParagraph) {
  166. paragraphs.push(...listParagraph)
  167. continue
  168. }
  169. // 处理表格
  170. const tableParagraph = docxTable.handleTable(el)
  171. if (tableParagraph) {
  172. paragraphs.push(tableParagraph)
  173. continue
  174. }
  175. // 处理图片
  176. const imageParagraph = await docxImage.handleImage(el)
  177. if (imageParagraph) {
  178. paragraphs.push(imageParagraph)
  179. continue
  180. }
  181. console.warn(`${el.tagName} 标签未处理。`)
  182. }
  183. return paragraphs
  184. }
  185. export const handleEmbeddedElement = (dom: Element): ParagraphChild => {
  186. for (const el of dom.querySelectorAll(EmbeddedTagsList.toString())) {
  187. const text = el.textContent?.trim()
  188. if (!text) continue
  189. // 处理章节标题和普通文本内容
  190. const textParagraphChiled = docxText.handleEmbeddedText(el)
  191. if (textParagraphChiled) {
  192. return textParagraphChiled
  193. }
  194. console.warn(`${el.tagName} 标签未处理。`)
  195. return new TextRun("")
  196. }
  197. }