@bendyline/squisq 1.4.1 → 1.5.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 (216) hide show
  1. package/dist/{Doc-BeSeH2iX.d.ts → Doc-BsMkmzH8.d.ts} +838 -268
  2. package/dist/{ImageEditDoc-BTIvw0oq.d.ts → ImageEditDoc-DvoeHMP9.d.ts} +11 -4
  3. package/dist/{chunk-ZTX4PFFT.js → chunk-2OIBZYKP.js} +75 -2
  4. package/dist/chunk-2OIBZYKP.js.map +1 -0
  5. package/dist/chunk-2UQOHYE2.js +45 -0
  6. package/dist/chunk-2UQOHYE2.js.map +1 -0
  7. package/dist/{chunk-B4EEON3N.js → chunk-4AKUQPEE.js} +536 -103
  8. package/dist/chunk-4AKUQPEE.js.map +1 -0
  9. package/dist/chunk-4ZFRZBU2.js +6582 -0
  10. package/dist/chunk-4ZFRZBU2.js.map +1 -0
  11. package/dist/{chunk-57CVQCFX.js → chunk-7MQGNR76.js} +79 -3
  12. package/dist/chunk-7MQGNR76.js.map +1 -0
  13. package/dist/{chunk-5WFRKURX.js → chunk-DLXZMS5K.js} +4 -2
  14. package/dist/chunk-DLXZMS5K.js.map +1 -0
  15. package/dist/{chunk-MYIH7FWD.js → chunk-FBKP5CAO.js} +1 -1
  16. package/dist/chunk-FBKP5CAO.js.map +1 -0
  17. package/dist/chunk-KZNXZ5SM.js +333 -0
  18. package/dist/chunk-KZNXZ5SM.js.map +1 -0
  19. package/dist/{chunk-WMOI7FN3.js → chunk-LRCV7N7F.js} +12 -2
  20. package/dist/{chunk-WMOI7FN3.js.map → chunk-LRCV7N7F.js.map} +1 -1
  21. package/dist/{chunk-3K5OG6KI.js → chunk-OH43RPTP.js} +403 -187
  22. package/dist/chunk-OH43RPTP.js.map +1 -0
  23. package/dist/{chunk-H3AXU4MJ.js → chunk-OKJOQXK4.js} +149 -2
  24. package/dist/chunk-OKJOQXK4.js.map +1 -0
  25. package/dist/chunk-PGGGKYWG.js +1 -0
  26. package/dist/chunk-PGGGKYWG.js.map +1 -0
  27. package/dist/{chunk-7UDSRZKG.js → chunk-Q3ROPT5H.js} +35 -14
  28. package/dist/chunk-Q3ROPT5H.js.map +1 -0
  29. package/dist/chunk-QE7TWGVT.js +178 -0
  30. package/dist/chunk-QE7TWGVT.js.map +1 -0
  31. package/dist/chunk-RUDYOTA6.js +345 -0
  32. package/dist/chunk-RUDYOTA6.js.map +1 -0
  33. package/dist/chunk-TVSGLUID.js +596 -0
  34. package/dist/chunk-TVSGLUID.js.map +1 -0
  35. package/dist/chunk-ZLQKNOZQ.js +1 -0
  36. package/dist/chunk-ZLQKNOZQ.js.map +1 -0
  37. package/dist/doc/index.d.ts +4 -4
  38. package/dist/doc/index.js +124 -6
  39. package/dist/generate/index.d.ts +9 -2
  40. package/dist/generate/index.js +1 -1
  41. package/dist/icons/index.d.ts +3 -26
  42. package/dist/icons/index.js +13 -0
  43. package/dist/icons/inlineIconMarker.d.ts +1 -0
  44. package/dist/icons/inlineIconMarker.js +15 -0
  45. package/dist/icons/inlineIconMarker.js.map +1 -0
  46. package/dist/imageEdit/index.d.ts +11 -5
  47. package/dist/imageEdit/index.js +4 -1
  48. package/dist/index.d.ts +11 -8
  49. package/dist/index.js +243 -24
  50. package/dist/inlineIconMarker-CiE8Hlvz.d.ts +59 -0
  51. package/dist/markdown/index.d.ts +212 -3
  52. package/dist/markdown/index.js +40 -7
  53. package/dist/recommend/index.d.ts +1 -1
  54. package/dist/recommend/index.js +3 -2
  55. package/dist/schemas/index.d.ts +28 -8
  56. package/dist/schemas/index.js +35 -5
  57. package/dist/spatial/index.d.ts +9 -4
  58. package/dist/spatial/index.js +1 -1
  59. package/dist/story/index.d.ts +906 -40
  60. package/dist/story/index.js +124 -6
  61. package/dist/{themeLibrary-BHjJ0Qx6.d.ts → themeLibrary-DQQKuRMx.d.ts} +1 -1
  62. package/dist/transform/index.d.ts +48 -10
  63. package/dist/transform/index.js +17 -481
  64. package/dist/transform/index.js.map +1 -1
  65. package/dist/{types-BdZkdJ3z.d.ts → types-DlAZ7MW4.d.ts} +115 -1
  66. package/package.json +6 -1
  67. package/src/__tests__/animationUtils.test.ts +40 -0
  68. package/src/__tests__/annotationCoercion.test.ts +243 -0
  69. package/src/__tests__/applyRenderStyle.test.ts +146 -0
  70. package/src/__tests__/atmosphereLayers.test.ts +108 -0
  71. package/src/__tests__/attrTokens.test.ts +162 -0
  72. package/src/__tests__/customTemplateSample.test.ts +83 -0
  73. package/src/__tests__/customTemplatesFrontmatter.test.ts +205 -0
  74. package/src/__tests__/customThemesFrontmatter.test.ts +118 -0
  75. package/src/__tests__/diagramBlock.test.ts +122 -0
  76. package/src/__tests__/diagramLayout.test.ts +134 -0
  77. package/src/__tests__/drawing.test.ts +109 -0
  78. package/src/__tests__/drawingBlock.test.ts +124 -0
  79. package/src/__tests__/drawingLayout.test.ts +171 -0
  80. package/src/__tests__/geohash.test.ts +6 -5
  81. package/src/__tests__/getLayers.test.ts +6 -2
  82. package/src/__tests__/getLayersFallback.test.ts +103 -0
  83. package/src/__tests__/imageEditExportSvg.test.ts +70 -0
  84. package/src/__tests__/imageEditVersions.test.ts +72 -0
  85. package/src/__tests__/inlineIconMarker.test.ts +36 -0
  86. package/src/__tests__/layoutBlock.test.ts +83 -0
  87. package/src/__tests__/layoutLayout.test.ts +169 -0
  88. package/src/__tests__/markdown.test.ts +23 -0
  89. package/src/__tests__/markdownSanitize.test.ts +64 -0
  90. package/src/__tests__/markdownToDoc.test.ts +223 -2
  91. package/src/__tests__/mediaAnnotations.test.ts +64 -0
  92. package/src/__tests__/mediaSchedule.test.ts +118 -0
  93. package/src/__tests__/pandocAttrParse.test.ts +187 -0
  94. package/src/__tests__/resolveDocTheme.test.ts +55 -0
  95. package/src/__tests__/rootExports.test.ts +43 -0
  96. package/src/__tests__/shapeGeometry.test.ts +89 -0
  97. package/src/__tests__/shapeVocabulary.test.ts +133 -0
  98. package/src/__tests__/structuredData.test.ts +179 -0
  99. package/src/__tests__/templateAnnotationParse.test.ts +108 -0
  100. package/src/__tests__/templateMetadata.test.ts +21 -0
  101. package/src/__tests__/templates.test.ts +145 -4
  102. package/src/__tests__/themeCompile.test.ts +42 -0
  103. package/src/__tests__/themeValidator.test.ts +6 -0
  104. package/src/__tests__/transformV2.test.ts +137 -0
  105. package/src/__tests__/transitionNormalize.test.ts +61 -0
  106. package/src/__tests__/validateDoc.test.ts +100 -0
  107. package/src/doc/customTemplatesFrontmatter.ts +308 -0
  108. package/src/doc/customThemesFrontmatter.ts +90 -0
  109. package/src/doc/docToMarkdown.ts +73 -4
  110. package/src/doc/getLayers.ts +40 -17
  111. package/src/doc/index.ts +35 -1
  112. package/src/doc/markdownToDoc.ts +333 -12
  113. package/src/doc/mediaAnnotations.ts +118 -0
  114. package/src/doc/resolveDocTheme.ts +55 -0
  115. package/src/doc/structuredData.ts +230 -0
  116. package/src/doc/templateInputs.ts +240 -0
  117. package/src/doc/templates/__tests__/customTemplate.test.ts +151 -0
  118. package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +110 -0
  119. package/src/doc/templates/accentImage.ts +30 -6
  120. package/src/doc/templates/captionUtils.ts +23 -0
  121. package/src/doc/templates/comparisonBar.ts +26 -18
  122. package/src/doc/templates/coverBlock.ts +7 -4
  123. package/src/doc/templates/customTemplate.ts +45 -0
  124. package/src/doc/templates/dataTable.ts +37 -19
  125. package/src/doc/templates/dateEvent.ts +41 -20
  126. package/src/doc/templates/definitionCard.ts +26 -18
  127. package/src/doc/templates/diagramBlock.ts +204 -0
  128. package/src/doc/templates/diagramLayout.ts +159 -0
  129. package/src/doc/templates/drawingBlock.ts +325 -0
  130. package/src/doc/templates/drawingLayout.ts +539 -0
  131. package/src/doc/templates/factCard.ts +51 -25
  132. package/src/doc/templates/fallbackBlock.ts +123 -0
  133. package/src/doc/templates/featureBlock.ts +20 -13
  134. package/src/doc/templates/fullBleedQuote.ts +18 -8
  135. package/src/doc/templates/imageWithCaption.ts +22 -9
  136. package/src/doc/templates/index.ts +215 -46
  137. package/src/doc/templates/layoutBlock.ts +43 -0
  138. package/src/doc/templates/layoutLayout.ts +243 -0
  139. package/src/doc/templates/listBlock.ts +56 -30
  140. package/src/doc/templates/mapBlock.ts +15 -12
  141. package/src/doc/templates/metadata.ts +120 -0
  142. package/src/doc/templates/persistentLayers.ts +129 -11
  143. package/src/doc/templates/photoGrid.ts +23 -12
  144. package/src/doc/templates/pullQuote.ts +30 -12
  145. package/src/doc/templates/quoteBlock.ts +54 -29
  146. package/src/doc/templates/sectionHeader.ts +25 -11
  147. package/src/doc/templates/statHighlight.ts +39 -22
  148. package/src/doc/templates/titleBlock.ts +59 -21
  149. package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +221 -0
  150. package/src/doc/templates/tokens/resolveTokens.ts +0 -0
  151. package/src/doc/templates/twoColumn.ts +48 -30
  152. package/src/doc/templates/videoPullQuote.ts +22 -12
  153. package/src/doc/templates/videoWithCaption.ts +13 -8
  154. package/src/doc/utils/animationUtils.ts +267 -3
  155. package/src/doc/utils/applyRenderStyle.ts +113 -0
  156. package/src/doc/utils/imageTreatment.ts +70 -0
  157. package/src/doc/utils/shapeGeometry.ts +464 -0
  158. package/src/doc/utils/themeUtils.ts +75 -1
  159. package/src/doc/validate.ts +476 -0
  160. package/src/generate/slideshowGenerator.ts +7 -0
  161. package/src/icons/index.ts +8 -0
  162. package/src/icons/inlineIconMarker.ts +73 -0
  163. package/src/imageEdit/export.ts +85 -2
  164. package/src/imageEdit/index.ts +1 -0
  165. package/src/imageEdit/persistence.ts +51 -0
  166. package/src/index.ts +2 -0
  167. package/src/markdown/annotationCoercion.ts +295 -0
  168. package/src/markdown/attrTokens.ts +222 -0
  169. package/src/markdown/convert.ts +229 -26
  170. package/src/markdown/index.ts +36 -0
  171. package/src/markdown/sanitize.ts +298 -0
  172. package/src/markdown/stringify.ts +84 -3
  173. package/src/markdown/types.ts +66 -0
  174. package/src/markdown/utils.ts +49 -1
  175. package/src/recommend/templates.ts +24 -0
  176. package/src/schemas/BlockTemplates.ts +133 -4
  177. package/src/schemas/CustomTemplates.ts +74 -0
  178. package/src/schemas/Doc.ts +353 -29
  179. package/src/schemas/ImageEditDoc.ts +11 -4
  180. package/src/schemas/Media.ts +169 -0
  181. package/src/schemas/Theme.ts +23 -1
  182. package/src/schemas/Transitions.ts +224 -0
  183. package/src/schemas/colorUtils.ts +33 -0
  184. package/src/schemas/fontStacks.ts +5 -2
  185. package/src/schemas/index.ts +3 -0
  186. package/src/schemas/themeCompile.ts +23 -4
  187. package/src/schemas/themeValidator.ts +49 -11
  188. package/src/schemas/themes/cinematic.json +69 -12
  189. package/src/schemas/themes/documentary.json +58 -11
  190. package/src/schemas/themes/gezellig.json +60 -11
  191. package/src/schemas/themes/magazine.json +54 -9
  192. package/src/schemas/themes/morning-light.json +52 -9
  193. package/src/schemas/themes/standard-dark.json +48 -13
  194. package/src/schemas/themes/standard.json +44 -12
  195. package/src/schemas/themes/tech-dark.json +65 -12
  196. package/src/spatial/Geohash.ts +52 -21
  197. package/src/transform/applyTransform.ts +43 -4
  198. package/src/transform/index.ts +1 -0
  199. package/src/transform/registry.ts +44 -13
  200. package/src/transform/styles/dataDriven.ts +2 -1
  201. package/src/transform/styles/documentary.ts +2 -1
  202. package/src/transform/styles/magazine.ts +3 -1
  203. package/src/transform/styles/minimal.ts +2 -1
  204. package/src/transform/styles/narrative.ts +3 -1
  205. package/src/transform/templateSelector.ts +87 -11
  206. package/src/transform/types.ts +35 -2
  207. package/dist/chunk-3K5OG6KI.js.map +0 -1
  208. package/dist/chunk-57CVQCFX.js.map +0 -1
  209. package/dist/chunk-5WFRKURX.js.map +0 -1
  210. package/dist/chunk-7UDSRZKG.js.map +0 -1
  211. package/dist/chunk-B4EEON3N.js.map +0 -1
  212. package/dist/chunk-H3AXU4MJ.js.map +0 -1
  213. package/dist/chunk-KSWJR66U.js +0 -3706
  214. package/dist/chunk-KSWJR66U.js.map +0 -1
  215. package/dist/chunk-MYIH7FWD.js.map +0 -1
  216. package/dist/chunk-ZTX4PFFT.js.map +0 -1
@@ -1,134 +1,276 @@
1
+ import {
2
+ parseFrontmatter,
3
+ parseHtmlToNodes
4
+ } from "./chunk-OKJOQXK4.js";
1
5
  import {
2
6
  resolveIcon
3
7
  } from "./chunk-DBS6RIFL.js";
4
8
  import {
5
- parseFrontmatter
6
- } from "./chunk-H3AXU4MJ.js";
9
+ TRANSITION_DIRECTIONS,
10
+ TRANSITION_TYPES,
11
+ normalizeTransitionDirection,
12
+ normalizeTransitionType
13
+ } from "./chunk-QE7TWGVT.js";
7
14
 
8
- // src/markdown/parse.ts
9
- import { unified } from "unified";
10
- import remarkParse from "remark-parse";
11
- import remarkGfm from "remark-gfm";
12
- import remarkMath from "remark-math";
13
- import remarkDirective from "remark-directive";
14
- import remarkFrontmatter from "remark-frontmatter";
15
-
16
- // src/markdown/htmlParse.ts
17
- import { fromHtml } from "hast-util-from-html";
18
- var HAST_PROP_TO_ATTR = {
19
- className: "class",
20
- htmlFor: "for",
21
- httpEquiv: "http-equiv",
22
- acceptCharset: "accept-charset"
15
+ // src/markdown/annotationCoercion.ts
16
+ var KNOWN_BLOCK_META_KEYS = {
17
+ x: "number",
18
+ y: "number",
19
+ startTime: "time",
20
+ duration: "time",
21
+ connectsTo: "connectionList",
22
+ transition: "transition",
23
+ transitionDuration: "time",
24
+ transitionDirection: "transitionDirection"
23
25
  };
24
- var VOID_ELEMENTS = /* @__PURE__ */ new Set([
25
- "area",
26
- "base",
27
- "br",
28
- "col",
29
- "embed",
30
- "hr",
31
- "img",
32
- "input",
33
- "link",
34
- "meta",
35
- "param",
36
- "source",
37
- "track",
38
- "wbr"
39
- ]);
40
- function propertyToAttribute(prop) {
41
- if (HAST_PROP_TO_ATTR[prop]) return HAST_PROP_TO_ATTR[prop];
42
- if (prop.length > 4 && prop.startsWith("data") && prop[4] >= "A" && prop[4] <= "Z") {
43
- return "data-" + prop.slice(4).replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()).replace(/^-/, "");
26
+ var BLOCK_META_KEY_DESCRIPTORS = [
27
+ {
28
+ key: "transition",
29
+ description: "Block-to-block transition effect",
30
+ values: TRANSITION_TYPES
31
+ },
32
+ {
33
+ key: "transitionDuration",
34
+ description: "How long the transition lasts",
35
+ valueHint: "seconds \u2014 e.g. 0.7, 700ms"
36
+ },
37
+ {
38
+ key: "transitionDirection",
39
+ description: "Directional variant for the transition",
40
+ values: TRANSITION_DIRECTIONS
41
+ },
42
+ {
43
+ key: "startTime",
44
+ description: "Timeline start time of this block",
45
+ valueHint: "mm:ss or seconds \u2014 e.g. 01:30, 5, 1500ms"
46
+ },
47
+ {
48
+ key: "duration",
49
+ description: "How long this block lasts",
50
+ valueHint: "mm:ss or seconds \u2014 e.g. 45, 1500ms"
51
+ },
52
+ {
53
+ key: "x",
54
+ description: "Horizontal position on the diagram canvas",
55
+ valueHint: "number \u2014 e.g. 600"
56
+ },
57
+ {
58
+ key: "y",
59
+ description: "Vertical position on the diagram canvas",
60
+ valueHint: "number \u2014 e.g. 300"
61
+ },
62
+ {
63
+ key: "connectsTo",
64
+ description: "Diagram connections to other blocks",
65
+ valueHint: "comma-separated target or target:type \u2014 e.g. foo,bar:flow"
66
+ }
67
+ ];
68
+ function coerceAnnotationValues(params) {
69
+ const blockMeta = {};
70
+ const metadata = {};
71
+ const warnings = [];
72
+ let transitionType = null;
73
+ let transitionDuration;
74
+ let transitionDirection;
75
+ for (const [key, raw] of Object.entries(params)) {
76
+ const kind = KNOWN_BLOCK_META_KEYS[key];
77
+ if (!kind) {
78
+ metadata[key] = raw;
79
+ continue;
80
+ }
81
+ if (kind === "number") {
82
+ const n = parseNumber(raw);
83
+ if (n == null) {
84
+ warnings.push(`Invalid number for "${key}": ${JSON.stringify(raw)}`);
85
+ } else {
86
+ blockMeta[key] = n;
87
+ }
88
+ } else if (kind === "time") {
89
+ const s = parseTimeSeconds(raw);
90
+ if (s == null) {
91
+ warnings.push(`Invalid time for "${key}": ${JSON.stringify(raw)}`);
92
+ } else if (key === "transitionDuration") {
93
+ transitionDuration = s;
94
+ } else {
95
+ blockMeta[key] = s;
96
+ }
97
+ } else if (kind === "connectionList") {
98
+ const { list, warning } = parseConnectionList(raw);
99
+ if (warning) warnings.push(`"${key}": ${warning}`);
100
+ blockMeta.connectsTo = list;
101
+ } else if (kind === "transition") {
102
+ const transition = normalizeTransitionType(raw);
103
+ if (transition == null) {
104
+ warnings.push(`Invalid transition for "${key}": ${JSON.stringify(raw)}`);
105
+ } else {
106
+ transitionType = transition;
107
+ }
108
+ } else if (kind === "transitionDirection") {
109
+ const direction = normalizeTransitionDirection(raw);
110
+ if (direction == null) {
111
+ warnings.push(`Invalid transition direction for "${key}": ${JSON.stringify(raw)}`);
112
+ } else {
113
+ transitionDirection = direction;
114
+ }
115
+ }
44
116
  }
45
- if (prop.length > 4 && prop.startsWith("aria") && prop[4] >= "A" && prop[4] <= "Z") {
46
- return "aria-" + prop.slice(4).replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()).replace(/^-/, "");
117
+ if (transitionType) {
118
+ blockMeta.transition = {
119
+ type: transitionType,
120
+ ...transitionDuration !== void 0 ? { duration: transitionDuration } : {},
121
+ ...transitionDirection !== void 0 ? { direction: transitionDirection } : {}
122
+ };
47
123
  }
48
- return prop.toLowerCase();
124
+ return { blockMeta, metadata, warnings };
49
125
  }
50
- function convertHastProperties(properties) {
51
- const attrs = {};
52
- for (const [key, value] of Object.entries(properties)) {
53
- if (value === false || value === void 0 || value === null) continue;
54
- const attrName = propertyToAttribute(key);
55
- if (value === true) {
56
- attrs[attrName] = "";
57
- } else if (Array.isArray(value)) {
58
- attrs[attrName] = value.join(" ");
59
- } else {
60
- attrs[attrName] = String(value);
126
+ function parseNumber(raw) {
127
+ if (raw.trim() === "") return null;
128
+ const n = Number(raw);
129
+ return Number.isFinite(n) ? n : null;
130
+ }
131
+ var TIME_BARE_RE = /^\d+(?:\.\d+)?$/;
132
+ var TIME_MS_RE = /^(\d+(?:\.\d+)?)ms$/;
133
+ var TIME_MMSS_RE = /^(\d+):(\d{1,2})(?:\.(\d+))?$/;
134
+ function parseTimeSeconds(raw) {
135
+ const trimmed = raw.trim();
136
+ if (!trimmed) return null;
137
+ if (TIME_BARE_RE.test(trimmed)) {
138
+ const n = Number(trimmed);
139
+ return Number.isFinite(n) ? n : null;
140
+ }
141
+ const msMatch = trimmed.match(TIME_MS_RE);
142
+ if (msMatch) {
143
+ const n = Number(msMatch[1]);
144
+ return Number.isFinite(n) ? n / 1e3 : null;
145
+ }
146
+ const mmssMatch = trimmed.match(TIME_MMSS_RE);
147
+ if (mmssMatch) {
148
+ const mins = Number(mmssMatch[1]);
149
+ const secs = Number(mmssMatch[2]);
150
+ const frac = mmssMatch[3] ? Number(`0.${mmssMatch[3]}`) : 0;
151
+ if (!Number.isFinite(mins) || !Number.isFinite(secs) || !Number.isFinite(frac)) {
152
+ return null;
61
153
  }
154
+ if (secs >= 60) return null;
155
+ return mins * 60 + secs + frac;
62
156
  }
63
- return attrs;
157
+ return null;
64
158
  }
65
- function hastChildrenToNodes(children) {
66
- const result = [];
67
- for (const child of children) {
68
- const node = hastNodeToHtmlNode(child);
69
- if (node) result.push(node);
159
+ function parseConnectionList(raw) {
160
+ const trimmed = raw.trim();
161
+ if (!trimmed) return { list: [], warning: null };
162
+ const list = [];
163
+ let droppedEmpty = false;
164
+ for (const part of trimmed.split(",")) {
165
+ const entry = part.trim();
166
+ if (!entry) {
167
+ droppedEmpty = true;
168
+ continue;
169
+ }
170
+ const colonIdx = entry.indexOf(":");
171
+ if (colonIdx < 0) {
172
+ list.push({ target: entry });
173
+ } else {
174
+ const target = entry.slice(0, colonIdx).trim();
175
+ const type = entry.slice(colonIdx + 1).trim();
176
+ if (!target) {
177
+ droppedEmpty = true;
178
+ continue;
179
+ }
180
+ list.push(type ? { target, type } : { target });
181
+ }
70
182
  }
71
- return result;
183
+ return {
184
+ list,
185
+ warning: droppedEmpty ? "dropped empty connection entries" : null
186
+ };
72
187
  }
73
- function hastNodeToHtmlNode(node) {
74
- switch (node.type) {
75
- case "element": {
76
- const tagName = node.tagName;
77
- const properties = node.properties ?? {};
78
- const children = node.children ?? [];
79
- return {
80
- type: "htmlElement",
81
- tagName,
82
- attributes: convertHastProperties(properties),
83
- children: hastChildrenToNodes(children),
84
- selfClosing: VOID_ELEMENTS.has(tagName) && children.length === 0
85
- };
188
+
189
+ // src/markdown/attrTokens.ts
190
+ var DQ_RUN = `"(?:[^"\\\\]|\\\\.)*"`;
191
+ var SQ_RUN = `'(?:[^'\\\\]|\\\\.)*'`;
192
+ var TEMPLATE_STRICT_RE = new RegExp(
193
+ `\\s*\\{\\[((?:[^\\]"']|${DQ_RUN}|${SQ_RUN})+)\\]\\}[\\s\\]}]*$`
194
+ );
195
+ var TEMPLATE_LEGACY_RE = /\s*\{\[([^\]]+)\]\}[\s\]}]*$/;
196
+ var PANDOC_STRICT_RE = new RegExp(`\\s*\\{(?!\\[)((?:[^}"']|${DQ_RUN}|${SQ_RUN})*)\\}\\s*$`);
197
+ var PANDOC_LEGACY_RE = /\s*\{(?!\[)([^}]*)\}\s*$/;
198
+ function matchTrailing(text, strict, legacy) {
199
+ const m = strict.exec(text) ?? legacy.exec(text);
200
+ return m ? { inner: m[1], index: m.index } : null;
201
+ }
202
+ function matchTrailingTemplateAnnotation(text) {
203
+ return matchTrailing(text, TEMPLATE_STRICT_RE, TEMPLATE_LEGACY_RE);
204
+ }
205
+ function matchTrailingPandocAttr(text) {
206
+ return matchTrailing(text, PANDOC_STRICT_RE, PANDOC_LEGACY_RE);
207
+ }
208
+ var WHITESPACE_RE = /\s/;
209
+ function tokenizeAttrTokens(input) {
210
+ const tokens = [];
211
+ let i = 0;
212
+ const n = input.length;
213
+ while (i < n) {
214
+ while (i < n && WHITESPACE_RE.test(input[i])) i++;
215
+ if (i >= n) break;
216
+ let token = "";
217
+ while (i < n && !WHITESPACE_RE.test(input[i])) {
218
+ const ch = input[i];
219
+ const atValueStart = token === "" || token.endsWith("=");
220
+ if ((ch === '"' || ch === "'") && atValueStart) {
221
+ token += ch;
222
+ i++;
223
+ while (i < n && input[i] !== ch) {
224
+ if (input[i] === "\\" && i + 1 < n && (input[i + 1] === ch || input[i + 1] === "\\")) {
225
+ token += input[i] + input[i + 1];
226
+ i += 2;
227
+ } else {
228
+ token += input[i];
229
+ i++;
230
+ }
231
+ }
232
+ if (i < n && input[i] === ch) {
233
+ token += ch;
234
+ i++;
235
+ }
236
+ } else {
237
+ token += ch;
238
+ i++;
239
+ }
86
240
  }
87
- case "text":
88
- return {
89
- type: "htmlText",
90
- value: node.value
91
- };
92
- case "comment":
93
- return {
94
- type: "htmlComment",
95
- value: node.value
96
- };
97
- case "doctype":
98
- return null;
99
- default:
100
- return null;
241
+ if (token) tokens.push(token);
101
242
  }
243
+ return tokens;
102
244
  }
103
- function parseHtmlToNodes(html) {
104
- if (!html || !html.trim()) return [];
105
- try {
106
- const tree = fromHtml(html, { fragment: true });
107
- return hastChildrenToNodes(tree.children);
108
- } catch {
109
- return [{ type: "htmlText", value: html }];
245
+ var DQ_UNESCAPE_RE = /\\([\\"])/g;
246
+ var SQ_UNESCAPE_RE = /\\([\\'])/g;
247
+ function unquoteAttrValue(raw) {
248
+ if (raw.length >= 2) {
249
+ const q = raw[0];
250
+ if ((q === '"' || q === "'") && raw.endsWith(q)) {
251
+ const body = raw.slice(1, -1);
252
+ return body.replace(q === '"' ? DQ_UNESCAPE_RE : SQ_UNESCAPE_RE, "$1");
253
+ }
110
254
  }
255
+ return raw;
111
256
  }
112
- function escapeHtmlAttr(value) {
113
- return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
257
+ function splitKeyValueToken(token) {
258
+ const eqIdx = token.indexOf("=");
259
+ if (eqIdx <= 0) return null;
260
+ return { key: token.slice(0, eqIdx), value: unquoteAttrValue(token.slice(eqIdx + 1)) };
114
261
  }
115
- function stringifyNode(node) {
116
- switch (node.type) {
117
- case "htmlElement": {
118
- const attrs = Object.entries(node.attributes).map(([k, v]) => v === "" ? k : `${k}="${escapeHtmlAttr(v)}"`).join(" ");
119
- const open = attrs ? `<${node.tagName} ${attrs}>` : `<${node.tagName}>`;
120
- if (node.selfClosing) return open;
121
- const inner = node.children.map(stringifyNode).join("");
122
- return `${open}${inner}</${node.tagName}>`;
123
- }
124
- case "htmlText":
125
- return node.value;
126
- case "htmlComment":
127
- return `<!--${node.value}-->`;
128
- }
262
+ var NEEDS_QUOTING_RE = /[\s"'[\]{}]/;
263
+ var DQ_ESCAPE_RE = /[\\"]/g;
264
+ var SQ_ESCAPE_RE = /[\\']/g;
265
+ function needsQuoting(value) {
266
+ return value === "" || NEEDS_QUOTING_RE.test(value);
129
267
  }
130
- function stringifyHtmlNodes(nodes) {
131
- return nodes.map(stringifyNode).join("");
268
+ function quoteAttrValue(value) {
269
+ if (!needsQuoting(value)) return value;
270
+ if (value.includes('"') && !value.includes("'")) {
271
+ return `'${value.replace(SQ_ESCAPE_RE, (ch) => `\\${ch}`)}'`;
272
+ }
273
+ return `"${value.replace(DQ_ESCAPE_RE, (ch) => `\\${ch}`)}"`;
132
274
  }
133
275
 
134
276
  // src/markdown/convert.ts
@@ -174,14 +316,13 @@ function extractText(node) {
174
316
  }
175
317
  return "";
176
318
  }
177
- var TEMPLATE_ANNOTATION_RE = /\s*\{\[([^\]]+)\]\}[\s\]}]*$/;
178
319
  function extractTemplateAnnotation(children) {
179
320
  for (let i = children.length - 1; i >= 0; i--) {
180
321
  const child = children[i];
181
322
  if (child.type === "text") {
182
- const match = child.value.match(TEMPLATE_ANNOTATION_RE);
323
+ const match = matchTrailingTemplateAnnotation(child.value);
183
324
  if (match) {
184
- const inner = match[1].trim();
325
+ const inner = match.inner.trim();
185
326
  const annotation = parseAnnotationTokens(inner);
186
327
  const stripped = child.value.slice(0, match.index).replace(/\s+$/, "");
187
328
  if (stripped) {
@@ -198,15 +339,15 @@ function extractTemplateAnnotation(children) {
198
339
  return null;
199
340
  }
200
341
  function parseAnnotationTokens(inner) {
201
- const tokens = inner.split(/\s+/);
342
+ const tokens = tokenizeAttrTokens(inner);
202
343
  const params = {};
203
- const firstIsParam = tokens[0].indexOf("=") > 0;
204
- const template = firstIsParam ? void 0 : tokens[0];
344
+ const firstIsParam = tokens.length > 0 && tokens[0].indexOf("=") > 0;
345
+ const template = firstIsParam || tokens.length === 0 ? void 0 : tokens[0];
205
346
  const startIdx = firstIsParam ? 0 : 1;
206
347
  for (let i = startIdx; i < tokens.length; i++) {
207
- const eqIdx = tokens[i].indexOf("=");
208
- if (eqIdx > 0) {
209
- params[tokens[i].slice(0, eqIdx)] = tokens[i].slice(eqIdx + 1);
348
+ const kv = splitKeyValueToken(tokens[i]);
349
+ if (kv) {
350
+ params[kv.key] = kv.value;
210
351
  }
211
352
  }
212
353
  const result = {};
@@ -218,6 +359,95 @@ function parseAnnotationTokens(inner) {
218
359
  }
219
360
  return result;
220
361
  }
362
+ function extractPandocAttributes(children) {
363
+ const trail = [];
364
+ for (let i = children.length - 1; i >= 0; i--) {
365
+ const c = children[i];
366
+ if (c.type === "text") {
367
+ trail.unshift({ val: c.value, idx: i, len: c.value.length });
368
+ } else if (c.type === "textDirective") {
369
+ const td = c;
370
+ const isBare = (!td.children || td.children.length === 0) && (!td.attributes || Object.keys(td.attributes).length === 0);
371
+ if (!isBare) break;
372
+ const synthesized = ":" + (td.name ?? "");
373
+ trail.unshift({ val: synthesized, idx: i, len: synthesized.length });
374
+ } else {
375
+ break;
376
+ }
377
+ }
378
+ if (trail.length === 0) return null;
379
+ const joined = trail.map((t) => t.val).join("");
380
+ const match = matchTrailingPandocAttr(joined);
381
+ if (!match) return null;
382
+ const inner = match.inner.trim();
383
+ const attrs = parsePandocAttrTokens(inner);
384
+ const matchStart = match.index;
385
+ let scannedLen = 0;
386
+ for (let ti = 0; ti < trail.length; ti++) {
387
+ const t = trail[ti];
388
+ if (scannedLen + t.len <= matchStart) {
389
+ scannedLen += t.len;
390
+ continue;
391
+ }
392
+ const firstNode = children[t.idx];
393
+ const keepLen = matchStart - scannedLen;
394
+ if (firstNode.type === "text") {
395
+ const trimmed = firstNode.value.slice(0, keepLen).replace(/\s+$/, "");
396
+ if (trimmed) {
397
+ firstNode.value = trimmed;
398
+ children.splice(t.idx + 1);
399
+ } else {
400
+ children.splice(t.idx);
401
+ }
402
+ } else {
403
+ children.splice(t.idx);
404
+ }
405
+ return attrs;
406
+ }
407
+ children.splice(trail[0].idx);
408
+ return attrs;
409
+ }
410
+ function parsePandocAttrTokens(inner) {
411
+ const tokens = tokenizeAttrTokens(inner);
412
+ const attrs = {};
413
+ const params = {};
414
+ const classes = [];
415
+ for (const token of tokens) {
416
+ if (token.startsWith("#") && !token.includes("=")) {
417
+ attrs.id = token.slice(1);
418
+ } else if (token.startsWith(".") && !token.includes("=")) {
419
+ const cls = token.slice(1);
420
+ if (cls) classes.push(cls);
421
+ } else {
422
+ const kv = splitKeyValueToken(token);
423
+ if (kv) {
424
+ params[kv.key] = kv.value;
425
+ }
426
+ }
427
+ }
428
+ if (classes.length > 0) attrs.classes = classes;
429
+ if (Object.keys(params).length > 0) {
430
+ attrs.params = params;
431
+ const { blockMeta, metadata } = coerceAnnotationValues(params);
432
+ if (Object.keys(blockMeta).length > 0) attrs.blockMeta = blockMeta;
433
+ if (Object.keys(metadata).length > 0) attrs.metadata = metadata;
434
+ }
435
+ return attrs;
436
+ }
437
+ function serializePandocAttributes(attrs) {
438
+ const parts = [];
439
+ if (attrs.id) parts.push(`#${attrs.id}`);
440
+ if (attrs.classes) {
441
+ for (const cls of attrs.classes) parts.push(`.${cls}`);
442
+ }
443
+ if (attrs.params) {
444
+ for (const [key, value] of Object.entries(attrs.params)) {
445
+ parts.push(`${key}=${quoteAttrValue(value)}`);
446
+ }
447
+ }
448
+ if (parts.length === 0) return "{}";
449
+ return `{${parts.join(" ")}}`;
450
+ }
221
451
  function serializeTemplateAnnotation(annotation) {
222
452
  const parts = [];
223
453
  if (annotation.template) {
@@ -225,7 +455,7 @@ function serializeTemplateAnnotation(annotation) {
225
455
  }
226
456
  if (annotation.params) {
227
457
  for (const [key, value] of Object.entries(annotation.params)) {
228
- parts.push(`${key}=${value}`);
458
+ parts.push(`${key}=${quoteAttrValue(value)}`);
229
459
  }
230
460
  }
231
461
  return `{[${parts.join(" ")}]}`;
@@ -373,7 +603,26 @@ function convertBlockNode(node, parseHtml) {
373
603
  switch (node.type) {
374
604
  case "heading": {
375
605
  const headingChildren = convertInlineChildren(node.children ?? [], parseHtml, false);
376
- const annotation = extractTemplateAnnotation(headingChildren);
606
+ let annotation = null;
607
+ let attrs = null;
608
+ for (let pass = 0; pass < 4; pass++) {
609
+ let matched = false;
610
+ if (!annotation) {
611
+ const t = extractTemplateAnnotation(headingChildren);
612
+ if (t) {
613
+ annotation = t;
614
+ matched = true;
615
+ }
616
+ }
617
+ if (!attrs) {
618
+ const a = extractPandocAttributes(headingChildren);
619
+ if (a) {
620
+ attrs = a;
621
+ matched = true;
622
+ }
623
+ }
624
+ if (!matched) break;
625
+ }
377
626
  const finalChildren = splitInlineIcons(headingChildren);
378
627
  const result = {
379
628
  type: "heading",
@@ -384,6 +633,9 @@ function convertBlockNode(node, parseHtml) {
384
633
  if (annotation) {
385
634
  result.templateAnnotation = annotation;
386
635
  }
636
+ if (attrs) {
637
+ result.attributes = attrs;
638
+ }
387
639
  return result;
388
640
  }
389
641
  case "paragraph":
@@ -637,8 +889,16 @@ function blockToMdast(node) {
637
889
  switch (node.type) {
638
890
  case "heading": {
639
891
  const mdastChildren = inlineChildrenToMdast(node.children);
892
+ const suffixes = [];
893
+ if (node.attributes) {
894
+ const pandoc = serializePandocAttributes(node.attributes);
895
+ if (pandoc != null) suffixes.push(pandoc);
896
+ }
640
897
  if (node.templateAnnotation) {
641
- const suffix = serializeTemplateAnnotation(node.templateAnnotation);
898
+ suffixes.push(serializeTemplateAnnotation(node.templateAnnotation));
899
+ }
900
+ if (suffixes.length > 0) {
901
+ const suffix = suffixes.join(" ");
642
902
  const lastChild = mdastChildren[mdastChildren.length - 1];
643
903
  if (lastChild && lastChild.type === "text") {
644
904
  lastChild.value = (lastChild.value ?? "") + " " + suffix;
@@ -932,6 +1192,12 @@ function definitionListToHtml(list) {
932
1192
  }
933
1193
 
934
1194
  // src/markdown/parse.ts
1195
+ import { unified } from "unified";
1196
+ import remarkParse from "remark-parse";
1197
+ import remarkGfm from "remark-gfm";
1198
+ import remarkMath from "remark-math";
1199
+ import remarkDirective from "remark-directive";
1200
+ import remarkFrontmatter from "remark-frontmatter";
935
1201
  var defaultProcessor;
936
1202
  function parseMarkdown(markdown, options) {
937
1203
  const useDefaults = !options || options.gfm !== false && options.math !== false && options.directive !== false && options.frontmatter !== false;
@@ -972,72 +1238,22 @@ function parseMarkdown(markdown, options) {
972
1238
  return doc;
973
1239
  }
974
1240
 
975
- // src/markdown/stringify.ts
976
- import { unified as unified2 } from "unified";
977
- import remarkStringify from "remark-stringify";
978
- import remarkGfm2 from "remark-gfm";
979
- import remarkMath2 from "remark-math";
980
- import remarkDirective2 from "remark-directive";
981
- var defaultProcessor2;
982
- function stringifyMarkdown(doc, options) {
983
- const mdastTree = toMdast(doc);
984
- const useDefaults = !options || options.gfm !== false && options.math !== false && options.directive !== false && !options.bullet && !options.bulletOrdered && !options.emphasis && !options.strong && !options.rule && !options.fence && options.setext == null;
985
- let processor;
986
- if (useDefaults) {
987
- if (!defaultProcessor2) {
988
- defaultProcessor2 = unified2().use(remarkGfm2).use(remarkMath2).use(remarkDirective2).use(remarkStringify, {
989
- bullet: "-",
990
- bulletOrdered: ".",
991
- emphasis: "*",
992
- strong: "*",
993
- rule: "-",
994
- fence: "`",
995
- setext: false
996
- });
997
- }
998
- processor = defaultProcessor2;
999
- } else {
1000
- processor = unified2();
1001
- if (options?.gfm !== false) {
1002
- processor = processor.use(remarkGfm2);
1003
- }
1004
- if (options?.math !== false) {
1005
- processor = processor.use(remarkMath2);
1006
- }
1007
- if (options?.directive !== false) {
1008
- processor = processor.use(remarkDirective2);
1009
- }
1010
- processor = processor.use(remarkStringify, {
1011
- bullet: options?.bullet ?? "-",
1012
- bulletOrdered: options?.bulletOrdered ?? ".",
1013
- emphasis: options?.emphasis ?? "*",
1014
- strong: options?.strong ?? "*",
1015
- rule: options?.rule ?? "-",
1016
- fence: options?.fence ?? "`",
1017
- setext: options?.setext ?? false
1018
- });
1019
- }
1020
- const result = processor.stringify(mdastTree);
1021
- const cleaned = result.replace(/\{\\\[([^\]]+)\]\}/g, "{[$1]}");
1022
- if (doc.frontmatter && Object.keys(doc.frontmatter).length > 0) {
1023
- const yamlLines = Object.entries(doc.frontmatter).map(
1024
- ([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`
1025
- );
1026
- return `---
1027
- ${yamlLines.join("\n")}
1028
- ---
1029
-
1030
- ${cleaned}`;
1031
- }
1032
- return cleaned;
1033
- }
1034
-
1035
1241
  export {
1036
- parseHtmlToNodes,
1037
- stringifyHtmlNodes,
1242
+ KNOWN_BLOCK_META_KEYS,
1243
+ BLOCK_META_KEY_DESCRIPTORS,
1244
+ coerceAnnotationValues,
1245
+ parseTimeSeconds,
1246
+ matchTrailingTemplateAnnotation,
1247
+ matchTrailingPandocAttr,
1248
+ tokenizeAttrTokens,
1249
+ unquoteAttrValue,
1250
+ splitKeyValueToken,
1251
+ needsQuoting,
1252
+ quoteAttrValue,
1253
+ parsePandocAttrTokens,
1254
+ serializePandocAttributes,
1038
1255
  fromMdast,
1039
1256
  toMdast,
1040
- parseMarkdown,
1041
- stringifyMarkdown
1257
+ parseMarkdown
1042
1258
  };
1043
- //# sourceMappingURL=chunk-3K5OG6KI.js.map
1259
+ //# sourceMappingURL=chunk-OH43RPTP.js.map