@elastic/isomer-sdk 0.1.0 → 0.3.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 (288) hide show
  1. package/NOTICE.txt +0 -286
  2. package/README.md +13 -2
  3. package/THIRD_PARTY_LICENSES.md +1 -885
  4. package/dist/author/authored_fields.d.ts +93 -18
  5. package/dist/author/authored_fields.d.ts.map +1 -1
  6. package/dist/author/authored_fields.js +63 -43
  7. package/dist/author/authored_fields.js.map +1 -1
  8. package/dist/author/authoring_input.d.ts +7 -0
  9. package/dist/author/authoring_input.d.ts.map +1 -0
  10. package/dist/author/authoring_input.js +66 -0
  11. package/dist/author/authoring_input.js.map +1 -0
  12. package/dist/author/authoring_model.d.ts +33 -0
  13. package/dist/author/authoring_model.d.ts.map +1 -0
  14. package/dist/author/authoring_model.js +142 -0
  15. package/dist/author/authoring_model.js.map +1 -0
  16. package/dist/author/declarations.d.ts +13 -0
  17. package/dist/author/declarations.d.ts.map +1 -0
  18. package/dist/author/declarations.js +288 -0
  19. package/dist/author/declarations.js.map +1 -0
  20. package/dist/author/index.d.ts +4 -1
  21. package/dist/author/index.d.ts.map +1 -1
  22. package/dist/author/index.js +4 -1
  23. package/dist/author/index.js.map +1 -1
  24. package/dist/author/jsx_shim.d.ts +50 -30
  25. package/dist/author/jsx_shim.d.ts.map +1 -1
  26. package/dist/author/jsx_shim.js +146 -138
  27. package/dist/author/jsx_shim.js.map +1 -1
  28. package/dist/author/print_jsx.d.ts +19 -0
  29. package/dist/author/print_jsx.d.ts.map +1 -0
  30. package/dist/author/print_jsx.js +372 -0
  31. package/dist/author/print_jsx.js.map +1 -0
  32. package/dist/author/prompt.d.ts +2 -2
  33. package/dist/author/prompt.d.ts.map +1 -1
  34. package/dist/author/prompt.js +7 -2
  35. package/dist/author/prompt.js.map +1 -1
  36. package/dist/author/schema_to_typescript.d.ts +37 -0
  37. package/dist/author/schema_to_typescript.d.ts.map +1 -0
  38. package/dist/author/schema_to_typescript.js +289 -0
  39. package/dist/author/schema_to_typescript.js.map +1 -0
  40. package/dist/cjs/author/authored_fields.js +68 -47
  41. package/dist/cjs/author/authored_fields.js.map +1 -1
  42. package/dist/cjs/author/authoring_input.js +70 -0
  43. package/dist/cjs/author/authoring_input.js.map +1 -0
  44. package/dist/cjs/author/authoring_model.js +149 -0
  45. package/dist/cjs/author/authoring_model.js.map +1 -0
  46. package/dist/cjs/author/declarations.js +292 -0
  47. package/dist/cjs/author/declarations.js.map +1 -0
  48. package/dist/cjs/author/index.js +10 -1
  49. package/dist/cjs/author/index.js.map +1 -1
  50. package/dist/cjs/author/jsx_shim.js +148 -140
  51. package/dist/cjs/author/jsx_shim.js.map +1 -1
  52. package/dist/cjs/author/print_jsx.js +378 -0
  53. package/dist/cjs/author/print_jsx.js.map +1 -0
  54. package/dist/cjs/author/prompt.js +7 -2
  55. package/dist/cjs/author/prompt.js.map +1 -1
  56. package/dist/cjs/author/schema_to_typescript.js +298 -0
  57. package/dist/cjs/author/schema_to_typescript.js.map +1 -0
  58. package/dist/cjs/composition/body_node_base.js +11 -4
  59. package/dist/cjs/composition/body_node_base.js.map +1 -1
  60. package/dist/cjs/composition/error.js +2 -0
  61. package/dist/cjs/composition/error.js.map +1 -1
  62. package/dist/cjs/composition/index.js +2 -1
  63. package/dist/cjs/composition/index.js.map +1 -1
  64. package/dist/cjs/composition/structured_value.js.map +1 -1
  65. package/dist/cjs/define/frame.js +2 -3
  66. package/dist/cjs/define/frame.js.map +1 -1
  67. package/dist/cjs/define/index.js +7 -1
  68. package/dist/cjs/define/index.js.map +1 -1
  69. package/dist/cjs/define/primitive_example.js +26 -0
  70. package/dist/cjs/define/primitive_example.js.map +1 -0
  71. package/dist/cjs/define/primitive_icon.js +17 -0
  72. package/dist/cjs/define/primitive_icon.js.map +1 -0
  73. package/dist/cjs/define/primitive_module.js +24 -7
  74. package/dist/cjs/define/primitive_module.js.map +1 -1
  75. package/dist/cjs/define/slack_assets.js.map +1 -1
  76. package/dist/cjs/entries/index.js +8 -2
  77. package/dist/cjs/entries/index.js.map +1 -1
  78. package/dist/cjs/entries/markdown.js +2 -1
  79. package/dist/cjs/entries/markdown.js.map +1 -1
  80. package/dist/cjs/entries/slack.js +1 -2
  81. package/dist/cjs/entries/slack.js.map +1 -1
  82. package/dist/cjs/pack/capabilities.js +17 -11
  83. package/dist/cjs/pack/capabilities.js.map +1 -1
  84. package/dist/cjs/pack/compose.js +4 -1
  85. package/dist/cjs/pack/compose.js.map +1 -1
  86. package/dist/cjs/pack/index.js +2 -1
  87. package/dist/cjs/pack/index.js.map +1 -1
  88. package/dist/cjs/pack/primitive_pack.js +27 -5
  89. package/dist/cjs/pack/primitive_pack.js.map +1 -1
  90. package/dist/cjs/render/anchors.js +1 -1
  91. package/dist/cjs/render/anchors.js.map +1 -1
  92. package/dist/cjs/render/format_number.js +2 -1
  93. package/dist/cjs/render/format_number.js.map +1 -1
  94. package/dist/cjs/render/html/envelope.js +12 -6
  95. package/dist/cjs/render/html/envelope.js.map +1 -1
  96. package/dist/cjs/render/layout_check.js.map +1 -1
  97. package/dist/cjs/render/markdown/builder.js +18 -8
  98. package/dist/cjs/render/markdown/builder.js.map +1 -1
  99. package/dist/cjs/render/markdown/format.js +70 -30
  100. package/dist/cjs/render/markdown/format.js.map +1 -1
  101. package/dist/cjs/render/markdown/host_tags.js +67 -0
  102. package/dist/cjs/render/markdown/host_tags.js.map +1 -0
  103. package/dist/cjs/render/markdown/index.js +3 -1
  104. package/dist/cjs/render/markdown/index.js.map +1 -1
  105. package/dist/cjs/render/markdown/split.js +325 -0
  106. package/dist/cjs/render/markdown/split.js.map +1 -0
  107. package/dist/cjs/render/primitive_dispatch.js +11 -25
  108. package/dist/cjs/render/primitive_dispatch.js.map +1 -1
  109. package/dist/cjs/render/react/content.js +3 -1
  110. package/dist/cjs/render/react/content.js.map +1 -1
  111. package/dist/cjs/render/slack/format.js +1 -601
  112. package/dist/cjs/render/slack/format.js.map +1 -1
  113. package/dist/cjs/render/slack/index.js +1 -2
  114. package/dist/cjs/render/slack/index.js.map +1 -1
  115. package/dist/cjs/render/slack/markdown_content.js +172 -115
  116. package/dist/cjs/render/slack/markdown_content.js.map +1 -1
  117. package/dist/cjs/testing/conformance.js +40 -24
  118. package/dist/cjs/testing/conformance.js.map +1 -1
  119. package/dist/cjs/testing/icon.js +248 -0
  120. package/dist/cjs/testing/icon.js.map +1 -0
  121. package/dist/cjs/testing/index.js +3 -1
  122. package/dist/cjs/testing/index.js.map +1 -1
  123. package/dist/cjs/testing/registration.js +5 -3
  124. package/dist/cjs/testing/registration.js.map +1 -1
  125. package/dist/cjs/validate/authoring_schema.js +17 -1
  126. package/dist/cjs/validate/authoring_schema.js.map +1 -1
  127. package/dist/cjs/validate/index.js +2 -1
  128. package/dist/cjs/validate/index.js.map +1 -1
  129. package/dist/cjs/validate/json_schema.js +10 -3
  130. package/dist/cjs/validate/json_schema.js.map +1 -1
  131. package/dist/cjs/validate/url.js +2 -1
  132. package/dist/cjs/validate/url.js.map +1 -1
  133. package/dist/cjs/validate/validation.js +2 -45
  134. package/dist/cjs/validate/validation.js.map +1 -1
  135. package/dist/composition/body_node_base.d.ts +7 -6
  136. package/dist/composition/body_node_base.d.ts.map +1 -1
  137. package/dist/composition/body_node_base.js +10 -3
  138. package/dist/composition/body_node_base.js.map +1 -1
  139. package/dist/composition/error.d.ts +2 -0
  140. package/dist/composition/error.d.ts.map +1 -1
  141. package/dist/composition/error.js +2 -0
  142. package/dist/composition/error.js.map +1 -1
  143. package/dist/composition/index.d.ts +1 -1
  144. package/dist/composition/index.d.ts.map +1 -1
  145. package/dist/composition/index.js +1 -1
  146. package/dist/composition/index.js.map +1 -1
  147. package/dist/composition/structured_value.d.ts +3 -3
  148. package/dist/composition/structured_value.d.ts.map +1 -1
  149. package/dist/composition/structured_value.js.map +1 -1
  150. package/dist/define/frame.d.ts +9 -20
  151. package/dist/define/frame.d.ts.map +1 -1
  152. package/dist/define/frame.js +2 -3
  153. package/dist/define/frame.js.map +1 -1
  154. package/dist/define/index.d.ts +3 -1
  155. package/dist/define/index.d.ts.map +1 -1
  156. package/dist/define/index.js +3 -1
  157. package/dist/define/index.js.map +1 -1
  158. package/dist/define/primitive_example.d.ts +30 -0
  159. package/dist/define/primitive_example.d.ts.map +1 -0
  160. package/dist/define/primitive_example.js +21 -0
  161. package/dist/define/primitive_example.js.map +1 -0
  162. package/dist/define/primitive_icon.d.ts +11 -0
  163. package/dist/define/primitive_icon.d.ts.map +1 -0
  164. package/dist/define/primitive_icon.js +14 -0
  165. package/dist/define/primitive_icon.js.map +1 -0
  166. package/dist/define/primitive_module.d.ts +45 -24
  167. package/dist/define/primitive_module.d.ts.map +1 -1
  168. package/dist/define/primitive_module.js +24 -7
  169. package/dist/define/primitive_module.js.map +1 -1
  170. package/dist/define/slack_assets.d.ts +1 -1
  171. package/dist/define/slack_assets.d.ts.map +1 -1
  172. package/dist/define/slack_assets.js.map +1 -1
  173. package/dist/entries/index.d.ts +3 -3
  174. package/dist/entries/index.d.ts.map +1 -1
  175. package/dist/entries/index.js +3 -3
  176. package/dist/entries/index.js.map +1 -1
  177. package/dist/entries/markdown.d.ts +1 -1
  178. package/dist/entries/markdown.d.ts.map +1 -1
  179. package/dist/entries/markdown.js +1 -1
  180. package/dist/entries/markdown.js.map +1 -1
  181. package/dist/entries/slack.d.ts +1 -1
  182. package/dist/entries/slack.d.ts.map +1 -1
  183. package/dist/entries/slack.js +1 -1
  184. package/dist/entries/slack.js.map +1 -1
  185. package/dist/pack/capabilities.d.ts +24 -10
  186. package/dist/pack/capabilities.d.ts.map +1 -1
  187. package/dist/pack/capabilities.js +17 -11
  188. package/dist/pack/capabilities.js.map +1 -1
  189. package/dist/pack/compose.d.ts +4 -1
  190. package/dist/pack/compose.d.ts.map +1 -1
  191. package/dist/pack/compose.js +4 -1
  192. package/dist/pack/compose.js.map +1 -1
  193. package/dist/pack/index.d.ts +2 -2
  194. package/dist/pack/index.d.ts.map +1 -1
  195. package/dist/pack/index.js +2 -2
  196. package/dist/pack/index.js.map +1 -1
  197. package/dist/pack/primitive_pack.d.ts +14 -3
  198. package/dist/pack/primitive_pack.d.ts.map +1 -1
  199. package/dist/pack/primitive_pack.js +25 -4
  200. package/dist/pack/primitive_pack.js.map +1 -1
  201. package/dist/render/anchors.d.ts +2 -2
  202. package/dist/render/anchors.d.ts.map +1 -1
  203. package/dist/render/anchors.js +1 -1
  204. package/dist/render/anchors.js.map +1 -1
  205. package/dist/render/format_number.d.ts.map +1 -1
  206. package/dist/render/format_number.js +2 -1
  207. package/dist/render/format_number.js.map +1 -1
  208. package/dist/render/html/envelope.d.ts +3 -3
  209. package/dist/render/html/envelope.js +12 -6
  210. package/dist/render/html/envelope.js.map +1 -1
  211. package/dist/render/layout_check.d.ts +1 -1
  212. package/dist/render/layout_check.d.ts.map +1 -1
  213. package/dist/render/layout_check.js.map +1 -1
  214. package/dist/render/markdown/builder.d.ts +5 -4
  215. package/dist/render/markdown/builder.d.ts.map +1 -1
  216. package/dist/render/markdown/builder.js +16 -7
  217. package/dist/render/markdown/builder.js.map +1 -1
  218. package/dist/render/markdown/format.d.ts +9 -0
  219. package/dist/render/markdown/format.d.ts.map +1 -1
  220. package/dist/render/markdown/format.js +67 -31
  221. package/dist/render/markdown/format.js.map +1 -1
  222. package/dist/render/markdown/host_tags.d.ts +14 -0
  223. package/dist/render/markdown/host_tags.d.ts.map +1 -0
  224. package/dist/render/markdown/host_tags.js +63 -0
  225. package/dist/render/markdown/host_tags.js.map +1 -0
  226. package/dist/render/markdown/index.d.ts +1 -0
  227. package/dist/render/markdown/index.d.ts.map +1 -1
  228. package/dist/render/markdown/index.js +1 -0
  229. package/dist/render/markdown/index.js.map +1 -1
  230. package/dist/render/markdown/split.d.ts +32 -0
  231. package/dist/render/markdown/split.d.ts.map +1 -0
  232. package/dist/render/markdown/split.js +321 -0
  233. package/dist/render/markdown/split.js.map +1 -0
  234. package/dist/render/primitive_dispatch.d.ts +6 -6
  235. package/dist/render/primitive_dispatch.d.ts.map +1 -1
  236. package/dist/render/primitive_dispatch.js +12 -26
  237. package/dist/render/primitive_dispatch.js.map +1 -1
  238. package/dist/render/react/content.d.ts +1 -1
  239. package/dist/render/react/content.d.ts.map +1 -1
  240. package/dist/render/react/content.js +3 -1
  241. package/dist/render/react/content.js.map +1 -1
  242. package/dist/render/slack/format.d.ts +0 -25
  243. package/dist/render/slack/format.d.ts.map +1 -1
  244. package/dist/render/slack/format.js +1 -599
  245. package/dist/render/slack/format.js.map +1 -1
  246. package/dist/render/slack/index.d.ts +1 -1
  247. package/dist/render/slack/index.d.ts.map +1 -1
  248. package/dist/render/slack/index.js +1 -1
  249. package/dist/render/slack/index.js.map +1 -1
  250. package/dist/render/slack/markdown_content.d.ts +10 -4
  251. package/dist/render/slack/markdown_content.d.ts.map +1 -1
  252. package/dist/render/slack/markdown_content.js +169 -113
  253. package/dist/render/slack/markdown_content.js.map +1 -1
  254. package/dist/testing/conformance.d.ts +19 -14
  255. package/dist/testing/conformance.d.ts.map +1 -1
  256. package/dist/testing/conformance.js +40 -24
  257. package/dist/testing/conformance.js.map +1 -1
  258. package/dist/testing/icon.d.ts +11 -0
  259. package/dist/testing/icon.d.ts.map +1 -0
  260. package/dist/testing/icon.js +244 -0
  261. package/dist/testing/icon.js.map +1 -0
  262. package/dist/testing/index.d.ts +2 -1
  263. package/dist/testing/index.d.ts.map +1 -1
  264. package/dist/testing/index.js +1 -0
  265. package/dist/testing/index.js.map +1 -1
  266. package/dist/testing/registration.d.ts +1 -1
  267. package/dist/testing/registration.d.ts.map +1 -1
  268. package/dist/testing/registration.js +6 -4
  269. package/dist/testing/registration.js.map +1 -1
  270. package/dist/validate/authoring_schema.d.ts +6 -0
  271. package/dist/validate/authoring_schema.d.ts.map +1 -1
  272. package/dist/validate/authoring_schema.js +15 -0
  273. package/dist/validate/authoring_schema.js.map +1 -1
  274. package/dist/validate/index.d.ts +1 -1
  275. package/dist/validate/index.d.ts.map +1 -1
  276. package/dist/validate/index.js +1 -1
  277. package/dist/validate/index.js.map +1 -1
  278. package/dist/validate/json_schema.d.ts.map +1 -1
  279. package/dist/validate/json_schema.js +10 -3
  280. package/dist/validate/json_schema.js.map +1 -1
  281. package/dist/validate/url.d.ts.map +1 -1
  282. package/dist/validate/url.js +2 -1
  283. package/dist/validate/url.js.map +1 -1
  284. package/dist/validate/validation.d.ts +1 -11
  285. package/dist/validate/validation.d.ts.map +1 -1
  286. package/dist/validate/validation.js +3 -46
  287. package/dist/validate/validation.js.map +1 -1
  288. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"layout_check.d.ts","sourceRoot":"","sources":["../../src/render/layout_check.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAUrE,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,0FAA0F;AAC1F,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,4FAA4F;AAC5F,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAqFD;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GACtB,QAAQ,SAAS,EACjB,MAAM,SAAS,OAAO,EAAE,EACxB,MAAM,eAAe,EACrB,SAAS,OAAO,GAAG,KAAK,KACvB,aAAa,EAgFf,CAAC"}
1
+ {"version":3,"file":"layout_check.d.ts","sourceRoot":"","sources":["../../src/render/layout_check.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAUrE,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,0FAA0F;AAC1F,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,4FAA4F;AAC5F,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAqFD;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GACtB,QAAQ,SAAS,EACjB,MAAM,SAAS,OAAO,EAAE,EACxB,MAAM,eAAe,EACrB,SAAS,OAAO,GAAG,UAAU,KAC5B,aAAa,EAgFf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"layout_check.js","sourceRoot":"","sources":["../../src/render/layout_check.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { ChildNodeWalker } from '../composition/body_node_base';\n\nimport {\n anchoredNodePaths,\n LAYOUT_ROOM_ATTRIBUTE,\n NODE_ANCHOR_ATTRIBUTE,\n nodeType,\n pairAnchors,\n} from './anchors';\n\n/** A rectangle on the canvas, in pixels. */\nexport interface LayoutRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** A laid-out element and the elements nested in it, as a layout engine measures them. */\nexport interface LayoutBox extends LayoutRect {\n /** Absent means unscaled. */\n readonly scale?: number;\n /** Text laid out in the box. */\n readonly runs?: readonly LayoutRect[];\n /** Where a {@link NODE_ANCHOR_ATTRIBUTE} is read from. */\n readonly attributes?: Readonly<Record<string, string>>;\n readonly children: readonly LayoutBox[];\n}\n\n/** A node drawn past the room its container gives it, or onto a sibling, by `by` pixels. */\nexport interface LayoutFinding {\n kind: 'overflow' | 'overlap';\n /** In validation's form, e.g. `body[1].items[0]`. */\n path: string;\n type: string;\n /** The sibling an `overlap` lands on. */\n with?: { path: string; type: string };\n by: number;\n}\n\ninterface PlacedNode {\n box: LayoutBox;\n path: string;\n type: string;\n}\n\n// Sub-pixel rounding reads as overflow without it.\nconst tolerance = 1;\n\nconst isScaled = ({ scale = 1 }: LayoutBox): boolean =>\n Math.abs(scale - 1) > 0.001;\n\nconst hasArea = ({ width, height }: LayoutRect): boolean =>\n width > 0 && height > 0;\n\n/** Every anchored box, pre-order, including those inside a scaled box, so a type's count matches its nodes. */\nconst anchoredBoxes = (box: LayoutBox): [string, LayoutBox][] => {\n const value = box.attributes?.[NODE_ANCHOR_ATTRIBUTE];\n return [\n ...(value === undefined ? [] : [[value, box] as [string, LayoutBox]]),\n ...box.children.flatMap(anchoredBoxes),\n ];\n};\n\nconst roomBoxes = (box: LayoutBox): LayoutBox[] => [\n ...(box.attributes?.[LAYOUT_ROOM_ATTRIBUTE] === undefined ? [] : [box]),\n ...box.children.flatMap(roomBoxes),\n];\n\n/**\n * The element boxes a node's own content fills: its box and those under it,\n * down to the nodes nested in it. Text runs are left out because glyphs\n * overhang a tight line height; a scaled box counts as itself alone.\n */\nconst ownBoxes = (\n box: LayoutBox,\n nested: ReadonlySet<LayoutBox>\n): LayoutBox[] => [\n box,\n ...(isScaled(box)\n ? []\n : box.children.flatMap((child) =>\n nested.has(child) ? [] : ownBoxes(child, nested)\n )),\n];\n\n/** What a box paints: its text, or itself when it holds nothing else, like a dot or a rule. */\nconst painted = (box: LayoutBox): LayoutRect[] => {\n if (isScaled(box)) {\n return [box];\n }\n const own =\n box.runs && box.runs.length > 0\n ? box.runs\n : box.children.length === 0\n ? [box]\n : [];\n return [...own.filter(hasArea), ...box.children.flatMap(painted)];\n};\n\nconst pastRoom = (room: LayoutRect, { x, y, width, height }: LayoutRect) =>\n Math.max(\n room.x - x,\n room.y - y,\n x + width - (room.x + room.width),\n y + height - (room.y + room.height)\n );\n\n/** How far `a` and `b` would have to move apart, along one axis, to clear each other. */\nconst overlapOf = (a: LayoutRect, b: LayoutRect): number => {\n const width = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const height = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n if (width <= tolerance || height <= tolerance) {\n return 0;\n }\n return Math.min(\n a.x + a.width - b.x,\n b.x + b.width - a.x,\n a.y + a.height - b.y,\n b.y + b.height - a.y\n );\n};\n\n/**\n * Where the nodes of `body` run past their room or onto each other in\n * `layout`, a measured render on `surface` with node anchors on. Empty when\n * nothing does.\n *\n * A node's room is the box of its nearest anchored or `layoutRoom` ancestor,\n * or `layout` at the top level, and only siblings under one room are\n * compared. Nothing inside a scaled box is checked. A finding is advice, not an error:\n * an overlap may be intended.\n */\nexport const checkLayout = (\n layout: LayoutBox,\n body: readonly unknown[],\n walk: ChildNodeWalker,\n surface: 'react' | 'svg'\n): LayoutFinding[] => {\n const nodes = anchoredNodePaths(body, walk, surface);\n const anchored = anchoredBoxes(layout);\n const boxes = pairAnchors(\n anchored,\n nodes.map(({ node }) => node)\n );\n const placed = new Map<LayoutBox, PlacedNode>();\n boxes.forEach((box, index) => {\n const { node, path } = nodes[index]!;\n const type = nodeType(node);\n if (box !== undefined && type !== undefined) {\n placed.set(box, { box, path, type });\n }\n });\n\n // Every anchored box bounds its ancestors' content, paired or not.\n const nested = new Set(anchored.map(([, box]) => box));\n const bounding = new Set([...nested, ...roomBoxes(layout)]);\n const rooms = new Map<PlacedNode, LayoutBox>();\n const siblings = new Map<LayoutBox | undefined, PlacedNode[]>();\n const visit = (box: LayoutBox, parent: LayoutBox | undefined): void => {\n const node = placed.get(box);\n if (node !== undefined) {\n rooms.set(node, parent ?? layout);\n siblings.set(parent, [...(siblings.get(parent) ?? []), node]);\n }\n if (!isScaled(box)) {\n box.children.forEach((child) =>\n visit(child, bounding.has(box) ? box : parent)\n );\n }\n };\n visit(layout, undefined);\n\n const overflows = [...rooms].flatMap(([node, room]): LayoutFinding[] => {\n const by = Math.max(\n 0,\n ...ownBoxes(node.box, nested)\n .filter(hasArea)\n .map((box) => pastRoom(room, box))\n );\n return by > tolerance\n ? [\n {\n kind: 'overflow',\n path: node.path,\n type: node.type,\n by: Math.round(by),\n },\n ]\n : [];\n });\n\n const overlaps = [...siblings.values()].flatMap((group) => {\n const paints = group.map(({ box }) => painted(box));\n return group.flatMap((first, i) =>\n group.slice(i + 1).flatMap((second, offset): LayoutFinding[] => {\n const by = Math.max(\n 0,\n ...paints[i]!.flatMap((a) =>\n paints[i + 1 + offset]!.map((b) => overlapOf(a, b))\n )\n );\n return by > 0\n ? [\n {\n kind: 'overlap',\n path: first.path,\n type: first.type,\n with: { path: second.path, type: second.type },\n by: Math.round(by),\n },\n ]\n : [];\n })\n );\n });\n\n return [...overflows, ...overlaps];\n};\n"]}
1
+ {"version":3,"file":"layout_check.js","sourceRoot":"","sources":["../../src/render/layout_check.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { ChildNodeWalker } from '../composition/body_node_base';\n\nimport {\n anchoredNodePaths,\n LAYOUT_ROOM_ATTRIBUTE,\n NODE_ANCHOR_ATTRIBUTE,\n nodeType,\n pairAnchors,\n} from './anchors';\n\n/** A rectangle on the canvas, in pixels. */\nexport interface LayoutRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** A laid-out element and the elements nested in it, as a layout engine measures them. */\nexport interface LayoutBox extends LayoutRect {\n /** Absent means unscaled. */\n readonly scale?: number;\n /** Text laid out in the box. */\n readonly runs?: readonly LayoutRect[];\n /** Where a {@link NODE_ANCHOR_ATTRIBUTE} is read from. */\n readonly attributes?: Readonly<Record<string, string>>;\n readonly children: readonly LayoutBox[];\n}\n\n/** A node drawn past the room its container gives it, or onto a sibling, by `by` pixels. */\nexport interface LayoutFinding {\n kind: 'overflow' | 'overlap';\n /** In validation's form, e.g. `body[1].items[0]`. */\n path: string;\n type: string;\n /** The sibling an `overlap` lands on. */\n with?: { path: string; type: string };\n by: number;\n}\n\ninterface PlacedNode {\n box: LayoutBox;\n path: string;\n type: string;\n}\n\n// Sub-pixel rounding reads as overflow without it.\nconst tolerance = 1;\n\nconst isScaled = ({ scale = 1 }: LayoutBox): boolean =>\n Math.abs(scale - 1) > 0.001;\n\nconst hasArea = ({ width, height }: LayoutRect): boolean =>\n width > 0 && height > 0;\n\n/** Every anchored box, pre-order, including those inside a scaled box, so a type's count matches its nodes. */\nconst anchoredBoxes = (box: LayoutBox): [string, LayoutBox][] => {\n const value = box.attributes?.[NODE_ANCHOR_ATTRIBUTE];\n return [\n ...(value === undefined ? [] : [[value, box] as [string, LayoutBox]]),\n ...box.children.flatMap(anchoredBoxes),\n ];\n};\n\nconst roomBoxes = (box: LayoutBox): LayoutBox[] => [\n ...(box.attributes?.[LAYOUT_ROOM_ATTRIBUTE] === undefined ? [] : [box]),\n ...box.children.flatMap(roomBoxes),\n];\n\n/**\n * The element boxes a node's own content fills: its box and those under it,\n * down to the nodes nested in it. Text runs are left out because glyphs\n * overhang a tight line height; a scaled box counts as itself alone.\n */\nconst ownBoxes = (\n box: LayoutBox,\n nested: ReadonlySet<LayoutBox>\n): LayoutBox[] => [\n box,\n ...(isScaled(box)\n ? []\n : box.children.flatMap((child) =>\n nested.has(child) ? [] : ownBoxes(child, nested)\n )),\n];\n\n/** What a box paints: its text, or itself when it holds nothing else, like a dot or a rule. */\nconst painted = (box: LayoutBox): LayoutRect[] => {\n if (isScaled(box)) {\n return [box];\n }\n const own =\n box.runs && box.runs.length > 0\n ? box.runs\n : box.children.length === 0\n ? [box]\n : [];\n return [...own.filter(hasArea), ...box.children.flatMap(painted)];\n};\n\nconst pastRoom = (room: LayoutRect, { x, y, width, height }: LayoutRect) =>\n Math.max(\n room.x - x,\n room.y - y,\n x + width - (room.x + room.width),\n y + height - (room.y + room.height)\n );\n\n/** How far `a` and `b` would have to move apart, along one axis, to clear each other. */\nconst overlapOf = (a: LayoutRect, b: LayoutRect): number => {\n const width = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);\n const height = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);\n if (width <= tolerance || height <= tolerance) {\n return 0;\n }\n return Math.min(\n a.x + a.width - b.x,\n b.x + b.width - a.x,\n a.y + a.height - b.y,\n b.y + b.height - a.y\n );\n};\n\n/**\n * Where the nodes of `body` run past their room or onto each other in\n * `layout`, a measured render on `surface` with node anchors on. Empty when\n * nothing does.\n *\n * A node's room is the box of its nearest anchored or `layoutRoom` ancestor,\n * or `layout` at the top level, and only siblings under one room are\n * compared. Nothing inside a scaled box is checked. A finding is advice, not an error:\n * an overlap may be intended.\n */\nexport const checkLayout = (\n layout: LayoutBox,\n body: readonly unknown[],\n walk: ChildNodeWalker,\n surface: 'react' | 'snapshot'\n): LayoutFinding[] => {\n const nodes = anchoredNodePaths(body, walk, surface);\n const anchored = anchoredBoxes(layout);\n const boxes = pairAnchors(\n anchored,\n nodes.map(({ node }) => node)\n );\n const placed = new Map<LayoutBox, PlacedNode>();\n boxes.forEach((box, index) => {\n const { node, path } = nodes[index]!;\n const type = nodeType(node);\n if (box !== undefined && type !== undefined) {\n placed.set(box, { box, path, type });\n }\n });\n\n // Every anchored box bounds its ancestors' content, paired or not.\n const nested = new Set(anchored.map(([, box]) => box));\n const bounding = new Set([...nested, ...roomBoxes(layout)]);\n const rooms = new Map<PlacedNode, LayoutBox>();\n const siblings = new Map<LayoutBox | undefined, PlacedNode[]>();\n const visit = (box: LayoutBox, parent: LayoutBox | undefined): void => {\n const node = placed.get(box);\n if (node !== undefined) {\n rooms.set(node, parent ?? layout);\n siblings.set(parent, [...(siblings.get(parent) ?? []), node]);\n }\n if (!isScaled(box)) {\n box.children.forEach((child) =>\n visit(child, bounding.has(box) ? box : parent)\n );\n }\n };\n visit(layout, undefined);\n\n const overflows = [...rooms].flatMap(([node, room]): LayoutFinding[] => {\n const by = Math.max(\n 0,\n ...ownBoxes(node.box, nested)\n .filter(hasArea)\n .map((box) => pastRoom(room, box))\n );\n return by > tolerance\n ? [\n {\n kind: 'overflow',\n path: node.path,\n type: node.type,\n by: Math.round(by),\n },\n ]\n : [];\n });\n\n const overlaps = [...siblings.values()].flatMap((group) => {\n const paints = group.map(({ box }) => painted(box));\n return group.flatMap((first, i) =>\n group.slice(i + 1).flatMap((second, offset): LayoutFinding[] => {\n const by = Math.max(\n 0,\n ...paints[i]!.flatMap((a) =>\n paints[i + 1 + offset]!.map((b) => overlapOf(a, b))\n )\n );\n return by > 0\n ? [\n {\n kind: 'overlap',\n path: first.path,\n type: first.type,\n with: { path: second.path, type: second.type },\n by: Math.round(by),\n },\n ]\n : [];\n })\n );\n });\n\n return [...overflows, ...overlaps];\n};\n"]}
@@ -1,6 +1,7 @@
1
1
  import { type MarkdownBlock, type MarkdownContent, type MarkdownInline, type MarkdownInlineInput } from '../../define/markdown_content.js';
2
2
  /** The node type of Markdown printed as written. */
3
3
  export declare const VERBATIM_TYPE = "isomerVerbatim";
4
+ export declare const verbatim: (markdown: string, source?: string) => MarkdownBlock;
4
5
  /**
5
6
  * Builds Markdown as content rather than strings, so escaping follows where
6
7
  * each value lands. Links and images apply the URL policy in
@@ -36,11 +37,11 @@ export declare const md: {
36
37
  table: (columns: readonly (MarkdownInlineInput | readonly MarkdownInlineInput[])[], rows: readonly (readonly (MarkdownInlineInput | readonly MarkdownInlineInput[])[])[]) => MarkdownBlock;
37
38
  /** An unsafe `language` is dropped. */
38
39
  codeBlock: (value: string, language?: string) => MarkdownBlock;
39
- /** Authored Markdown source, after {@link sanitizeMarkdownSource}. */
40
- authored: (source: string) => MarkdownBlock;
40
+ /** Authored Markdown source, after {@link sanitizeAuthoredSource}; whitespace-only source is dropped. */
41
+ authored: (source: string) => MarkdownContent;
41
42
  };
42
- /** A renderer's string output as content, printed as written. */
43
- export declare const markdownFromString: (markdown: string) => MarkdownContent;
43
+ /** Parsed mdast blocks as GFM, unsanitized, for `md.authored` to sanitize as it sanitizes source. */
44
+ export declare const printParsed: (nodes: readonly unknown[]) => string;
44
45
  /** `content` as flat mdast blocks, typed `unknown` so no declaration names mdast. */
45
46
  export declare const markdownBlocks: (content: MarkdownContent) => readonly unknown[];
46
47
  /** `content` as GFM, without a trailing line break. */
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/render/markdown/builder.ts"],"names":[],"mappings":"AA6BA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAYvC,oDAAoD;AACpD,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAsG9C;;;;;;;;GAQG;AACH,eAAO,MAAM,EAAE;kBACC,MAAM,KAAG,cAAc;0BACf,mBAAmB,EAAE,KAAG,cAAc;4BAEpC,mBAAmB,EAAE,KAAG,cAAc;kBAEhD,MAAM,KAAG,cAAc;kBAK5B,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,QACrD,MAAM,KACX,cAAc;iBAMJ,MAAM,OAAO,MAAM,KAAG,cAAc;IAMjD,4NAA4N;iBACjN,cAAc;6BACA,mBAAmB,EAAE,KAAG,aAAa;qBAGrD,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,eACf,mBAAmB,EAAE,KACjC,aAAa;IAEhB,mFAAmF;8BACzD,eAAe,EAAE,KAAG,eAAe;IAS7D;;;;OAIG;kBAEM,SAAS,CAAC,mBAAmB,GAAG,eAAe,CAAC,EAAE,uBAC7B;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAChE,aAAa;IAehB,+EAA+E;qBAEpE,SAAS,CAAC,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,CAAC,EAAE,QACpE,SAAS,CAAC,SAAS,CACvB,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,CACrD,EAAE,CAAC,EAAE,KACL,aAAa;IAWhB,uCAAuC;uBACpB,MAAM,aAAa,MAAM,KAAG,aAAa;IAS5D,sEAAsE;uBACnD,MAAM,KAAG,aAAa;CAE1C,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,eACJ,CAAC;AA+CnD,qFAAqF;AACrF,eAAO,MAAM,cAAc,GAAI,SAAS,eAAe,KAAG,SAAS,OAAO,EACpD,CAAC;AAEvB,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,GAAI,SAAS,eAAe,KAAG,MAI1D,CAAC"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/render/markdown/builder.ts"],"names":[],"mappings":"AA6BA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAYvC,oDAAoD;AACpD,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAqF9C,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,SAAS,MAAM,KAAG,aAK/B,CAAC;AAe/B;;;;;;;;GAQG;AACH,eAAO,MAAM,EAAE;kBACC,MAAM,KAAG,cAAc;0BACf,mBAAmB,EAAE,KAAG,cAAc;4BAEpC,mBAAmB,EAAE,KAAG,cAAc;kBAEhD,MAAM,KAAG,cAAc;kBAK5B,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,QACrD,MAAM,KACX,cAAc;iBAMJ,MAAM,OAAO,MAAM,KAAG,cAAc;IAMjD,4NAA4N;iBACjN,cAAc;6BACA,mBAAmB,EAAE,KAAG,aAAa;qBAGrD,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,eACf,mBAAmB,EAAE,KACjC,aAAa;IAEhB,mFAAmF;8BACzD,eAAe,EAAE,KAAG,eAAe;IAS7D;;;;OAIG;kBAEM,SAAS,CAAC,mBAAmB,GAAG,eAAe,CAAC,EAAE,uBAC7B;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAChE,aAAa;IAehB,+EAA+E;qBAEpE,SAAS,CAAC,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,CAAC,EAAE,QACpE,SAAS,CAAC,SAAS,CACvB,mBAAmB,GAAG,SAAS,mBAAmB,EAAE,CACrD,EAAE,CAAC,EAAE,KACL,aAAa;IAWhB,uCAAuC;uBACpB,MAAM,aAAa,MAAM,KAAG,aAAa;IAS5D,yGAAyG;uBACtF,MAAM,KAAG,eAAe;CAO5C,CAAC;AA+CF,qGAAqG;AACrG,eAAO,MAAM,WAAW,GAAI,OAAO,SAAS,OAAO,EAAE,KAAG,MAIlC,CAAC;AAEvB,qFAAqF;AACrF,eAAO,MAAM,cAAc,GAAI,SAAS,eAAe,KAAG,SAAS,OAAO,EACpD,CAAC;AAEvB,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,GAAI,SAAS,eAAe,KAAG,MAI1D,CAAC"}
@@ -9,7 +9,7 @@ import { defaultHandlers, toMarkdown, } from 'mdast-util-to-markdown';
9
9
  import { oneLine } from '../../composition/one_line.js';
10
10
  import { markdownContent, } from '../../define/markdown_content.js';
11
11
  import { BLOCKED_HREF, sanitizeAssetUrl, sanitizeNavigationHref, } from '../../validate/url.js';
12
- import { sanitizeMarkdownSource } from './format.js';
12
+ import { sanitizeAuthoredSource } from './format.js';
13
13
  // A fence-info string only allows word-ish tokens; anything else would
14
14
  // terminate the fence early or inject markdown.
15
15
  const FENCE_INFO_RE = /^[\w+#.-]+$/;
@@ -55,10 +55,13 @@ const isListStart = (start, count) => start !== undefined &&
55
55
  start >= 0 &&
56
56
  start + Math.max(count - 1, 0) <= MAX_LIST_NUMBER;
57
57
  // Printed as written, for Markdown that is already safe. Trailing whitespace
58
- // would add blank lines between blocks.
59
- const verbatim = (markdown) => block({
58
+ // would add blank lines between blocks. `source` is the authored text when
59
+ // sanitizing degraded it to inert text, whose escapes only Markdown resolves;
60
+ // surfaces that print literal text read it instead.
61
+ export const verbatim = (markdown, source) => block({
60
62
  type: VERBATIM_TYPE,
61
63
  value: markdown.trimEnd(),
64
+ ...(source === undefined ? {} : { source }),
62
65
  });
63
66
  // An empty wrapper prints its markers alone: `****` reads as a thematic break.
64
67
  const wrapper = (type, inputs) => {
@@ -144,11 +147,15 @@ export const md = {
144
147
  : null,
145
148
  value,
146
149
  }),
147
- /** Authored Markdown source, after {@link sanitizeMarkdownSource}. */
148
- authored: (source) => verbatim(sanitizeMarkdownSource(source)),
150
+ /** Authored Markdown source, after {@link sanitizeAuthoredSource}; whitespace-only source is dropped. */
151
+ authored: (source) => {
152
+ if (source.trim() === '') {
153
+ return [];
154
+ }
155
+ const { markdown, inert } = sanitizeAuthoredSource(source);
156
+ return verbatim(markdown, inert ? source : undefined);
157
+ },
149
158
  };
150
- /** A renderer's string output as content, printed as written. */
151
- export const markdownFromString = (markdown) => markdown.trim() === '' ? [] : verbatim(markdown);
152
159
  const asText = (node, ...rest) => defaultHandlers.text({ type: 'text', value: node.value ?? node.alt ?? '' }, ...rest);
153
160
  // The URL policy again at serialization, for content built outside `md`.
154
161
  const handlers = {
@@ -176,6 +183,8 @@ const OPTIONS = {
176
183
  extensions: [gfmToMarkdown({ tablePipeAlign: false })],
177
184
  handlers: handlers,
178
185
  };
186
+ /** Parsed mdast blocks as GFM, unsanitized, for `md.authored` to sanitize as it sanitizes source. */
187
+ export const printParsed = (nodes) => toMarkdown({ type: 'root', children: nodes }, { ...OPTIONS, handlers: {} }).replace(/\n$/, '');
179
188
  /** `content` as flat mdast blocks, typed `unknown` so no declaration names mdast. */
180
189
  export const markdownBlocks = (content) => rootContent(content);
181
190
  /** `content` as GFM, without a trailing line break. */
@@ -1 +1 @@
1
- {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/render/markdown/builder.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\n// Builder content is mdast under a brand. Every mdast type stays inside this\n// module, so no emitted declaration names one.\n\nimport type {\n Blockquote,\n Definition,\n Image,\n Link,\n ListItem,\n PhrasingContent,\n RootContent,\n TableRow,\n} from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport {\n defaultHandlers,\n type Handle,\n type Options,\n toMarkdown,\n} from 'mdast-util-to-markdown';\n\nimport { oneLine } from '../../composition/one_line';\nimport {\n type MarkdownBlock,\n type MarkdownContent,\n markdownContent,\n type MarkdownInline,\n type MarkdownInlineInput,\n} from '../../define/markdown_content';\nimport {\n BLOCKED_HREF,\n sanitizeAssetUrl,\n sanitizeNavigationHref,\n} from '../../validate/url';\n\nimport { sanitizeMarkdownSource } from './format';\n\n// A fence-info string only allows word-ish tokens; anything else would\n// terminate the fence early or inject markdown.\nconst FENCE_INFO_RE = /^[\\w+#.-]+$/;\n/** The node type of Markdown printed as written. */\nexport const VERBATIM_TYPE = 'isomerVerbatim';\n\nconst inline = (node: PhrasingContent): MarkdownInline =>\n Object.assign(node, { [markdownContent]: 'inline' as const });\n\nconst block = (node: RootContent): MarkdownBlock =>\n Object.assign(node, { [markdownContent]: 'block' as const });\n\nconst isContentList = (\n content: MarkdownInline | MarkdownContent\n): content is readonly MarkdownContent[] => Array.isArray(content);\n\nconst isInlineList = (\n label: MarkdownInlineInput | readonly MarkdownInlineInput[]\n): label is readonly MarkdownInlineInput[] => Array.isArray(label);\n\nconst phrasing = (input: MarkdownInlineInput): PhrasingContent =>\n typeof input === 'string'\n ? { type: 'text', value: oneLine(input) }\n : (input as unknown as PhrasingContent);\n\nconst emptyText = (): PhrasingContent => ({ type: 'text', value: '' });\n\nconst isEmptyText = (node: PhrasingContent): boolean =>\n node.type === 'text' && node.value === '';\n\n// A break at either edge prints as a literal `\\` or loose markers.\nconst withoutEdgeBreaks = (\n inputs: readonly MarkdownInlineInput[]\n): PhrasingContent[] => {\n const children = inputs.map(phrasing).filter((node) => !isEmptyText(node));\n let start = 0;\n let end = children.length;\n while (start < end && children[start]!.type === 'break') {\n start += 1;\n }\n while (end > start && children[end - 1]!.type === 'break') {\n end -= 1;\n }\n return children.slice(start, end);\n};\n\n// Only a paragraph breaks a line: a heading with one turns setext, and the\n// Slack fallback reads a line at a time.\nconst inlineChildren = (\n inputs: readonly MarkdownInlineInput[]\n): PhrasingContent[] =>\n withoutEdgeBreaks(inputs).map((node) =>\n node.type === 'break' ? { type: 'text', value: ' ' } : node\n );\n\nconst rootContent = (content: MarkdownContent): RootContent[] =>\n isContentList(content)\n ? content.flatMap(rootContent)\n : [content as unknown as RootContent];\n\nconst isInlineInput = (\n item: MarkdownInlineInput | MarkdownContent\n): item is MarkdownInlineInput =>\n typeof item === 'string' ||\n (!isContentList(item) && item[markdownContent] === 'inline');\n\nconst itemContent = (\n item: MarkdownInlineInput | MarkdownContent\n): ListItem['children'] =>\n isInlineInput(item)\n ? [{ type: 'paragraph', children: withoutEdgeBreaks([item]) }]\n : (rootContent(item) as ListItem['children']);\n\n// GFM reads a list number of at most nine digits, so the last item's must fit.\nconst MAX_LIST_NUMBER = 999_999_999;\n\nconst isListStart = (\n start: number | undefined,\n count: number\n): start is number =>\n start !== undefined &&\n Number.isInteger(start) &&\n start >= 0 &&\n start + Math.max(count - 1, 0) <= MAX_LIST_NUMBER;\n\n// Printed as written, for Markdown that is already safe. Trailing whitespace\n// would add blank lines between blocks.\nconst verbatim = (markdown: string): MarkdownBlock =>\n block({\n type: VERBATIM_TYPE,\n value: markdown.trimEnd(),\n } as unknown as RootContent);\n\n// An empty wrapper prints its markers alone: `****` reads as a thematic break.\nconst wrapper = (\n type: 'strong' | 'emphasis',\n inputs: MarkdownInlineInput[]\n): MarkdownInline => {\n const children = inlineChildren(inputs);\n return inline(children.length === 0 ? emptyText() : { type, children });\n};\n\nconst inlineRuns = (\n runs: MarkdownInlineInput | readonly MarkdownInlineInput[]\n): PhrasingContent[] => inlineChildren(isInlineList(runs) ? runs : [runs]);\n\n/**\n * Builds Markdown as content rather than strings, so escaping follows where\n * each value lands. Links and images apply the URL policy in\n * `src/validate/url.ts`: a blocked link keeps its label on\n * {@link BLOCKED_HREF}, and a blocked image degrades to its alt text.\n *\n * @example\n * md.list(rows.map((row) => md.paragraph(md.strong(row.label), ': ', row.value)))\n */\nexport const md = {\n text: (value: string): MarkdownInline => inline(phrasing(value)),\n strong: (...children: MarkdownInlineInput[]): MarkdownInline =>\n wrapper('strong', children),\n emphasis: (...children: MarkdownInlineInput[]): MarkdownInline =>\n wrapper('emphasis', children),\n code: (value: string): MarkdownInline =>\n inline(\n value === '' ? emptyText() : { type: 'inlineCode', value: oneLine(value) }\n ),\n link: (\n label: MarkdownInlineInput | readonly MarkdownInlineInput[],\n href: string\n ): MarkdownInline =>\n inline({\n type: 'link',\n url: sanitizeNavigationHref(href) ?? BLOCKED_HREF,\n children: inlineRuns(label),\n }),\n image: (alt: string, src: string): MarkdownInline => {\n const url = sanitizeAssetUrl(src);\n return url === null\n ? inline(phrasing(alt))\n : inline({ type: 'image', url, alt: oneLine(alt) });\n },\n /** A hard line break, printed as a backslash before the line ending. Inside a heading, strong, emphasis, link label, or table cell it is a space; at the start or end of any of these, or of a paragraph, it is dropped. */\n break: (): MarkdownInline => inline({ type: 'break' }),\n paragraph: (...children: MarkdownInlineInput[]): MarkdownBlock =>\n block({ type: 'paragraph', children: withoutEdgeBreaks(children) }),\n heading: (\n depth: 1 | 2 | 3 | 4 | 5 | 6,\n ...children: MarkdownInlineInput[]\n ): MarkdownBlock =>\n block({ type: 'heading', depth, children: inlineChildren(children) }),\n /** A quote with no blocks, such as one holding only a hidden child, is dropped. */\n blockquote: (...children: MarkdownContent[]): MarkdownContent => {\n const content = rootContent(children);\n return content.length === 0\n ? []\n : block({\n type: 'blockquote',\n children: content as Blockquote['children'],\n });\n },\n /**\n * An item that is inline input becomes one paragraph; one with no blocks,\n * such as a hidden child, is dropped. A `start` that would print a marker\n * GFM does not read as a list number is ignored.\n */\n list: (\n items: readonly (MarkdownInlineInput | MarkdownContent)[],\n { ordered = false, start }: { ordered?: boolean; start?: number } = {}\n ): MarkdownBlock => {\n const children = items.flatMap((item): ListItem[] => {\n const content = itemContent(item);\n return content.length === 0\n ? []\n : [{ type: 'listItem', spread: false, children: content }];\n });\n return block({\n type: 'list',\n ordered,\n ...(isListStart(start, children.length) ? { start } : {}),\n spread: false,\n children,\n });\n },\n /** A cell is one inline run or several. GFM trims a cell's edge whitespace. */\n table: (\n columns: readonly (MarkdownInlineInput | readonly MarkdownInlineInput[])[],\n rows: readonly (readonly (\n MarkdownInlineInput | readonly MarkdownInlineInput[]\n )[])[]\n ): MarkdownBlock =>\n block({\n type: 'table',\n children: [columns, ...rows].map((cells): TableRow => ({\n type: 'tableRow',\n children: cells.map((cell) => ({\n type: 'tableCell',\n children: inlineRuns(cell),\n })),\n })),\n }),\n /** An unsafe `language` is dropped. */\n codeBlock: (value: string, language?: string): MarkdownBlock =>\n block({\n type: 'code',\n lang:\n language !== undefined && FENCE_INFO_RE.test(language)\n ? language\n : null,\n value,\n }),\n /** Authored Markdown source, after {@link sanitizeMarkdownSource}. */\n authored: (source: string): MarkdownBlock =>\n verbatim(sanitizeMarkdownSource(source)),\n};\n\n/** A renderer's string output as content, printed as written. */\nexport const markdownFromString = (markdown: string): MarkdownContent =>\n markdown.trim() === '' ? [] : verbatim(markdown);\n\nconst asText: Handle = (\n node: { value?: string; alt?: string | null },\n ...rest\n) =>\n defaultHandlers.text(\n { type: 'text', value: node.value ?? node.alt ?? '' },\n ...rest\n );\n\n// The URL policy again at serialization, for content built outside `md`.\nconst handlers: Record<string, Handle> = {\n link: (node: Link, ...rest) =>\n defaultHandlers.link(\n { ...node, url: sanitizeNavigationHref(node.url) ?? BLOCKED_HREF },\n ...rest\n ),\n definition: (node: Definition, ...rest) =>\n defaultHandlers.definition(\n { ...node, url: sanitizeNavigationHref(node.url) ?? BLOCKED_HREF },\n ...rest\n ),\n image: (node: Image, ...rest) => {\n const url = sanitizeAssetUrl(node.url);\n return url === null\n ? asText(node, ...rest)\n : defaultHandlers.image({ ...node, url }, ...rest);\n },\n html: asText,\n [VERBATIM_TYPE]: (node: { value: string }) => node.value,\n};\n\nconst OPTIONS: Options = {\n bullet: '-',\n // With `*`, emphasis around strong prints `***x***`, which the Slack\n // fallback cannot split. `_` costs character references around emphasis\n // inside a word.\n emphasis: '_',\n fence: '`',\n listItemIndent: 'one',\n rule: '-',\n strong: '*',\n extensions: [gfmToMarkdown({ tablePipeAlign: false })],\n handlers: handlers as Options['handlers'],\n};\n\n/** `content` as flat mdast blocks, typed `unknown` so no declaration names mdast. */\nexport const markdownBlocks = (content: MarkdownContent): readonly unknown[] =>\n rootContent(content);\n\n/** `content` as GFM, without a trailing line break. */\nexport const serializeMarkdown = (content: MarkdownContent): string =>\n toMarkdown({ type: 'root', children: rootContent(content) }, OPTIONS).replace(\n /\\n$/,\n ''\n );\n"]}
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/render/markdown/builder.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\n// Builder content is mdast under a brand. Every mdast type stays inside this\n// module, so no emitted declaration names one.\n\nimport type {\n Blockquote,\n Definition,\n Image,\n Link,\n ListItem,\n PhrasingContent,\n RootContent,\n TableRow,\n} from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport {\n defaultHandlers,\n type Handle,\n type Options,\n toMarkdown,\n} from 'mdast-util-to-markdown';\n\nimport { oneLine } from '../../composition/one_line';\nimport {\n type MarkdownBlock,\n type MarkdownContent,\n markdownContent,\n type MarkdownInline,\n type MarkdownInlineInput,\n} from '../../define/markdown_content';\nimport {\n BLOCKED_HREF,\n sanitizeAssetUrl,\n sanitizeNavigationHref,\n} from '../../validate/url';\n\nimport { sanitizeAuthoredSource } from './format';\n\n// A fence-info string only allows word-ish tokens; anything else would\n// terminate the fence early or inject markdown.\nconst FENCE_INFO_RE = /^[\\w+#.-]+$/;\n/** The node type of Markdown printed as written. */\nexport const VERBATIM_TYPE = 'isomerVerbatim';\n\nconst inline = (node: PhrasingContent): MarkdownInline =>\n Object.assign(node, { [markdownContent]: 'inline' as const });\n\nconst block = (node: RootContent): MarkdownBlock =>\n Object.assign(node, { [markdownContent]: 'block' as const });\n\nconst isContentList = (\n content: MarkdownInline | MarkdownContent\n): content is readonly MarkdownContent[] => Array.isArray(content);\n\nconst isInlineList = (\n label: MarkdownInlineInput | readonly MarkdownInlineInput[]\n): label is readonly MarkdownInlineInput[] => Array.isArray(label);\n\nconst phrasing = (input: MarkdownInlineInput): PhrasingContent =>\n typeof input === 'string'\n ? { type: 'text', value: oneLine(input) }\n : (input as unknown as PhrasingContent);\n\nconst emptyText = (): PhrasingContent => ({ type: 'text', value: '' });\n\nconst isEmptyText = (node: PhrasingContent): boolean =>\n node.type === 'text' && node.value === '';\n\n// A break at either edge prints as a literal `\\` or loose markers.\nconst withoutEdgeBreaks = (\n inputs: readonly MarkdownInlineInput[]\n): PhrasingContent[] => {\n const children = inputs.map(phrasing).filter((node) => !isEmptyText(node));\n let start = 0;\n let end = children.length;\n while (start < end && children[start]!.type === 'break') {\n start += 1;\n }\n while (end > start && children[end - 1]!.type === 'break') {\n end -= 1;\n }\n return children.slice(start, end);\n};\n\n// Only a paragraph breaks a line: a heading with one turns setext, and the\n// Slack fallback reads a line at a time.\nconst inlineChildren = (\n inputs: readonly MarkdownInlineInput[]\n): PhrasingContent[] =>\n withoutEdgeBreaks(inputs).map((node) =>\n node.type === 'break' ? { type: 'text', value: ' ' } : node\n );\n\nconst rootContent = (content: MarkdownContent): RootContent[] =>\n isContentList(content)\n ? content.flatMap(rootContent)\n : [content as unknown as RootContent];\n\nconst isInlineInput = (\n item: MarkdownInlineInput | MarkdownContent\n): item is MarkdownInlineInput =>\n typeof item === 'string' ||\n (!isContentList(item) && item[markdownContent] === 'inline');\n\nconst itemContent = (\n item: MarkdownInlineInput | MarkdownContent\n): ListItem['children'] =>\n isInlineInput(item)\n ? [{ type: 'paragraph', children: withoutEdgeBreaks([item]) }]\n : (rootContent(item) as ListItem['children']);\n\n// GFM reads a list number of at most nine digits, so the last item's must fit.\nconst MAX_LIST_NUMBER = 999_999_999;\n\nconst isListStart = (\n start: number | undefined,\n count: number\n): start is number =>\n start !== undefined &&\n Number.isInteger(start) &&\n start >= 0 &&\n start + Math.max(count - 1, 0) <= MAX_LIST_NUMBER;\n\n// Printed as written, for Markdown that is already safe. Trailing whitespace\n// would add blank lines between blocks. `source` is the authored text when\n// sanitizing degraded it to inert text, whose escapes only Markdown resolves;\n// surfaces that print literal text read it instead.\nexport const verbatim = (markdown: string, source?: string): MarkdownBlock =>\n block({\n type: VERBATIM_TYPE,\n value: markdown.trimEnd(),\n ...(source === undefined ? {} : { source }),\n } as unknown as RootContent);\n\n// An empty wrapper prints its markers alone: `****` reads as a thematic break.\nconst wrapper = (\n type: 'strong' | 'emphasis',\n inputs: MarkdownInlineInput[]\n): MarkdownInline => {\n const children = inlineChildren(inputs);\n return inline(children.length === 0 ? emptyText() : { type, children });\n};\n\nconst inlineRuns = (\n runs: MarkdownInlineInput | readonly MarkdownInlineInput[]\n): PhrasingContent[] => inlineChildren(isInlineList(runs) ? runs : [runs]);\n\n/**\n * Builds Markdown as content rather than strings, so escaping follows where\n * each value lands. Links and images apply the URL policy in\n * `src/validate/url.ts`: a blocked link keeps its label on\n * {@link BLOCKED_HREF}, and a blocked image degrades to its alt text.\n *\n * @example\n * md.list(rows.map((row) => md.paragraph(md.strong(row.label), ': ', row.value)))\n */\nexport const md = {\n text: (value: string): MarkdownInline => inline(phrasing(value)),\n strong: (...children: MarkdownInlineInput[]): MarkdownInline =>\n wrapper('strong', children),\n emphasis: (...children: MarkdownInlineInput[]): MarkdownInline =>\n wrapper('emphasis', children),\n code: (value: string): MarkdownInline =>\n inline(\n value === '' ? emptyText() : { type: 'inlineCode', value: oneLine(value) }\n ),\n link: (\n label: MarkdownInlineInput | readonly MarkdownInlineInput[],\n href: string\n ): MarkdownInline =>\n inline({\n type: 'link',\n url: sanitizeNavigationHref(href) ?? BLOCKED_HREF,\n children: inlineRuns(label),\n }),\n image: (alt: string, src: string): MarkdownInline => {\n const url = sanitizeAssetUrl(src);\n return url === null\n ? inline(phrasing(alt))\n : inline({ type: 'image', url, alt: oneLine(alt) });\n },\n /** A hard line break, printed as a backslash before the line ending. Inside a heading, strong, emphasis, link label, or table cell it is a space; at the start or end of any of these, or of a paragraph, it is dropped. */\n break: (): MarkdownInline => inline({ type: 'break' }),\n paragraph: (...children: MarkdownInlineInput[]): MarkdownBlock =>\n block({ type: 'paragraph', children: withoutEdgeBreaks(children) }),\n heading: (\n depth: 1 | 2 | 3 | 4 | 5 | 6,\n ...children: MarkdownInlineInput[]\n ): MarkdownBlock =>\n block({ type: 'heading', depth, children: inlineChildren(children) }),\n /** A quote with no blocks, such as one holding only a hidden child, is dropped. */\n blockquote: (...children: MarkdownContent[]): MarkdownContent => {\n const content = rootContent(children);\n return content.length === 0\n ? []\n : block({\n type: 'blockquote',\n children: content as Blockquote['children'],\n });\n },\n /**\n * An item that is inline input becomes one paragraph; one with no blocks,\n * such as a hidden child, is dropped. A `start` that would print a marker\n * GFM does not read as a list number is ignored.\n */\n list: (\n items: readonly (MarkdownInlineInput | MarkdownContent)[],\n { ordered = false, start }: { ordered?: boolean; start?: number } = {}\n ): MarkdownBlock => {\n const children = items.flatMap((item): ListItem[] => {\n const content = itemContent(item);\n return content.length === 0\n ? []\n : [{ type: 'listItem', spread: false, children: content }];\n });\n return block({\n type: 'list',\n ordered,\n ...(isListStart(start, children.length) ? { start } : {}),\n spread: false,\n children,\n });\n },\n /** A cell is one inline run or several. GFM trims a cell's edge whitespace. */\n table: (\n columns: readonly (MarkdownInlineInput | readonly MarkdownInlineInput[])[],\n rows: readonly (readonly (\n MarkdownInlineInput | readonly MarkdownInlineInput[]\n )[])[]\n ): MarkdownBlock =>\n block({\n type: 'table',\n children: [columns, ...rows].map((cells): TableRow => ({\n type: 'tableRow',\n children: cells.map((cell) => ({\n type: 'tableCell',\n children: inlineRuns(cell),\n })),\n })),\n }),\n /** An unsafe `language` is dropped. */\n codeBlock: (value: string, language?: string): MarkdownBlock =>\n block({\n type: 'code',\n lang:\n language !== undefined && FENCE_INFO_RE.test(language)\n ? language\n : null,\n value,\n }),\n /** Authored Markdown source, after {@link sanitizeAuthoredSource}; whitespace-only source is dropped. */\n authored: (source: string): MarkdownContent => {\n if (source.trim() === '') {\n return [];\n }\n const { markdown, inert } = sanitizeAuthoredSource(source);\n return verbatim(markdown, inert ? source : undefined);\n },\n};\n\nconst asText: Handle = (\n node: { value?: string; alt?: string | null },\n ...rest\n) =>\n defaultHandlers.text(\n { type: 'text', value: node.value ?? node.alt ?? '' },\n ...rest\n );\n\n// The URL policy again at serialization, for content built outside `md`.\nconst handlers: Record<string, Handle> = {\n link: (node: Link, ...rest) =>\n defaultHandlers.link(\n { ...node, url: sanitizeNavigationHref(node.url) ?? BLOCKED_HREF },\n ...rest\n ),\n definition: (node: Definition, ...rest) =>\n defaultHandlers.definition(\n { ...node, url: sanitizeNavigationHref(node.url) ?? BLOCKED_HREF },\n ...rest\n ),\n image: (node: Image, ...rest) => {\n const url = sanitizeAssetUrl(node.url);\n return url === null\n ? asText(node, ...rest)\n : defaultHandlers.image({ ...node, url }, ...rest);\n },\n html: asText,\n [VERBATIM_TYPE]: (node: { value: string }) => node.value,\n};\n\nconst OPTIONS: Options = {\n bullet: '-',\n // With `*`, emphasis around strong prints `***x***`, which the Slack\n // fallback cannot split. `_` costs character references around emphasis\n // inside a word.\n emphasis: '_',\n fence: '`',\n listItemIndent: 'one',\n rule: '-',\n strong: '*',\n extensions: [gfmToMarkdown({ tablePipeAlign: false })],\n handlers: handlers as Options['handlers'],\n};\n\n/** Parsed mdast blocks as GFM, unsanitized, for `md.authored` to sanitize as it sanitizes source. */\nexport const printParsed = (nodes: readonly unknown[]): string =>\n toMarkdown(\n { type: 'root', children: nodes as RootContent[] },\n { ...OPTIONS, handlers: {} }\n ).replace(/\\n$/, '');\n\n/** `content` as flat mdast blocks, typed `unknown` so no declaration names mdast. */\nexport const markdownBlocks = (content: MarkdownContent): readonly unknown[] =>\n rootContent(content);\n\n/** `content` as GFM, without a trailing line break. */\nexport const serializeMarkdown = (content: MarkdownContent): string =>\n toMarkdown({ type: 'root', children: rootContent(content) }, OPTIONS).replace(\n /\\n$/,\n ''\n );\n"]}
@@ -1,3 +1,12 @@
1
+ /** `markdown` as flat GFM mdast blocks, typed `unknown` so no declaration names mdast; `null` past the parse budget or the parser's recursion depth. */
2
+ export declare const parseGfmBlocks: (markdown: string) => readonly unknown[] | null;
3
+ /** {@link sanitizeMarkdownSource}'s result, and whether it degraded to inert text. */
4
+ export declare const sanitizeAuthoredSource: (markdown: string) => {
5
+ markdown: string;
6
+ inert: boolean;
7
+ };
1
8
  /** Sanitizes GFM destinations and HTML; excessive syntax or length degrades to inert text. */
2
9
  export declare const sanitizeMarkdownSource: (markdown: string) => string;
10
+ export declare const inert: (markdown: string) => string;
11
+ export declare const exceedsParseBudget: (markdown: string) => boolean;
3
12
  //# sourceMappingURL=format.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/render/markdown/format.ts"],"names":[],"mappings":"AAuKA,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,KAAG,MAezD,CAAC"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/render/markdown/format.ts"],"names":[],"mappings":"AAsDA,wJAAwJ;AACxJ,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,SAAS,OAAO,EAAE,GAAG,IAYtE,CAAC;AAiJF,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,GACjC,UAAU,MAAM,KACf;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAqBpC,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,KAAG,MACf,CAAC;AAG5C,eAAO,MAAM,KAAK,GAAI,UAAU,MAAM,KAAG,MACmB,CAAC;AAY7D,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,OAgBrD,CAAC"}
@@ -15,14 +15,35 @@ const escapeLinkLabel = (label) => label.replace(/[[\]\\]/g, '\\$&');
15
15
  // early or read as a link title. `encodeURIComponent` leaves `(` and `)`
16
16
  // unescaped by spec, so those two are mapped by hand.
17
17
  const escapeLinkDestination = (href) => href.replace(/[()\s\\]/g, (char) => {
18
- if (char === '(')
18
+ if (char === '(') {
19
19
  return '%28';
20
- if (char === ')')
20
+ }
21
+ if (char === ')') {
21
22
  return '%29';
23
+ }
22
24
  return encodeURIComponent(char);
23
25
  });
24
26
  const escapeParsedDestination = (href) => escapeLinkDestination(href.replace(/&/g, '&amp;'));
25
27
  let parseOptions;
28
+ const parse = (source) => fromMarkdown(source, (parseOptions ??= {
29
+ extensions: [gfm()],
30
+ mdastExtensions: [gfmFromMarkdown()],
31
+ }));
32
+ /** `markdown` as flat GFM mdast blocks, typed `unknown` so no declaration names mdast; `null` past the parse budget or the parser's recursion depth. */
33
+ export const parseGfmBlocks = (markdown) => {
34
+ if (exceedsParseBudget(markdown)) {
35
+ return null;
36
+ }
37
+ try {
38
+ return parse(markdown).children;
39
+ }
40
+ catch (error) {
41
+ if (!(error instanceof RangeError)) {
42
+ throw error;
43
+ }
44
+ return null;
45
+ }
46
+ };
26
47
  // Each pass can expose a new sink (an escaped HTML block reveals the Markdown
27
48
  // inside it; a blocked link's label may close an outer `](`), so passes repeat
28
49
  // until the source is stable.
@@ -34,11 +55,7 @@ const offsets = (node) => {
34
55
  return start === undefined || end === undefined ? undefined : [start, end];
35
56
  };
36
57
  const sanitizePass = (source) => {
37
- parseOptions ??= {
38
- extensions: [gfm()],
39
- mdastExtensions: [gfmFromMarkdown()],
40
- };
41
- const root = fromMarkdown(source, parseOptions);
58
+ const root = parse(source);
42
59
  const definitions = new Map();
43
60
  const pending = [...root.children].reverse();
44
61
  while (pending.length) {
@@ -46,8 +63,9 @@ const sanitizePass = (source) => {
46
63
  if (node.type === 'definition' && !definitions.has(node.identifier)) {
47
64
  definitions.set(node.identifier, node);
48
65
  }
49
- if ('children' in node)
66
+ if ('children' in node) {
50
67
  pending.push(...[...node.children].reverse());
68
+ }
51
69
  }
52
70
  const slice = (node) => {
53
71
  const range = offsets(node);
@@ -58,8 +76,9 @@ const sanitizePass = (source) => {
58
76
  let cursor = start;
59
77
  for (const child of children) {
60
78
  const range = offsets(child);
61
- if (!range)
79
+ if (!range) {
62
80
  continue;
81
+ }
63
82
  out += source.slice(cursor, range[0]) + emit(child);
64
83
  cursor = range[1];
65
84
  }
@@ -79,8 +98,9 @@ const sanitizePass = (source) => {
79
98
  case 'definition': {
80
99
  const safe = sanitizeParsedNavigationHref(node.url) ??
81
100
  sanitizeParsedAssetUrl(node.url);
82
- if (safe === node.url)
101
+ if (safe === node.url) {
83
102
  return undefined;
103
+ }
84
104
  const title = node.title ? ` ${escapeTitle(node.title)}` : '';
85
105
  return `[${node.label ?? node.identifier}]: ${safe === null ? BLOCKED_HREF : escapeParsedDestination(safe)}${title}`;
86
106
  }
@@ -100,10 +120,12 @@ const sanitizePass = (source) => {
100
120
  }
101
121
  case 'image': {
102
122
  const safe = sanitizeParsedAssetUrl(node.url);
103
- if (safe === null)
123
+ if (safe === null) {
104
124
  return escapeLinkLabel(node.alt ?? '');
105
- if (safe === node.url)
125
+ }
126
+ if (safe === node.url) {
106
127
  return undefined;
128
+ }
107
129
  const title = node.title ? ` ${escapeTitle(node.title)}` : '';
108
130
  return `![${escapeLinkLabel(node.alt ?? '')}](${escapeParsedDestination(safe)}${title})`;
109
131
  }
@@ -114,12 +136,15 @@ const sanitizePass = (source) => {
114
136
  return safe === null ? raw.slice(1, -1) : undefined;
115
137
  }
116
138
  // A GFM literal (`www.x.com`) is http(s) or mailto by construction.
117
- if (!raw.startsWith('['))
139
+ if (!raw.startsWith('[')) {
118
140
  return undefined;
119
- if (safe === null)
141
+ }
142
+ if (safe === null) {
120
143
  return emitLabel(node);
121
- if (safe === node.url)
144
+ }
145
+ if (safe === node.url) {
122
146
  return undefined;
147
+ }
123
148
  const title = node.title ? ` ${escapeTitle(node.title)}` : '';
124
149
  return `[${emitLabel(node)}](${escapeParsedDestination(safe)}${title})`;
125
150
  }
@@ -129,57 +154,68 @@ const sanitizePass = (source) => {
129
154
  };
130
155
  const emit = (node) => {
131
156
  const replaced = rewrite(node);
132
- if (replaced !== undefined)
157
+ if (replaced !== undefined) {
133
158
  return replaced;
159
+ }
134
160
  const range = offsets(node);
135
- if (!range)
161
+ if (!range) {
136
162
  return '';
163
+ }
137
164
  return 'children' in node
138
165
  ? emitChildren(range[0], range[1], node.children)
139
166
  : source.slice(...range);
140
167
  };
141
168
  return emitChildren(0, source.length, root.children);
142
169
  };
143
- /** Sanitizes GFM destinations and HTML; excessive syntax or length degrades to inert text. */
144
- export const sanitizeMarkdownSource = (markdown) => {
145
- if (exceedsParseBudget(markdown))
146
- return inert(markdown);
170
+ /** {@link sanitizeMarkdownSource}'s result, and whether it degraded to inert text. */
171
+ export const sanitizeAuthoredSource = (markdown) => {
172
+ if (exceedsParseBudget(markdown)) {
173
+ return { markdown: inert(markdown), inert: true };
174
+ }
147
175
  let current = markdown;
148
176
  try {
149
177
  for (let pass = 0; pass < MAX_PASSES; pass++) {
150
178
  const next = sanitizePass(current);
151
- if (next === current)
152
- return current;
179
+ if (next === current) {
180
+ return { markdown: current, inert: false };
181
+ }
153
182
  current = next;
154
183
  }
155
184
  }
156
185
  catch (error) {
157
186
  // The parser recurses per nesting level, so inline nesting deep enough
158
187
  // to exhaust the stack lands here.
159
- if (!(error instanceof RangeError))
188
+ if (!(error instanceof RangeError)) {
160
189
  throw error;
190
+ }
161
191
  }
162
- return inert(current);
192
+ return { markdown: inert(current), inert: true };
163
193
  };
194
+ /** Sanitizes GFM destinations and HTML; excessive syntax or length degrades to inert text. */
195
+ export const sanitizeMarkdownSource = (markdown) => sanitizeAuthoredSource(markdown).markdown;
164
196
  // No link, image, definition, or tag can survive without `[` or `<`.
165
- const inert = (markdown) => markdown.replace(/[[\]\\]/g, '\\$&').replace(/</g, '&lt;');
197
+ export const inert = (markdown) => markdown.replace(/[[\]\\]/g, '\\$&').replace(/</g, '&lt;');
166
198
  // GFM parsing is superlinear for some delimiter runs, even without nesting.
167
199
  const LINE_PREFIX_RE = /^(?:[ \t>]|[-*+](?=[ \t])|\d{1,9}[.)](?=[ \t]))+/gm;
168
200
  const MAX_LINE_PREFIX = 256;
169
- const INLINE_DELIMITER_RE = /[[\]*`~<>|\\]|(?<![\p{L}\p{N}])_|_(?![\p{L}\p{N}])/gu;
201
+ // An escaped punctuation character opens nothing, so `\*` counts as one.
202
+ const INLINE_DELIMITER_RE = /\\[!-/:-@[-`{-~]|[[\]*`~<>|\\]|(?<![\p{L}\p{N}])_|_(?![\p{L}\p{N}])/gu;
170
203
  const MAX_INLINE_DELIMITERS = 2048;
171
204
  const MAX_PARSE_LENGTH = 16_384;
172
- const exceedsParseBudget = (markdown) => {
173
- if (markdown.length > MAX_PARSE_LENGTH)
205
+ export const exceedsParseBudget = (markdown) => {
206
+ if (markdown.length > MAX_PARSE_LENGTH) {
174
207
  return true;
208
+ }
175
209
  for (const [prefix] of markdown.matchAll(LINE_PREFIX_RE)) {
176
- if (prefix.length > MAX_LINE_PREFIX)
210
+ if (prefix.length > MAX_LINE_PREFIX) {
177
211
  return true;
212
+ }
178
213
  }
179
214
  let delimiters = 0;
180
215
  for (const _ of markdown.matchAll(INLINE_DELIMITER_RE)) {
181
- if (++delimiters > MAX_INLINE_DELIMITERS)
216
+ if (++delimiters > MAX_INLINE_DELIMITERS) {
182
217
  return true;
218
+ }
183
219
  }
184
220
  return false;
185
221
  };
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/render/markdown/format.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\n// Authored Markdown source made safe to print, for `md.authored`.\n\nimport type { Definition, Nodes, Parents } from 'mdast';\nimport { fromMarkdown } from 'mdast-util-from-markdown';\nimport { gfmFromMarkdown } from 'mdast-util-gfm';\nimport { gfm } from 'micromark-extension-gfm';\n\nimport {\n BLOCKED_HREF,\n sanitizeParsedAssetUrl,\n sanitizeParsedNavigationHref,\n} from '../../validate/url';\n\n// Escapes label characters that could close a `[...]` early and smuggle in a\n// hostile destination of their own.\nconst escapeLinkLabel = (label: string): string =>\n label.replace(/[[\\]\\\\]/g, '\\\\$&');\n\n// Percent-encodes destination characters that would terminate the `(...)`\n// early or read as a link title. `encodeURIComponent` leaves `(` and `)`\n// unescaped by spec, so those two are mapped by hand.\nconst escapeLinkDestination = (href: string): string =>\n href.replace(/[()\\s\\\\]/g, (char) => {\n if (char === '(') return '%28';\n if (char === ')') return '%29';\n return encodeURIComponent(char);\n });\n\nconst escapeParsedDestination = (href: string): string =>\n escapeLinkDestination(href.replace(/&/g, '&amp;'));\n\nlet parseOptions: Parameters<typeof fromMarkdown>[1] | undefined;\n\n// Each pass can expose a new sink (an escaped HTML block reveals the Markdown\n// inside it; a blocked link's label may close an outer `](`), so passes repeat\n// until the source is stable.\nconst MAX_PASSES = 16;\n\nconst escapeTitle = (title: string): string =>\n `\"${title.replace(/[\"\\\\]/g, '\\\\$&')}\"`;\n\nconst offsets = (node: Nodes): [number, number] | undefined => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n return start === undefined || end === undefined ? undefined : [start, end];\n};\n\nconst sanitizePass = (source: string): string => {\n parseOptions ??= {\n extensions: [gfm()],\n mdastExtensions: [gfmFromMarkdown()],\n };\n const root = fromMarkdown(source, parseOptions);\n const definitions = new Map<string, Definition>();\n const pending: Nodes[] = [...root.children].reverse();\n while (pending.length) {\n const node = pending.pop()!;\n if (node.type === 'definition' && !definitions.has(node.identifier)) {\n definitions.set(node.identifier, node);\n }\n if ('children' in node) pending.push(...[...node.children].reverse());\n }\n\n const slice = (node: Nodes): string => {\n const range = offsets(node);\n return range ? source.slice(...range) : '';\n };\n\n const emitChildren = (\n start: number,\n end: number,\n children: readonly Nodes[]\n ): string => {\n let out = '';\n let cursor = start;\n for (const child of children) {\n const range = offsets(child);\n if (!range) continue;\n out += source.slice(cursor, range[0]) + emit(child);\n cursor = range[1];\n }\n return out + source.slice(cursor, end);\n };\n\n const emitLabel = (node: Parents): string => {\n const first = node.children[0];\n const last = node.children[node.children.length - 1];\n const from = first && offsets(first);\n const to = last && offsets(last);\n return from && to ? emitChildren(from[0], to[1], node.children) : '';\n };\n\n const rewrite = (node: Nodes): string | undefined => {\n switch (node.type) {\n case 'html':\n return slice(node).replace(/</g, '&lt;');\n case 'definition': {\n const safe =\n sanitizeParsedNavigationHref(node.url) ??\n sanitizeParsedAssetUrl(node.url);\n if (safe === node.url) return undefined;\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `[${node.label ?? node.identifier}]: ${\n safe === null ? BLOCKED_HREF : escapeParsedDestination(safe)\n }${title}`;\n }\n case 'imageReference': {\n const definition = definitions.get(node.identifier);\n return definition && sanitizeParsedAssetUrl(definition.url) === null\n ? escapeLinkLabel(node.alt ?? '')\n : undefined;\n }\n case 'linkReference': {\n const definition = definitions.get(node.identifier);\n return definition &&\n sanitizeParsedNavigationHref(definition.url) === null &&\n sanitizeParsedAssetUrl(definition.url) !== null\n ? emitLabel(node)\n : undefined;\n }\n case 'image': {\n const safe = sanitizeParsedAssetUrl(node.url);\n if (safe === null) return escapeLinkLabel(node.alt ?? '');\n if (safe === node.url) return undefined;\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `![${escapeLinkLabel(node.alt ?? '')}](${escapeParsedDestination(\n safe\n )}${title})`;\n }\n case 'link': {\n const raw = slice(node);\n const safe = sanitizeParsedNavigationHref(node.url);\n if (raw.startsWith('<')) {\n return safe === null ? raw.slice(1, -1) : undefined;\n }\n // A GFM literal (`www.x.com`) is http(s) or mailto by construction.\n if (!raw.startsWith('[')) return undefined;\n if (safe === null) return emitLabel(node);\n if (safe === node.url) return undefined;\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `[${emitLabel(node)}](${escapeParsedDestination(safe)}${title})`;\n }\n default:\n return undefined;\n }\n };\n\n const emit = (node: Nodes): string => {\n const replaced = rewrite(node);\n if (replaced !== undefined) return replaced;\n const range = offsets(node);\n if (!range) return '';\n return 'children' in node\n ? emitChildren(range[0], range[1], node.children)\n : source.slice(...range);\n };\n\n return emitChildren(0, source.length, root.children);\n};\n\n/** Sanitizes GFM destinations and HTML; excessive syntax or length degrades to inert text. */\nexport const sanitizeMarkdownSource = (markdown: string): string => {\n if (exceedsParseBudget(markdown)) return inert(markdown);\n let current = markdown;\n try {\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n const next = sanitizePass(current);\n if (next === current) return current;\n current = next;\n }\n } catch (error) {\n // The parser recurses per nesting level, so inline nesting deep enough\n // to exhaust the stack lands here.\n if (!(error instanceof RangeError)) throw error;\n }\n return inert(current);\n};\n\n// No link, image, definition, or tag can survive without `[` or `<`.\nconst inert = (markdown: string): string =>\n markdown.replace(/[[\\]\\\\]/g, '\\\\$&').replace(/</g, '&lt;');\n\n// GFM parsing is superlinear for some delimiter runs, even without nesting.\nconst LINE_PREFIX_RE = /^(?:[ \\t>]|[-*+](?=[ \\t])|\\d{1,9}[.)](?=[ \\t]))+/gm;\nconst MAX_LINE_PREFIX = 256;\nconst INLINE_DELIMITER_RE =\n /[[\\]*`~<>|\\\\]|(?<![\\p{L}\\p{N}])_|_(?![\\p{L}\\p{N}])/gu;\nconst MAX_INLINE_DELIMITERS = 2048;\n\nconst MAX_PARSE_LENGTH = 16_384;\n\nconst exceedsParseBudget = (markdown: string): boolean => {\n if (markdown.length > MAX_PARSE_LENGTH) return true;\n for (const [prefix] of markdown.matchAll(LINE_PREFIX_RE)) {\n if (prefix.length > MAX_LINE_PREFIX) return true;\n }\n let delimiters = 0;\n for (const _ of markdown.matchAll(INLINE_DELIMITER_RE)) {\n if (++delimiters > MAX_INLINE_DELIMITERS) return true;\n }\n return false;\n};\n"]}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/render/markdown/format.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAE9C,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,6EAA6E;AAC7E,oCAAoC;AACpC,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CAChD,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAEpC,0EAA0E;AAC1E,yEAAyE;AACzE,sDAAsD;AACtD,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAU,EAAE,CACrD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;IACjC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEL,MAAM,uBAAuB,GAAG,CAAC,IAAY,EAAU,EAAE,CACvD,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAErD,IAAI,YAA4D,CAAC;AAEjE,MAAM,KAAK,GAAG,CAAC,MAAc,EAAQ,EAAE,CACrC,YAAY,CACV,MAAM,EACN,CAAC,YAAY,KAAK;IAChB,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC;IACnB,eAAe,EAAE,CAAC,eAAe,EAAE,CAAC;CACrC,CAAC,CACH,CAAC;AAEJ,wJAAwJ;AACxJ,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAA6B,EAAE;IAC5E,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE,CAAC;YACnC,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,8EAA8E;AAC9E,+EAA+E;AAC/E,8BAA8B;AAC9B,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE,CAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;AAEzC,MAAM,OAAO,GAAG,CAAC,IAAW,EAAgC,EAAE;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;IACtC,OAAO,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,MAAc,EAAU,EAAE;IAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;IAClD,MAAM,OAAO,GAAY,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;IACtD,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACpE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,IAAW,EAAU,EAAE;QACpC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CACnB,KAAa,EACb,GAAW,EACX,QAA0B,EAClB,EAAE;QACV,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,SAAS;YACX,CAAC;YACD,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,IAAa,EAAU,EAAE;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,IAAW,EAAsB,EAAE;QAClD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,MAAM;gBACT,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,IAAI,GACR,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC;oBACtC,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnC,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;oBACtB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,MACtC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAC7D,GAAG,KAAK,EAAE,CAAC;YACb,CAAC;YACD,KAAK,gBAAgB,CAAC,CAAC,CAAC;gBACtB,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACpD,OAAO,UAAU,IAAI,sBAAsB,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI;oBAClE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;oBACjC,CAAC,CAAC,SAAS,CAAC;YAChB,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACrB,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACpD,OAAO,UAAU;oBACf,4BAA4B,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI;oBACrD,sBAAsB,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI;oBAC/C,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;oBACjB,CAAC,CAAC,SAAS,CAAC;YAChB,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC9C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;gBACzC,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;oBACtB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,OAAO,KAAK,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,uBAAuB,CACrE,IAAI,CACL,GAAG,KAAK,GAAG,CAAC;YACf,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxB,MAAM,IAAI,GAAG,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACtD,CAAC;gBACD,oEAAoE;gBACpE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;oBACtB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,uBAAuB,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC;YAC1E,CAAC;YACD;gBACE,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,IAAW,EAAU,EAAE;QACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,UAAU,IAAI,IAAI;YACvB,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;YACjD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,QAAgB,EACsB,EAAE;IACxC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,IAAI,CAAC;QACH,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC7C,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uEAAuE;QACvE,mCAAmC;QACnC,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE,CAAC;YACnC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACnD,CAAC,CAAC;AAEF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAU,EAAE,CACjE,sBAAsB,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;AAE5C,qEAAqE;AACrE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAU,EAAE,CAChD,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAE7D,4EAA4E;AAC5E,MAAM,cAAc,GAAG,oDAAoD,CAAC;AAC5E,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,yEAAyE;AACzE,MAAM,mBAAmB,GACvB,uEAAuE,CAAC;AAC1E,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAW,EAAE;IAC9D,IAAI,QAAQ,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACzD,IAAI,MAAM,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACvD,IAAI,EAAE,UAAU,GAAG,qBAAqB,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\n// Authored Markdown source made safe to print, for `md.authored`, and the GFM\n// parse it shares with the Slack fallback.\n\nimport type { Definition, Nodes, Parents, Root } from 'mdast';\nimport { fromMarkdown } from 'mdast-util-from-markdown';\nimport { gfmFromMarkdown } from 'mdast-util-gfm';\nimport { gfm } from 'micromark-extension-gfm';\n\nimport {\n BLOCKED_HREF,\n sanitizeParsedAssetUrl,\n sanitizeParsedNavigationHref,\n} from '../../validate/url';\n\n// Escapes label characters that could close a `[...]` early and smuggle in a\n// hostile destination of their own.\nconst escapeLinkLabel = (label: string): string =>\n label.replace(/[[\\]\\\\]/g, '\\\\$&');\n\n// Percent-encodes destination characters that would terminate the `(...)`\n// early or read as a link title. `encodeURIComponent` leaves `(` and `)`\n// unescaped by spec, so those two are mapped by hand.\nconst escapeLinkDestination = (href: string): string =>\n href.replace(/[()\\s\\\\]/g, (char) => {\n if (char === '(') {\n return '%28';\n }\n if (char === ')') {\n return '%29';\n }\n return encodeURIComponent(char);\n });\n\nconst escapeParsedDestination = (href: string): string =>\n escapeLinkDestination(href.replace(/&/g, '&amp;'));\n\nlet parseOptions: Parameters<typeof fromMarkdown>[1] | undefined;\n\nconst parse = (source: string): Root =>\n fromMarkdown(\n source,\n (parseOptions ??= {\n extensions: [gfm()],\n mdastExtensions: [gfmFromMarkdown()],\n })\n );\n\n/** `markdown` as flat GFM mdast blocks, typed `unknown` so no declaration names mdast; `null` past the parse budget or the parser's recursion depth. */\nexport const parseGfmBlocks = (markdown: string): readonly unknown[] | null => {\n if (exceedsParseBudget(markdown)) {\n return null;\n }\n try {\n return parse(markdown).children;\n } catch (error) {\n if (!(error instanceof RangeError)) {\n throw error;\n }\n return null;\n }\n};\n\n// Each pass can expose a new sink (an escaped HTML block reveals the Markdown\n// inside it; a blocked link's label may close an outer `](`), so passes repeat\n// until the source is stable.\nconst MAX_PASSES = 16;\n\nconst escapeTitle = (title: string): string =>\n `\"${title.replace(/[\"\\\\]/g, '\\\\$&')}\"`;\n\nconst offsets = (node: Nodes): [number, number] | undefined => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n return start === undefined || end === undefined ? undefined : [start, end];\n};\n\nconst sanitizePass = (source: string): string => {\n const root = parse(source);\n const definitions = new Map<string, Definition>();\n const pending: Nodes[] = [...root.children].reverse();\n while (pending.length) {\n const node = pending.pop()!;\n if (node.type === 'definition' && !definitions.has(node.identifier)) {\n definitions.set(node.identifier, node);\n }\n if ('children' in node) {\n pending.push(...[...node.children].reverse());\n }\n }\n\n const slice = (node: Nodes): string => {\n const range = offsets(node);\n return range ? source.slice(...range) : '';\n };\n\n const emitChildren = (\n start: number,\n end: number,\n children: readonly Nodes[]\n ): string => {\n let out = '';\n let cursor = start;\n for (const child of children) {\n const range = offsets(child);\n if (!range) {\n continue;\n }\n out += source.slice(cursor, range[0]) + emit(child);\n cursor = range[1];\n }\n return out + source.slice(cursor, end);\n };\n\n const emitLabel = (node: Parents): string => {\n const first = node.children[0];\n const last = node.children[node.children.length - 1];\n const from = first && offsets(first);\n const to = last && offsets(last);\n return from && to ? emitChildren(from[0], to[1], node.children) : '';\n };\n\n const rewrite = (node: Nodes): string | undefined => {\n switch (node.type) {\n case 'html':\n return slice(node).replace(/</g, '&lt;');\n case 'definition': {\n const safe =\n sanitizeParsedNavigationHref(node.url) ??\n sanitizeParsedAssetUrl(node.url);\n if (safe === node.url) {\n return undefined;\n }\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `[${node.label ?? node.identifier}]: ${\n safe === null ? BLOCKED_HREF : escapeParsedDestination(safe)\n }${title}`;\n }\n case 'imageReference': {\n const definition = definitions.get(node.identifier);\n return definition && sanitizeParsedAssetUrl(definition.url) === null\n ? escapeLinkLabel(node.alt ?? '')\n : undefined;\n }\n case 'linkReference': {\n const definition = definitions.get(node.identifier);\n return definition &&\n sanitizeParsedNavigationHref(definition.url) === null &&\n sanitizeParsedAssetUrl(definition.url) !== null\n ? emitLabel(node)\n : undefined;\n }\n case 'image': {\n const safe = sanitizeParsedAssetUrl(node.url);\n if (safe === null) {\n return escapeLinkLabel(node.alt ?? '');\n }\n if (safe === node.url) {\n return undefined;\n }\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `![${escapeLinkLabel(node.alt ?? '')}](${escapeParsedDestination(\n safe\n )}${title})`;\n }\n case 'link': {\n const raw = slice(node);\n const safe = sanitizeParsedNavigationHref(node.url);\n if (raw.startsWith('<')) {\n return safe === null ? raw.slice(1, -1) : undefined;\n }\n // A GFM literal (`www.x.com`) is http(s) or mailto by construction.\n if (!raw.startsWith('[')) {\n return undefined;\n }\n if (safe === null) {\n return emitLabel(node);\n }\n if (safe === node.url) {\n return undefined;\n }\n const title = node.title ? ` ${escapeTitle(node.title)}` : '';\n return `[${emitLabel(node)}](${escapeParsedDestination(safe)}${title})`;\n }\n default:\n return undefined;\n }\n };\n\n const emit = (node: Nodes): string => {\n const replaced = rewrite(node);\n if (replaced !== undefined) {\n return replaced;\n }\n const range = offsets(node);\n if (!range) {\n return '';\n }\n return 'children' in node\n ? emitChildren(range[0], range[1], node.children)\n : source.slice(...range);\n };\n\n return emitChildren(0, source.length, root.children);\n};\n\n/** {@link sanitizeMarkdownSource}'s result, and whether it degraded to inert text. */\nexport const sanitizeAuthoredSource = (\n markdown: string\n): { markdown: string; inert: boolean } => {\n if (exceedsParseBudget(markdown)) {\n return { markdown: inert(markdown), inert: true };\n }\n let current = markdown;\n try {\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n const next = sanitizePass(current);\n if (next === current) {\n return { markdown: current, inert: false };\n }\n current = next;\n }\n } catch (error) {\n // The parser recurses per nesting level, so inline nesting deep enough\n // to exhaust the stack lands here.\n if (!(error instanceof RangeError)) {\n throw error;\n }\n }\n return { markdown: inert(current), inert: true };\n};\n\n/** Sanitizes GFM destinations and HTML; excessive syntax or length degrades to inert text. */\nexport const sanitizeMarkdownSource = (markdown: string): string =>\n sanitizeAuthoredSource(markdown).markdown;\n\n// No link, image, definition, or tag can survive without `[` or `<`.\nexport const inert = (markdown: string): string =>\n markdown.replace(/[[\\]\\\\]/g, '\\\\$&').replace(/</g, '&lt;');\n\n// GFM parsing is superlinear for some delimiter runs, even without nesting.\nconst LINE_PREFIX_RE = /^(?:[ \\t>]|[-*+](?=[ \\t])|\\d{1,9}[.)](?=[ \\t]))+/gm;\nconst MAX_LINE_PREFIX = 256;\n// An escaped punctuation character opens nothing, so `\\*` counts as one.\nconst INLINE_DELIMITER_RE =\n /\\\\[!-/:-@[-`{-~]|[[\\]*`~<>|\\\\]|(?<![\\p{L}\\p{N}])_|_(?![\\p{L}\\p{N}])/gu;\nconst MAX_INLINE_DELIMITERS = 2048;\n\nconst MAX_PARSE_LENGTH = 16_384;\n\nexport const exceedsParseBudget = (markdown: string): boolean => {\n if (markdown.length > MAX_PARSE_LENGTH) {\n return true;\n }\n for (const [prefix] of markdown.matchAll(LINE_PREFIX_RE)) {\n if (prefix.length > MAX_LINE_PREFIX) {\n return true;\n }\n }\n let delimiters = 0;\n for (const _ of markdown.matchAll(INLINE_DELIMITER_RE)) {\n if (++delimiters > MAX_INLINE_DELIMITERS) {\n return true;\n }\n }\n return false;\n};\n"]}
@@ -0,0 +1,14 @@
1
+ /** A tag found by {@link findHostTags}. */
2
+ export interface HostTag {
3
+ /** Offset of the `<` in the source. */
4
+ readonly index: number;
5
+ /** The tag as written. */
6
+ readonly raw: string;
7
+ /** The name as listed in the options. */
8
+ readonly name: string;
9
+ /** Values as written, keyed by lower-cased name; a bare attribute is `''`. */
10
+ readonly attributes: Readonly<Record<string, string>>;
11
+ }
12
+ /** Every tag named in `names` (matched case-insensitively and whole), in source order. */
13
+ export declare const findHostTags: (source: string, names: readonly string[]) => HostTag[];
14
+ //# sourceMappingURL=host_tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host_tags.d.ts","sourceRoot":"","sources":["../../../src/render/markdown/host_tags.ts"],"names":[],"mappings":"AAaA,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AA6CD,0FAA0F;AAC1F,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,OAAO,SAAS,MAAM,EAAE,KACvB,OAAO,EAwBT,CAAC"}