@amermathsoc/texml-to-html 18.1.0 → 18.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +2 -0
  3. package/lib/elements/abstract.js +1 -0
  4. package/lib/elements/app.js +2 -1
  5. package/lib/elements/attrib.js +2 -17
  6. package/lib/elements/book-meta-json.js +1 -1
  7. package/lib/elements/disp-formula-group.js +7 -0
  8. package/lib/elements/disp-quote.js +6 -3
  9. package/lib/elements/fig.js +7 -2
  10. package/lib/elements/formula.js +1 -2
  11. package/lib/elements/label.js +5 -49
  12. package/lib/elements/notes.js +1 -0
  13. package/lib/elements/ref-list.js +1 -1
  14. package/lib/elements/sec.js +3 -2
  15. package/lib/elements/secheading.js +3 -2
  16. package/lib/elements/statement.js +11 -0
  17. package/lib/elements/subtitle.js +1 -4
  18. package/lib/elements/tag.js +2 -2
  19. package/lib/elements/target.js +3 -6
  20. package/lib/elements/{subject.js → title-group.js} +3 -5
  21. package/lib/head.js +1 -1
  22. package/lib/postProcessing.js +81 -0
  23. package/lib/transformer.js +44 -14
  24. package/package.json +3 -1
  25. package/test/article.xml +40 -33
  26. package/test/book.xml +27 -7
  27. package/test/element-attrib.js +2 -2
  28. package/test/element-disp-quote.js +2 -1
  29. package/test/element-fig-subfig-label.js +2 -1
  30. package/test/element-fn.js +6 -3
  31. package/test/element-formula.js +63 -0
  32. package/test/element-front.js +2 -1
  33. package/test/{element-sec-app-front-matter-part-dedication-title-label.js → element-sec.js} +2 -1
  34. package/test/element-tag.js +5 -1
  35. package/test/element-tex-math.js +64 -0
  36. package/test/helper.js +4 -0
  37. package/test/postProcessing.js +45 -0
  38. package/test/snapshots/article--alttitle.html +121 -0
  39. package/test/snapshots/article--nometa.html +56 -0
  40. package/test/snapshots/article.html +561 -0
  41. package/test/snapshots/book.html +160 -0
  42. package/test/snapshots/texml-tests/LGR.html +104 -0
  43. package/test/snapshots/texml-tests/LGR.xml +82 -0
  44. package/test/snapshots/texml-tests/NLMnote.html +10 -0
  45. package/test/snapshots/texml-tests/NLMnote.xml +12 -0
  46. package/test/snapshots/texml-tests/OT1.html +61 -0
  47. package/test/snapshots/texml-tests/OT1.xml +39 -0
  48. package/test/snapshots/texml-tests/OT1ti.html +61 -0
  49. package/test/snapshots/texml-tests/OT1ti.xml +39 -0
  50. package/test/snapshots/texml-tests/OT1tt.html +60 -0
  51. package/test/snapshots/texml-tests/OT1tt.xml +38 -0
  52. package/test/snapshots/texml-tests/OT2.html +119 -0
  53. package/test/snapshots/texml-tests/OT2.xml +97 -0
  54. package/test/snapshots/texml-tests/OT4.html +68 -0
  55. package/test/snapshots/texml-tests/OT4.xml +46 -0
  56. package/test/snapshots/texml-tests/OT6.html +49 -0
  57. package/test/snapshots/texml-tests/OT6.xml +27 -0
  58. package/test/snapshots/texml-tests/T1.html +44 -0
  59. package/test/snapshots/texml-tests/T1.xml +22 -0
  60. package/test/snapshots/texml-tests/T4.html +48 -0
  61. package/test/snapshots/texml-tests/T4.xml +26 -0
  62. package/test/snapshots/texml-tests/T5.html +45 -0
  63. package/test/snapshots/texml-tests/T5.xml +23 -0
  64. package/test/snapshots/texml-tests/Uchar.html +9 -0
  65. package/test/snapshots/texml-tests/Uchar.xml +11 -0
  66. package/test/snapshots/texml-tests/Ucharcat.html +45 -0
  67. package/test/snapshots/texml-tests/Ucharcat.xml +23 -0
  68. package/test/snapshots/texml-tests/accent.html +54 -0
  69. package/test/snapshots/texml-tests/accent.xml +32 -0
  70. package/test/snapshots/texml-tests/algorithm.html +55 -0
  71. package/test/snapshots/texml-tests/algorithm.xml +35 -0
  72. package/test/snapshots/texml-tests/algorithmic.html +706 -0
  73. package/test/snapshots/texml-tests/algorithmic.xml +712 -0
  74. package/test/snapshots/texml-tests/algpseudocode.html +520 -0
  75. package/test/snapshots/texml-tests/algpseudocode.xml +538 -0
  76. package/test/snapshots/texml-tests/ams_measure.html +46 -0
  77. package/test/snapshots/texml-tests/ams_measure.xml +24 -0
  78. package/test/snapshots/texml-tests/amsart.html +66 -0
  79. package/test/snapshots/texml-tests/amsart.xml +39 -0
  80. package/test/snapshots/texml-tests/amscyr.html +53 -0
  81. package/test/snapshots/texml-tests/amscyr.xml +35 -0
  82. package/test/snapshots/texml-tests/amsfonts.html +41 -0
  83. package/test/snapshots/texml-tests/amsfonts.xml +21 -0
  84. package/test/snapshots/texml-tests/amsrefs.html +82 -0
  85. package/test/snapshots/texml-tests/amsrefs.xml +87 -0
  86. package/test/snapshots/texml-tests/amsthm.html +83 -0
  87. package/test/snapshots/texml-tests/amsthm.xml +61 -0
  88. package/test/snapshots/texml-tests/amsviet.html +42 -0
  89. package/test/snapshots/texml-tests/amsviet.xml +20 -0
  90. package/test/snapshots/texml-tests/appendix.html +69 -0
  91. package/test/snapshots/texml-tests/appendix.xml +43 -0
  92. package/test/snapshots/texml-tests/array.html +58 -0
  93. package/test/snapshots/texml-tests/array.xml +36 -0
  94. package/test/snapshots/texml-tests/arydshln.html +69 -0
  95. package/test/snapshots/texml-tests/arydshln.xml +47 -0
  96. package/test/snapshots/texml-tests/autoref.html +76 -0
  97. package/test/snapshots/texml-tests/autoref.xml +79 -0
  98. package/test/snapshots/texml-tests/begincsname.html +46 -0
  99. package/test/snapshots/texml-tests/begincsname.xml +24 -0
  100. package/test/snapshots/texml-tests/boldline.html +93 -0
  101. package/test/snapshots/texml-tests/boldline.xml +71 -0
  102. package/test/snapshots/texml-tests/book-app.html +22 -0
  103. package/test/snapshots/texml-tests/book-app.xml +26 -0
  104. package/test/snapshots/texml-tests/booktabs.html +7 -0
  105. package/test/snapshots/texml-tests/booktabs.xml +9 -0
  106. package/test/snapshots/texml-tests/boxes.html +54 -0
  107. package/test/snapshots/texml-tests/boxes.xml +32 -0
  108. package/test/snapshots/texml-tests/cases.html +13 -0
  109. package/test/snapshots/texml-tests/cases.xml +19 -0
  110. package/test/snapshots/texml-tests/cite.html +48 -0
  111. package/test/snapshots/texml-tests/cite.xml +40 -0
  112. package/test/snapshots/texml-tests/citesort.html +62 -0
  113. package/test/snapshots/texml-tests/citesort.xml +74 -0
  114. package/test/snapshots/texml-tests/cleveref.html +25 -0
  115. package/test/snapshots/texml-tests/cleveref.xml +28 -0
  116. package/test/snapshots/texml-tests/codes.html +7 -0
  117. package/test/snapshots/texml-tests/codes.xml +9 -0
  118. package/test/snapshots/texml-tests/colortbl.html +46 -0
  119. package/test/snapshots/texml-tests/colortbl.xml +24 -0
  120. package/test/snapshots/texml-tests/combinetoks.html +49 -0
  121. package/test/snapshots/texml-tests/combinetoks.xml +27 -0
  122. package/test/snapshots/texml-tests/constants.html +45 -0
  123. package/test/snapshots/texml-tests/constants.xml +23 -0
  124. package/test/snapshots/texml-tests/csstring.html +44 -0
  125. package/test/snapshots/texml-tests/csstring.xml +22 -0
  126. package/test/snapshots/texml-tests/detokenize.html +56 -0
  127. package/test/snapshots/texml-tests/detokenize.xml +34 -0
  128. package/test/snapshots/texml-tests/diacritics.html +41 -0
  129. package/test/snapshots/texml-tests/diacritics.xml +19 -0
  130. package/test/snapshots/texml-tests/dimexpr.html +42 -0
  131. package/test/snapshots/texml-tests/dimexpr.xml +20 -0
  132. package/test/snapshots/texml-tests/doi.html +6 -0
  133. package/test/snapshots/texml-tests/doi.xml +8 -0
  134. package/test/snapshots/texml-tests/drm.html +12 -0
  135. package/test/snapshots/texml-tests/drm.xml +76 -0
  136. package/test/snapshots/texml-tests/dz.html +25 -0
  137. package/test/snapshots/texml-tests/dz.xml +27 -0
  138. package/test/snapshots/texml-tests/edef.html +8 -0
  139. package/test/snapshots/texml-tests/edef.xml +10 -0
  140. package/test/snapshots/texml-tests/empheq.html +9 -0
  141. package/test/snapshots/texml-tests/empheq.xml +13 -0
  142. package/test/snapshots/texml-tests/enclose.html +27 -0
  143. package/test/snapshots/texml-tests/enclose.xml +45 -0
  144. package/test/snapshots/texml-tests/everyeof.html +42 -0
  145. package/test/snapshots/texml-tests/everyeof.xml +20 -0
  146. package/test/snapshots/texml-tests/expanded.html +44 -0
  147. package/test/snapshots/texml-tests/expanded.xml +22 -0
  148. package/test/snapshots/texml-tests/footnote.html +28 -0
  149. package/test/snapshots/texml-tests/footnote.xml +59 -0
  150. package/test/snapshots/texml-tests/frac.html +15 -0
  151. package/test/snapshots/texml-tests/frac.xml +21 -0
  152. package/test/snapshots/texml-tests/framebox.html +43 -0
  153. package/test/snapshots/texml-tests/framebox.xml +23 -0
  154. package/test/snapshots/texml-tests/glueexpr.html +42 -0
  155. package/test/snapshots/texml-tests/glueexpr.xml +20 -0
  156. package/test/snapshots/texml-tests/graphics.html +9 -0
  157. package/test/snapshots/texml-tests/graphics.xml +13 -0
  158. package/test/snapshots/texml-tests/gsm_l.html +35 -0
  159. package/test/snapshots/texml-tests/gsm_l.xml +71 -0
  160. package/test/snapshots/texml-tests/halign.html +78 -0
  161. package/test/snapshots/texml-tests/halign.xml +56 -0
  162. package/test/snapshots/texml-tests/hbox.html +11 -0
  163. package/test/snapshots/texml-tests/hbox.xml +17 -0
  164. package/test/snapshots/texml-tests/hello.html +38 -0
  165. package/test/snapshots/texml-tests/hello.xml +16 -0
  166. package/test/snapshots/texml-tests/hhline.html +101 -0
  167. package/test/snapshots/texml-tests/hhline.xml +79 -0
  168. package/test/snapshots/texml-tests/hline.html +40 -0
  169. package/test/snapshots/texml-tests/hline.xml +18 -0
  170. package/test/snapshots/texml-tests/href.html +6 -0
  171. package/test/snapshots/texml-tests/href.xml +8 -0
  172. package/test/snapshots/texml-tests/hyperams.html +43 -0
  173. package/test/snapshots/texml-tests/hyperams.xml +21 -0
  174. package/test/snapshots/texml-tests/hyperref.html +10 -0
  175. package/test/snapshots/texml-tests/hyperref.xml +12 -0
  176. package/test/snapshots/texml-tests/ifcondition.html +39 -0
  177. package/test/snapshots/texml-tests/ifcondition.xml +17 -0
  178. package/test/snapshots/texml-tests/ifcsname.html +40 -0
  179. package/test/snapshots/texml-tests/ifcsname.xml +18 -0
  180. package/test/snapshots/texml-tests/ifdefined.html +40 -0
  181. package/test/snapshots/texml-tests/ifdefined.xml +18 -0
  182. package/test/snapshots/texml-tests/ifdim.html +40 -0
  183. package/test/snapshots/texml-tests/ifdim.xml +18 -0
  184. package/test/snapshots/texml-tests/ifnum.html +40 -0
  185. package/test/snapshots/texml-tests/ifnum.xml +18 -0
  186. package/test/snapshots/texml-tests/ifprimitive.html +48 -0
  187. package/test/snapshots/texml-tests/ifprimitive.xml +26 -0
  188. package/test/snapshots/texml-tests/immediateassigned.html +44 -0
  189. package/test/snapshots/texml-tests/immediateassigned.xml +22 -0
  190. package/test/snapshots/texml-tests/immediateassignment.html +44 -0
  191. package/test/snapshots/texml-tests/immediateassignment.xml +22 -0
  192. package/test/snapshots/texml-tests/lastbox.html +40 -0
  193. package/test/snapshots/texml-tests/lastbox.xml +18 -0
  194. package/test/snapshots/texml-tests/lastnamedcs.html +40 -0
  195. package/test/snapshots/texml-tests/lastnamedcs.xml +18 -0
  196. package/test/snapshots/texml-tests/let.html +43 -0
  197. package/test/snapshots/texml-tests/let.xml +21 -0
  198. package/test/snapshots/texml-tests/letcharcode.html +41 -0
  199. package/test/snapshots/texml-tests/letcharcode.xml +19 -0
  200. package/test/snapshots/texml-tests/ligatures.html +69 -0
  201. package/test/snapshots/texml-tests/ligatures.xml +47 -0
  202. package/test/snapshots/texml-tests/list.html +12 -0
  203. package/test/snapshots/texml-tests/list.xml +14 -0
  204. package/test/snapshots/texml-tests/listings.html +46 -0
  205. package/test/snapshots/texml-tests/listings.xml +24 -0
  206. package/test/snapshots/texml-tests/longtable.html +61 -0
  207. package/test/snapshots/texml-tests/longtable.xml +39 -0
  208. package/test/snapshots/texml-tests/ltxcodes.html +1330 -0
  209. package/test/snapshots/texml-tests/ltxcodes.xml +1332 -0
  210. package/test/snapshots/texml-tests/ltxthm.html +6 -0
  211. package/test/snapshots/texml-tests/ltxthm.xml +8 -0
  212. package/test/snapshots/texml-tests/makecell.html +40 -0
  213. package/test/snapshots/texml-tests/makecell.xml +18 -0
  214. package/test/snapshots/texml-tests/maketitle.html +82 -0
  215. package/test/snapshots/texml-tests/maketitle.xml +67 -0
  216. package/test/snapshots/texml-tests/math.html +35 -0
  217. package/test/snapshots/texml-tests/math.xml +47 -0
  218. package/test/snapshots/texml-tests/mathscinet.html +41 -0
  219. package/test/snapshots/texml-tests/mathscinet.xml +19 -0
  220. package/test/snapshots/texml-tests/meaning.html +44 -0
  221. package/test/snapshots/texml-tests/meaning.xml +22 -0
  222. package/test/snapshots/texml-tests/metadata.html +125 -0
  223. package/test/snapshots/texml-tests/metadata.xml +137 -0
  224. package/test/snapshots/texml-tests/missingfile.html +3 -0
  225. package/test/snapshots/texml-tests/missingfile.xml +5 -0
  226. package/test/snapshots/texml-tests/muexpr.html +42 -0
  227. package/test/snapshots/texml-tests/muexpr.xml +20 -0
  228. package/test/snapshots/texml-tests/multicolumn.html +47 -0
  229. package/test/snapshots/texml-tests/multicolumn.xml +25 -0
  230. package/test/snapshots/texml-tests/multirow.html +47 -0
  231. package/test/snapshots/texml-tests/multirow.xml +25 -0
  232. package/test/snapshots/texml-tests/multirowcell.html +50 -0
  233. package/test/snapshots/texml-tests/multirowcell.xml +28 -0
  234. package/test/snapshots/texml-tests/multline.html +71 -0
  235. package/test/snapshots/texml-tests/multline.xml +55 -0
  236. package/test/snapshots/texml-tests/nameref.html +45 -0
  237. package/test/snapshots/texml-tests/nameref.xml +23 -0
  238. package/test/snapshots/texml-tests/noexpand.html +44 -0
  239. package/test/snapshots/texml-tests/noexpand.xml +22 -0
  240. package/test/snapshots/texml-tests/noindent.html +39 -0
  241. package/test/snapshots/texml-tests/noindent.xml +17 -0
  242. package/test/snapshots/texml-tests/null_cs.html +4 -0
  243. package/test/snapshots/texml-tests/null_cs.xml +6 -0
  244. package/test/snapshots/texml-tests/numexpr.html +48 -0
  245. package/test/snapshots/texml-tests/numexpr.xml +26 -0
  246. package/test/snapshots/texml-tests/parshape.html +41 -0
  247. package/test/snapshots/texml-tests/parshape.xml +19 -0
  248. package/test/snapshots/texml-tests/protected.html +47 -0
  249. package/test/snapshots/texml-tests/protected.xml +25 -0
  250. package/test/snapshots/texml-tests/quote.html +43 -0
  251. package/test/snapshots/texml-tests/quote.xml +21 -0
  252. package/test/snapshots/texml-tests/read.html +13 -0
  253. package/test/snapshots/texml-tests/read.xml +15 -0
  254. package/test/snapshots/texml-tests/refrange.html +126 -0
  255. package/test/snapshots/texml-tests/refrange.xml +110 -0
  256. package/test/snapshots/texml-tests/scantokens.html +45 -0
  257. package/test/snapshots/texml-tests/scantokens.xml +23 -0
  258. package/test/snapshots/texml-tests/secmeta.html +27 -0
  259. package/test/snapshots/texml-tests/secmeta.xml +39 -0
  260. package/test/snapshots/texml-tests/section.html +86 -0
  261. package/test/snapshots/texml-tests/section.xml +64 -0
  262. package/test/snapshots/texml-tests/showonlyrefs.html +95 -0
  263. package/test/snapshots/texml-tests/showonlyrefs.xml +85 -0
  264. package/test/snapshots/texml-tests/smash.html +41 -0
  265. package/test/snapshots/texml-tests/smash.xml +21 -0
  266. package/test/snapshots/texml-tests/strcmp.html +41 -0
  267. package/test/snapshots/texml-tests/strcmp.xml +19 -0
  268. package/test/snapshots/texml-tests/string.html +44 -0
  269. package/test/snapshots/texml-tests/string.xml +22 -0
  270. package/test/snapshots/texml-tests/sub_sup.html +50 -0
  271. package/test/snapshots/texml-tests/sub_sup.xml +28 -0
  272. package/test/snapshots/texml-tests/subcaption.html +54 -0
  273. package/test/snapshots/texml-tests/subcaption.xml +32 -0
  274. package/test/snapshots/texml-tests/subfig.html +45 -0
  275. package/test/snapshots/texml-tests/subfig.xml +23 -0
  276. package/test/snapshots/texml-tests/subfigure.html +44 -0
  277. package/test/snapshots/texml-tests/subfigure.xml +22 -0
  278. package/test/snapshots/texml-tests/tableofcontents.html +42 -0
  279. package/test/snapshots/texml-tests/tableofcontents.xml +95 -0
  280. package/test/snapshots/texml-tests/tabular.html +47 -0
  281. package/test/snapshots/texml-tests/tabular.xml +25 -0
  282. package/test/snapshots/texml-tests/tag.html +16 -0
  283. package/test/snapshots/texml-tests/tag.xml +20 -0
  284. package/test/snapshots/texml-tests/tcolorbox.html +43 -0
  285. package/test/snapshots/texml-tests/tcolorbox.xml +21 -0
  286. package/test/snapshots/texml-tests/textequation.html +55 -0
  287. package/test/snapshots/texml-tests/textequation.xml +33 -0
  288. package/test/snapshots/texml-tests/thm-restate.html +94 -0
  289. package/test/snapshots/texml-tests/thm-restate.xml +86 -0
  290. package/test/snapshots/texml-tests/tracingnodes.html +38 -0
  291. package/test/snapshots/texml-tests/tracingnodes.xml +16 -0
  292. package/test/snapshots/texml-tests/unexpanded.html +44 -0
  293. package/test/snapshots/texml-tests/unexpanded.xml +22 -0
  294. package/test/snapshots/texml-tests/unless.html +40 -0
  295. package/test/snapshots/texml-tests/unless.xml +18 -0
  296. package/test/snapshots/texml-tests/upgreek.html +79 -0
  297. package/test/snapshots/texml-tests/upgreek.xml +57 -0
  298. package/test/snapshots/texml-tests/uri.html +12 -0
  299. package/test/snapshots/texml-tests/uri.xml +14 -0
  300. package/test/snapshots/texml-tests/url.html +41 -0
  301. package/test/snapshots/texml-tests/url.xml +19 -0
  302. package/test/snapshots/texml-tests/vlist.html +48 -0
  303. package/test/snapshots/texml-tests/vlist.xml +28 -0
  304. package/test/snapshots/texml-tests/xcolor.html +50 -0
  305. package/test/snapshots/texml-tests/xcolor.xml +28 -0
  306. package/test/snapshots/updateTexmlSnapshots.js +14 -0
  307. package/texml-to-html.js +2 -2
  308. package/lib/elements/article-title.js +0 -26
  309. package/lib/elements/book-title.js +0 -26
  310. package/lib/elements/meta-name.js +0 -29
  311. package/lib/elements/meta-value.js +0 -27
  312. package/lib/elements/subj-group.js +0 -29
  313. package/lib/hacks.js +0 -43
  314. package/test/element-inline-formula-disp-formula-tex-math.js +0 -98
  315. package/test/hacks.js +0 -39
package/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [18.2.0](https://github.com/AmerMathSoc/texml-to-html/compare/v18.1.0...v18.2.0) (2025-02-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * **attrib.js:** add data-ams-doc ([70fa67c](https://github.com/AmerMathSoc/texml-to-html/commit/70fa67ca59b92d1ff18900d430b107ceef7f2d9c)), closes [#462](https://github.com/AmerMathSoc/texml-to-html/issues/462)
11
+ * replace applyHacks() with fixContentModel() ([0cb4ae7](https://github.com/AmerMathSoc/texml-to-html/commit/0cb4ae7fbcdc4006b51d43b8cd0398dd4cbb2b30)), closes [#473](https://github.com/AmerMathSoc/texml-to-html/issues/473)
12
+ * revise tag and target in text equations ([d7244f6](https://github.com/AmerMathSoc/texml-to-html/commit/d7244f6a8212336754a112657b9e14bb9e0e20a9)), closes [#429](https://github.com/AmerMathSoc/texml-to-html/issues/429)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **app.js:** remove unused ternary path ([f459df1](https://github.com/AmerMathSoc/texml-to-html/commit/f459df12b6f4582138e001cb8c7ae0ddf5125ecd)), closes [#470](https://github.com/AmerMathSoc/texml-to-html/issues/470)
18
+ * **disp-quote.js:** remove outdated workaround ([390482a](https://github.com/AmerMathSoc/texml-to-html/commit/390482a82bd84762e3b8d1ec5191b38c50e29d02)), closes [#472](https://github.com/AmerMathSoc/texml-to-html/issues/472)
19
+ * **disp-quote:** footer is last child ([ee46ad7](https://github.com/AmerMathSoc/texml-to-html/commit/ee46ad7a326ac029ca03adbfe63da1d41bbc2798)), closes [#457](https://github.com/AmerMathSoc/texml-to-html/issues/457) [#463](https://github.com/AmerMathSoc/texml-to-html/issues/463)
20
+ * **formula.js:** remove whitespace clean-up ([6f673f4](https://github.com/AmerMathSoc/texml-to-html/commit/6f673f49e146e08b4647a12122f30ddac88f9e1b)), closes [#424](https://github.com/AmerMathSoc/texml-to-html/issues/424)
21
+ * **formula.js:** trim inner whitespace ([2ae7130](https://github.com/AmerMathSoc/texml-to-html/commit/2ae7130ef1d1d27f4e26a46686c7ec211936d0ec)), closes [#471](https://github.com/AmerMathSoc/texml-to-html/issues/471)
22
+ * remove book-title.js ([57610a8](https://github.com/AmerMathSoc/texml-to-html/commit/57610a8a86ba8e3409d78fcc0dfbe813f9d68b4d)), closes [#254](https://github.com/AmerMathSoc/texml-to-html/issues/254) [#448](https://github.com/AmerMathSoc/texml-to-html/issues/448)
23
+ * remove meta-name.js and meta-value.js ([2bbc8e0](https://github.com/AmerMathSoc/texml-to-html/commit/2bbc8e05b75b72d3f60968d9c891050b16935cde)), closes [#254](https://github.com/AmerMathSoc/texml-to-html/issues/254) [#448](https://github.com/AmerMathSoc/texml-to-html/issues/448)
24
+ * remove subject-group.js and subject.js ([9fefa46](https://github.com/AmerMathSoc/texml-to-html/commit/9fefa4616d0ebe2068e1dd0d1db56a83fae3ed8b)), closes [#254](https://github.com/AmerMathSoc/texml-to-html/issues/254) [#448](https://github.com/AmerMathSoc/texml-to-html/issues/448)
25
+ * revise label/title/etc handling ([804904a](https://github.com/AmerMathSoc/texml-to-html/commit/804904a4bf21878e302bc328a4bbdbee0bbe4f90)), closes [#467](https://github.com/AmerMathSoc/texml-to-html/issues/467) [#452](https://github.com/AmerMathSoc/texml-to-html/issues/452)
26
+ * **sec.js:** workaround nested book-app ([1ec8680](https://github.com/AmerMathSoc/texml-to-html/commit/1ec86805829838288453e8a2ff4140c11a79bc02)), closes [#460](https://github.com/AmerMathSoc/texml-to-html/issues/460)
27
+
5
28
  ## [18.1.0](https://github.com/AmerMathSoc/texml-to-html/compare/v18.0.0...v18.1.0) (2024-09-09)
6
29
 
7
30
 
package/README.md CHANGED
@@ -118,6 +118,7 @@ Beyond HTML element and attributes, texml-to-html stores data in custom `data-*`
118
118
  - container is inside data-ams-doc="math block" elements
119
119
  - ams-html uses these to generate the math panel DTs for equations
120
120
  - app-group [from book-app-group]
121
+ - attribution [from attrib]
121
122
  - data-ams-doc-contrib
122
123
  - {@content-type} [expected: "authors", "editors", "translators", "contributors"]
123
124
  - {@contrib-type} [expected: "author", "editor", "translator", "contributor"]
@@ -247,6 +248,7 @@ The following provide a list from the reverse point of view.
247
248
  - @notes-type => @data-ams-content-type (and role=dedication for dedications)
248
249
  - use cases: dedication (articles), article and section notes (NOTI only), drm notice & epub note (books)
249
250
  - toc-entry@specific-use => data-ams-ref
251
+ - attrib => data-ams-doc="attribution"
250
252
  - attributes
251
253
  - @disp-level => data-ams-doc-level [data-ams-doc-level is also added to some elements that lack disp-level]
252
254
  - @content-type => data-ams-content-type
@@ -30,5 +30,6 @@ export default function (htmlParentNode, xmlnode) {
30
30
  });
31
31
  mapAttributes(section, xmlnode);
32
32
  htmlParentNode.appendChild(section);
33
+ this.createHeading(section, xmlnode);
33
34
  this.passThrough(section, xmlnode);
34
35
  };
@@ -24,12 +24,13 @@ import mapAttributes from '../helpers/mapAttributes.js';
24
24
  export default function (htmlParentNode, xmlnode) {
25
25
  const section = this.createNode('section', '', {
26
26
  role: 'doc-appendix',
27
- 'data-ams-doc-level': this.isBook ? 0 : 1,
27
+ 'data-ams-doc-level': 1,
28
28
  });
29
29
  const titleChild = xmlnode.querySelector('title');
30
30
  if (titleChild && titleChild.textContent.startsWith('Acknowledg'))
31
31
  section.setAttribute('role', 'doc-acknowledgments');
32
32
  htmlParentNode.appendChild(section);
33
33
  mapAttributes(section, xmlnode);
34
+ this.createHeading(section, xmlnode);
34
35
  this.passThrough(section, xmlnode);
35
36
  };
@@ -20,22 +20,7 @@
20
20
  * @param {Element} xmlnode
21
21
  */
22
22
  export default function (htmlParentNode, xmlnode) {
23
- let actualParent = htmlParentNode;
24
- if (xmlnode.parentNode.tagName === 'disp-quote') {
25
- const footer = this.createNode('footer');
26
- htmlParentNode.appendChild(footer);
27
- actualParent = footer;
28
- }
29
- if (
30
- xmlnode.parentNode.tagName === 'fig' ||
31
- xmlnode.parentNode.tagName === 'fig-group'
32
- ) {
33
- // NOTE there should be a figcaption element (cf. caption())
34
- // NOTE so far this only occurs in mbk103, clrm067 to attribute graphics in figures
35
- actualParent = htmlParentNode.querySelector(':scope>figcaption');
36
- }
37
- const span = this.createNode('span');
38
- actualParent.insertAdjacentText('beforeend', ' '); // NOTE needed inside fig-caption
39
- actualParent.appendChild(span);
23
+ const span = this.createNode('span', '', { 'data-ams-doc': 'attribution' });
24
+ htmlParentNode.appendChild(span);
40
25
  this.passThrough(span, xmlnode);
41
26
  };
@@ -115,7 +115,7 @@ export function generateBookJson(bookMetaNode) {
115
115
  })
116
116
 
117
117
  // book-title-group
118
- const title = bookMetaNode.querySelector('book-title-group > book-title'); // NOTE title might contain math-mode (no use case yet)
118
+ const title = bookMetaNode.querySelector('book-title-group > book-title'); // NOTE title might contain complex markup (no use case yet; however e.g. surv279 has math-as-unicode). See also head.js
119
119
  const subtitle = bookMetaNode.querySelector('book-title-group > subtitle'); // NOTE subtitle might contain math-mode (no use case yet)
120
120
  const alttitle = bookMetaNode.querySelector('book-title-group > alt-title') || title;
121
121
  bookMetaJson.book.title = this.passthroughIntoHTMLString(title);
@@ -26,5 +26,12 @@ export default function (htmlParentNode, xmlnode) {
26
26
  id: xmlnode.id,
27
27
  });
28
28
  htmlParentNode.appendChild(figure);
29
+ const label = xmlnode.querySelector(':scope>label');
30
+ if (label) {
31
+ const figcaption = this.createNode('figcaption');
32
+ figure.appendChild(figcaption);
33
+ this.redirectRecurseTheDom(figcaption, label);
34
+ }
35
+
29
36
  this.passThrough(figure, xmlnode);
30
37
  };
@@ -26,8 +26,11 @@ export default function (htmlParentNode, xmlnode) {
26
26
  if (contentType === 'epigraph')
27
27
  blockquote.setAttribute('role', 'doc-epigraph');
28
28
  else blockquote.setAttribute('data-ams-style', specificUse);
29
- if (htmlParentNode.tagName === 'P')
30
- htmlParentNode.insertAdjacentElement('afterend', blockquote);
31
- else htmlParentNode.appendChild(blockquote);
29
+ htmlParentNode.appendChild(blockquote);
30
+ // handle attrib
31
+ const attrib = xmlnode.querySelector(':scope>attrib');
32
+ const footer = this.createNode('footer');
33
+ if (attrib) this.redirectRecurseTheDom(footer, attrib);
32
34
  this.passThrough(blockquote, xmlnode);
35
+ if (attrib) blockquote.appendChild(footer);
33
36
  };
@@ -31,8 +31,9 @@ export default function (htmlParentNode, xmlnode) {
31
31
 
32
32
  const label = xmlnode.querySelector(':scope>label');
33
33
  const caption = xmlnode.querySelector(':scope>caption');
34
-
35
- if (label || caption) {
34
+ const attrib = xmlnode.querySelector(':scope>attrib');
35
+
36
+ if (label || caption || attrib) {
36
37
  const figcaption = this.createNode('figcaption');
37
38
  figure.appendChild(figcaption);
38
39
  if (label) {
@@ -44,6 +45,10 @@ export default function (htmlParentNode, xmlnode) {
44
45
  if (caption) {
45
46
  this.passThrough(figcaption, caption);
46
47
  }
48
+ if (attrib) {
49
+ figcaption.insertAdjacentText('beforeend', ' '); //NOTE figcaptioninline content
50
+ this.redirectRecurseTheDom(figcaption, attrib);
51
+ }
47
52
  }
48
53
  // process remaining children
49
54
  this.passThrough(figure, xmlnode);
@@ -46,7 +46,6 @@ export default function (htmlParentNode, xmlnode) {
46
46
  const tagContainer = `<span hidden data-ams-doc="tags"></span>`; //NOTE we store copies of tags for easier re-use downstream (cf. tags.js) except for text equations
47
47
  if (hasLinkedTag) span.insertAdjacentHTML('afterbegin', tagContainer)
48
48
  this.passThrough(span, xmlnode);
49
- // NOTE we (sometimes?) get extra whitespace from childnodes; needs test
50
49
  const text = span.innerHTML;
51
- span.innerHTML = text.replace(/[ \n]+/g, ' ');
50
+ span.innerHTML = text.trim(); // NOTE: texml (sometimes) adds whitespace around the tex-math child; this causes undesired whitespace (e.g., theorem titles like `($x$)` becoming `( $x$ )`) TODO: revisit after AmerMathSoc/texml#234 is closed
52
51
  };
@@ -14,58 +14,14 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import getParentLevel from '../helpers/getParentLevel.js';
18
-
19
17
  /**
20
- * label and title elements. If both are present, expects label+title (not title+label)
18
+ * label and title elements, usually redirected
21
19
  * @param {HTMLElement} htmlParentNode
22
20
  * @param {Element} xmlnode
23
21
  */
24
22
  export default function (htmlParentNode, xmlnode) {
25
- // CASE label followed by a title -- we skip (and pull in the label later on when processing title)
26
- if (xmlnode.nextElementSibling?.tagName === 'title') return;
27
- // CASE empty label
28
- if (xmlnode.tagName === 'label' && xmlnode.innerHTML.trim() === '') return;
29
-
30
- // complex cases
31
-
32
- // Decide container (h* or figcaption; wrapping header for subtitles)
33
- const isStatement = xmlnode.parentNode.tagName === 'statement';
34
- const isDispFormulaGroup = xmlnode.parentNode.tagName === 'disp-formula-group';
35
- const level = getParentLevel(htmlParentNode) + 1;
36
- const container = (isStatement || isDispFormulaGroup) ? this.createNode('figcaption', '') : this.createNode(`h${level}`, '');
37
- htmlParentNode.appendChild(container);
38
-
39
- // subtitle handling (assumes container is not figcaption)
40
- const subtitleSibling = xmlnode.parentNode.querySelector(':scope>subtitle');
41
- if (subtitleSibling && subtitleSibling.innerHTML.trim() !== '') {
42
- // wrap heading in header
43
- const header = this.createNode('header');
44
- htmlParentNode.appendChild(header);
45
- header.appendChild(container);
46
- // recurse subtitle
47
- this.recurseTheDom(header, subtitleSibling);
48
- }
49
-
50
- // Pull in label (if title+label and we're processing title)
51
- const previousSibling = xmlnode.previousElementSibling;
52
- if (previousSibling?.tagName === 'label' && previousSibling.innerHTML.trim() !== '') {
53
- const labelSpan = this.createNode('span', '', { 'data-ams-doc': 'label' });
54
- container.appendChild(labelSpan);
55
- this.passThrough(labelSpan, previousSibling);
56
- labelSpan.insertAdjacentText('afterend', ' '); // NOTE: adding (in HTML meaningful) space after label & before title to avoid them from smashing together.
57
- }
58
-
59
- // CASE Book
60
- const altTitle = xmlnode.parentNode.querySelector(':scope>alt-title');
61
- const hasAltTitle = altTitle && altTitle.innerHTML !== xmlnode.innerHTML;
62
- if (this.isBook && hasAltTitle) {
63
- container.setAttribute('data-ams-doc-alttitle', container.textContent + altTitle.innerHTML); // NOTE assumes previousSibling handled first
64
- }
65
-
66
- // add main node and recurse
67
- const actualSpan = this.createNode('span', '', { 'data-ams-doc': xmlnode.tagName });
68
- container.appendChild(actualSpan);
69
- // NOTE: no space after title/label if there's only one. Downstream might insert some (e.g., with inlined headings).
70
- this.passThrough(actualSpan, xmlnode);
23
+ if (xmlnode.innerHTML.trim() === '') return;
24
+ const span = this.createNode('span', '', { 'data-ams-doc': xmlnode.tagName });
25
+ htmlParentNode.appendChild(span);
26
+ this.passThrough(span, xmlnode);
71
27
  };
@@ -32,5 +32,6 @@ export default function (htmlParentNode, xmlnode) {
32
32
  htmlParentNode.appendChild(section);
33
33
  if (this.isBook) section.setAttribute('data-ams-doc-level', '0');
34
34
 
35
+ this.createHeading(section, xmlnode);
35
36
  this.passThrough(section, xmlnode);
36
37
  };
@@ -36,6 +36,7 @@ export default function (htmlParentNode, xmlnode) {
36
36
  });
37
37
  mapAttributes(section, xmlnode);
38
38
  htmlParentNode.appendChild(section);
39
+ this.createHeading(section, xmlnode);
39
40
  if (!isNestedRefList) {
40
41
  section.setAttribute('role', 'doc-bibliography');
41
42
  }
@@ -43,7 +44,6 @@ export default function (htmlParentNode, xmlnode) {
43
44
  this.passThrough(section, xmlnode);
44
45
  return;
45
46
  }
46
- this.recurseTheDom(section, xmlnode.querySelector('title'));
47
47
  const dl = this.createNode('dl', '');
48
48
  section.appendChild(dl);
49
49
  xmlnode.querySelectorAll('ref').forEach(this.recurseTheDom.bind(null, dl));
@@ -53,7 +53,7 @@ export default function (htmlParentNode, xmlnode) {
53
53
  });
54
54
  htmlParentNode.appendChild(section);
55
55
 
56
- if (xmlnode.hasAttribute('style')) section.setAttribute('data-ams-style', xmlnode.getAttribute('style'));
56
+ if (xmlnode.hasAttribute('style')) section.setAttribute('data-ams-style', xmlnode.getAttribute('style'));
57
57
 
58
58
  if (specificUse === 'part') {
59
59
  section.setAttribute('role', 'doc-part');
@@ -82,7 +82,8 @@ export default function (htmlParentNode, xmlnode) {
82
82
  if (tagName === 'book-app-group') {
83
83
  section.setAttribute('data-ams-doc', 'app-group');
84
84
  }
85
- if (tagName === 'book-app') section.setAttribute('role', 'doc-appendix');
85
+ if (tagName === 'book-app' && !xmlnode.parentNode.closest('book-app')) section.setAttribute('role', 'doc-appendix'); // TODO: revisit after AmerMathSoc/texml#223
86
86
 
87
+ this.createHeading(section, xmlnode);
87
88
  this.passThrough(section, xmlnode);
88
89
  };
@@ -25,16 +25,17 @@ export default function (htmlParentNode, xmlnode) {
25
25
  const parentLevel = htmlParentNode.closest('[data-ams-doc-level]')?.getAttribute('data-ams-doc-level') || 5;
26
26
  const span = this.createNode('span', '', {
27
27
  'data-ams-doc': 'secheading',
28
- 'data-ams-doc-level': parseInt(parentLevel)+1,
28
+ 'data-ams-doc-level': parseInt(parentLevel) + 1,
29
29
  });
30
30
  mapAttributes(span, xmlnode);
31
31
 
32
32
  htmlParentNode.appendChild(span);
33
+ // NOTE: secheadings are re-written to headings downstream so we keep them flat here
33
34
  const label = xmlnode.querySelector('label');
34
35
  const title = xmlnode.querySelector('title');
35
36
  if (label) {
36
37
  this.passThrough(span, label);
37
- if (title) span.insertAdjacentText('beforeend', ' '); //TODO: cf. & unify with label.js
38
+ if (title) span.insertAdjacentText('beforeend', ' ');
38
39
  }
39
40
  if (!title) return;
40
41
  this.passThrough(span, title);
@@ -27,5 +27,16 @@ export default function (htmlParentNode, xmlnode) {
27
27
  });
28
28
  mapAttributes(figure, xmlnode);
29
29
  htmlParentNode.appendChild(figure);
30
+
31
+ const label = xmlnode.querySelector(':scope>label:not(:empty)');
32
+ const title = xmlnode.querySelector(':scope>title:not(:empty)');
33
+ if (label || title) {
34
+ const figcaption = this.createNode('figcaption');
35
+ figure.appendChild(figcaption);
36
+ this.redirectRecurseTheDom(figcaption, label);
37
+ if (label && title) figcaption.insertAdjacentText('beforeend', ' ');
38
+ this.redirectRecurseTheDom(figcaption, title);
39
+ }
40
+
30
41
  this.passThrough(figure, xmlnode);
31
42
  };
@@ -14,15 +14,12 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import getParentLevel from '../helpers/getParentLevel.js';
18
-
19
17
  /**
20
- * subtitle element
18
+ * subtitle element, usually redirected
21
19
  * @param {HTMLElement} htmlParentNode
22
20
  * @param {Element} xmlnode
23
21
  */
24
22
  export default function (htmlParentNode, xmlnode) {
25
- // NOTE the subtitle is also touched in label.js (which creates a header as htmlParent)
26
23
  const p = this.createNode('p', '', { 'data-ams-doc': 'subtitle' });
27
24
  htmlParentNode.appendChild(p);
28
25
  this.passThrough(p, xmlnode);
@@ -37,11 +37,11 @@ export default function (htmlParentNode, xmlnode) {
37
37
  }
38
38
  // rarely, it appears in "text equations" (cf. formula.js, target.js)
39
39
  else if (xmlnode.closest('disp-formula[content-type="text"]')) {
40
- const span = this.createNode('span', '', { 'data-ams-doc': 'label', id: xmlnode.parentNode.id }); // NOTE: tag should always have a <target> parent with an ID.
40
+ const span = this.createNode('span', '', { 'data-ams-doc': 'label'});
41
41
  if (xmlnode.getAttribute('parens') === 'yes') span.insertAdjacentText('afterbegin', '(')
42
42
  this.passThrough(span, xmlnode);
43
43
  if (xmlnode.getAttribute('parens') === 'yes') span.insertAdjacentText('beforeend', ')')
44
- htmlParentNode.prepend(span);
44
+ htmlParentNode.prepend(span); //NOTE: we prepend to get left-side tags even when there is no target; but cf. AmerMathSoc/texml#232
45
45
  }
46
46
  // tag extraction
47
47
  // if some tag in the equation is linked, we store all tags in a special element in the HTML parent
@@ -27,13 +27,10 @@ export default function (htmlParentNode, xmlnode) {
27
27
  node2macro.apply(this, [htmlParentNode, xmlnode, `cssId{${xmlnode.id}}`, false]);
28
28
  return;
29
29
  }
30
- // NOTE: inside a "text equation" we pass it through; the tag child will pick up the ID.
31
- if (xmlnode.parentNode.tagName === 'disp-formula' && xmlnode.parentNode.getAttribute('content-type') === 'text') {
32
- this.passThrough(htmlParentNode, xmlnode);
33
- return;
34
- }
35
30
  const span = this.createNode('span');
36
- htmlParentNode.appendChild(span);
31
+ const isTextEquation = (xmlnode.parentNode.tagName === 'disp-formula' && xmlnode.parentNode.getAttribute('content-type') === 'text');
32
+ if (isTextEquation) htmlParentNode.prepend(span); // NOTE: inside a "text equation" we prepend to get a left-side label, but cf. also AmerMathSoc/texml#232
33
+ else htmlParentNode.appendChild(span);
37
34
  mapAttributes(span, xmlnode);
38
35
  this.passThrough(span, xmlnode);
39
36
  };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Copyright (c) 2023 American Mathematical Society
2
+ * Copyright (c) 2025 American Mathematical Society
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -15,12 +15,10 @@
15
15
  */
16
16
 
17
17
  /**
18
- * subject element
18
+ * title-group element mapped to h1
19
19
  * @param {HTMLElement} htmlParentNode
20
20
  * @param {Element} xmlnode
21
21
  */
22
22
  export default function (htmlParentNode, xmlnode) {
23
- const dd = this.createNode('dd');
24
- htmlParentNode.appendChild(dd);
25
- this.passThrough(dd, xmlnode);
23
+ this.createHeading(htmlParentNode, xmlnode);
26
24
  };
package/lib/head.js CHANGED
@@ -27,7 +27,7 @@ export const setHead = (xmldoc, htmldoc) => {
27
27
  xmldoc.querySelector('front>article-meta>title-group>alt-title') ||
28
28
  xmldoc.querySelector(
29
29
  'book-meta>book-title-group>book-title, front>article-meta>title-group>article-title'
30
- );
30
+ );// NOTE title might contain complex markup (no use case yet; however e.g. surv279 has math-as-unicode). See also book-meta-json.js
31
31
  htmldoc.title = xmlTitle ? xmlTitle.textContent : 'AMS Publication';
32
32
 
33
33
  const root = xmldoc.querySelector('article, book');
@@ -0,0 +1,81 @@
1
+ /*!
2
+ * Copyright (c) 2025 American Mathematical Society
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ // From https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#phrasing_content
18
+ // Note: 'a', 'del', 'ins', 'link', 'map', 'meta' have additional constraints that we ignore since they shouldn't occur in our content
19
+ const phrasingContentTags = ['abbr', 'audio', 'b', 'bdo', 'br', 'button', 'canvas', 'cite', 'code', 'data', 'datalist', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 'input', 'kbd', 'label', 'mark', 'math', 'meter', 'noscript', 'object', 'output', 'picture', 'progress', 'q', 'ruby', 'samp', 'script', 'select', 'small', 'span', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'u', 'var', 'video', 'wbr', 'a', 'del', 'ins', 'link', 'map', 'meta']
20
+
21
+ /**
22
+ * Checks if node is an element that is not phrasing content.
23
+ * @param {Node} node
24
+ * @returns Boolean
25
+ */
26
+ const isProperFlow = node =>
27
+ node.nodeType === 1
28
+ && !phrasingContentTags.includes(node.tagName.toLowerCase())
29
+ && !node.tagName.includes('-');
30
+
31
+ /**
32
+ * Helper to remove whitespace-only elements
33
+ * @param {HTMLElement} node
34
+ */
35
+ const removeIfEmpty = node => {
36
+ if (node.innerHTML.trim() === '') node.remove();
37
+ }
38
+
39
+ /**
40
+ * Split paragraph node into multiple nodes if it contains non-phrasing content.
41
+ * @param {HTMLElement} node
42
+ */
43
+ const splitAtNonPhrasing = node => {
44
+ const document = node.ownerDocument;
45
+ const tagName = node.tagName.toLowerCase();
46
+ const childNodes = [...node.childNodes];
47
+ const properFlowChild = childNodes.find(isProperFlow);
48
+ if (!properFlowChild) return;
49
+ let currentNode = node;
50
+ let index = 0
51
+ while (index < childNodes.length) {
52
+ const child = childNodes[index];
53
+ if (isProperFlow(child)) {
54
+ currentNode.insertAdjacentElement('afterend', child);
55
+ }
56
+ else {
57
+ currentNode.appendChild(child);
58
+ }
59
+ // continuation
60
+ index++;
61
+ if (!childNodes[index]) break;
62
+ if (isProperFlow(child) && !isProperFlow(childNodes[index])) {
63
+ const newNode = document.createElement(tagName);
64
+ child.insertAdjacentElement('afterend', newNode);
65
+ removeIfEmpty(currentNode);
66
+ currentNode = newNode;
67
+ }
68
+ else if (isProperFlow(child)) {
69
+ currentNode = child;
70
+ }
71
+ }
72
+ removeIfEmpty(currentNode);
73
+ }
74
+
75
+ /**
76
+ * Wrapper around fixes for discrepancies between XML and HTML content models
77
+ * @param {Document} document
78
+ */
79
+ export const fixContentModel = document => {
80
+ document.querySelectorAll('p').forEach(splitAtNonPhrasing);
81
+ }
@@ -17,7 +17,6 @@
17
17
  import Front from './elements/front.js';
18
18
  import Preface from './elements/preface.js';
19
19
  import BookMeta from './elements/book-meta.js';
20
- import BookTitle from './elements/book-title.js';
21
20
  import Subtitle from './elements/subtitle.js';
22
21
  import Email from './elements/email.js';
23
22
  import Xref from './elements/xref.js';
@@ -28,13 +27,10 @@ import MixedCitation from './elements/mixed-citation.js';
28
27
  import Label from './elements/label.js';
29
28
  import StringName from './elements/string-name.js';
30
29
  import Article from './elements/article.js';
31
- import ArticleTitle from './elements/article-title.js';
32
30
  import KwdGroup from './elements/kwd-group.js';
33
31
  import Kwd from './elements/kwd.js';
34
32
  import CompoundKwd from './elements/compound-kwd.js';
35
33
  import FundingGroup from './elements/funding-group.js';
36
- import MetaName from './elements/meta-name.js';
37
- import MetaValue from './elements/meta-value.js';
38
34
  import Notes from './elements/notes.js';
39
35
  import Abstract from './elements/abstract.js';
40
36
  import Sec from './elements/sec.js';
@@ -69,8 +65,6 @@ import Underline from './elements/underline.js';
69
65
  import DispFormulaGroup from './elements/disp-formula-group.js';
70
66
  import SimpleTabbing from './elements/simpletabbing.js';
71
67
  import Line from './elements/line.js';
72
- import SubjGroup from './elements/subj-group.js';
73
- import Subject from './elements/subject.js';
74
68
  import Monospace from './elements/monospace.js';
75
69
  import Roman from './elements/roman.js';
76
70
  import SansSerif from './elements/sans-serif.js';
@@ -81,9 +75,11 @@ import Xrefgroup from './elements/xref-group.js';
81
75
  import TexMath from './elements/tex-math.js';
82
76
  import CiteGroup from './elements/cite-group.js';
83
77
  import CiteDetail from './elements/cite-detail.js';
78
+ import TitleGroup from './elements/title-group.js';
84
79
 
85
80
  import copyElement from './helpers/copyElement.js';
86
81
  import { extractContribGroups } from './helpers/extractContribGroups.js';
82
+ import getParentLevel from './helpers/getParentLevel.js';
87
83
 
88
84
  /**
89
85
  * The Transformer class
@@ -144,10 +140,10 @@ export class Transformer {
144
140
  'permissions',
145
141
  'back',
146
142
  'alternatives',
147
- 'title-group',
148
143
  'app-group',
149
144
  'book-title-group',
150
145
  'private-char',
146
+ 'article-title' // NOTE: maybe map to label (like title)
151
147
  ].forEach(mapTag.bind(null, this.passThrough));
152
148
  }
153
149
 
@@ -181,7 +177,18 @@ export class Transformer {
181
177
  };
182
178
 
183
179
  /**
184
- * Pass-through function (for xmlnode that are we "unwrap")
180
+ * Function to "redirect" the recursion.
181
+ * @param {Node} htmlParentNode - HTML "parent" for xmlnode content
182
+ * @param {Node} xmlnode - XML node to recurse with a different parent and detach afterwards
183
+ * @returns {undefined}
184
+ */
185
+ redirectRecurseTheDom = (htmlParentNode, xmlnode) => {
186
+ this.recurseTheDom(htmlParentNode, xmlnode);
187
+ xmlnode?.remove(); // NOTE: falsy handling; matches recurseTheDom
188
+ };
189
+
190
+ /**
191
+ * Pass-through function (for xmlnode that we "unwrap")
185
192
  * @param {Node} htmlParentNode - HTML "parent" for xmlnode content
186
193
  * @param {Node} xmlnode - XML node to unwrap
187
194
  * @returns {undefined}
@@ -201,6 +208,34 @@ export class Transformer {
201
208
  this.passThrough(span, xmlnode);
202
209
  return span.innerHTML.trim();
203
210
  }
211
+
212
+ createHeading = (section, xmlnode) => { // create heading structure
213
+ const label = xmlnode.querySelector(':scope>label:not(:empty)');
214
+ const title = xmlnode.querySelector(':scope>title:not(:empty), :scope>article-title:not(:empty)');
215
+ const subtitle = xmlnode.querySelector(':scope>subtitle:not(:empty)');
216
+ const altTitle = xmlnode.querySelector(':scope>alt-title:not(:empty)');
217
+
218
+ const level = getParentLevel(section) + 1 || 1;
219
+
220
+ const heading = this.createNode(`h${level}`);
221
+ if (label || title) section.appendChild(heading);
222
+
223
+ this.redirectRecurseTheDom(heading, label);
224
+
225
+ if (label&&title) heading.insertAdjacentText('beforeend', ' '); // NOTE: adding (in HTML meaningful) space after label & before title to avoid them from smashing together.
226
+
227
+ if (this.isBook && altTitle) heading.setAttribute('data-ams-doc-alttitle', heading.textContent + altTitle.innerHTML); // NOTE placed between label and title handling so that the result includes label content (but cf. #464)
228
+
229
+ this.redirectRecurseTheDom(heading, title);
230
+
231
+ if (subtitle) {
232
+ const header = this.createNode('header');
233
+ section.appendChild(header);
234
+ header.appendChild(heading);
235
+ this.redirectRecurseTheDom(header, subtitle);
236
+ }
237
+
238
+ }
204
239
 
205
240
  // extract contrib-groups into json data
206
241
  extractContribGroups = extractContribGroups.bind(this);
@@ -212,7 +247,6 @@ export class Transformer {
212
247
  front = Front.bind(this)
213
248
  preface = Preface.bind(this)
214
249
  'book-meta' = BookMeta.bind(this)
215
- 'book-title' = BookTitle.bind(this)
216
250
  subtitle = Subtitle.bind(this)
217
251
  email = Email.bind(this)
218
252
  xref = Xref.bind(this)
@@ -223,13 +257,10 @@ export class Transformer {
223
257
  label = Label.bind(this)
224
258
  'string-name' = StringName.bind(this)
225
259
  article = Article.bind(this)
226
- 'article-title' = ArticleTitle.bind(this)
227
260
  'kwd-group' = KwdGroup.bind(this)
228
261
  kwd = Kwd.bind(this)
229
262
  'compound-kwd' = CompoundKwd.bind(this)
230
263
  'funding-group' = FundingGroup.bind(this)
231
- 'meta-name' = MetaName.bind(this)
232
- 'meta-value' = MetaValue.bind(this)
233
264
  notes = Notes.bind(this)
234
265
  abstract = Abstract.bind(this)
235
266
  sec = Sec.bind(this)
@@ -264,8 +295,6 @@ export class Transformer {
264
295
  'disp-formula-group' = DispFormulaGroup.bind(this)
265
296
  simpletabbing = SimpleTabbing.bind(this)
266
297
  line = Line.bind(this)
267
- 'subj-group' = SubjGroup.bind(this)
268
- subject = Subject.bind(this)
269
298
  monospace = Monospace.bind(this)
270
299
  roman = Roman.bind(this)
271
300
  'sans-serif' = SansSerif.bind(this)
@@ -275,6 +304,7 @@ export class Transformer {
275
304
  'tex-math' = TexMath.bind(this)
276
305
  'cite-group' = CiteGroup.bind(this)
277
306
  'cite-detail' = CiteDetail.bind(this)
307
+ 'title-group' = TitleGroup.bind(this)
278
308
 
279
309
  // one-off reuse of imported elements
280
310
  // NOTE if RHS gets re-used more than once, use mapTag in the constructor