@portabletext/markdown 1.4.3 → 1.4.5

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.
package/dist/index.js CHANGED
@@ -1,1460 +1,1267 @@
1
- import { compileSchema, defineSchema, isTextBlock, isSpan } from "@portabletext/schema";
2
- import { isPortableTextListItemBlock, isPortableTextToolkitSpan, isPortableTextBlock, isPortableTextToolkitTextNode, buildMarksTree, spanToPlainText } from "@portabletext/toolkit";
1
+ import { compileSchema, defineSchema, isSpan, isTextBlock } from "@portabletext/schema";
2
+ import { buildMarksTree, isPortableTextBlock, isPortableTextListItemBlock, isPortableTextToolkitSpan, isPortableTextToolkitTextNode, spanToPlainText } from "@portabletext/toolkit";
3
3
  import { alert } from "@mdit/plugin-alert";
4
4
  import markdownit from "markdown-it";
5
5
  function defaultKeyGenerator() {
6
- return randomKey(12);
6
+ return randomKey(12);
7
7
  }
8
- const getByteHexTable = /* @__PURE__ */ (() => {
9
- let table;
10
- return () => {
11
- if (table)
12
- return table;
13
- table = [];
14
- for (let i = 0; i < 256; ++i)
15
- table[i] = (i + 256).toString(16).slice(1);
16
- return table;
17
- };
8
+ const getByteHexTable = (() => {
9
+ let table;
10
+ return () => {
11
+ if (table) return table;
12
+ table = [];
13
+ for (let i = 0; i < 256; ++i) table[i] = (i + 256).toString(16).slice(1);
14
+ return table;
15
+ };
18
16
  })();
19
17
  function whatwgRNG(length = 16) {
20
- const rnds8 = new Uint8Array(length);
21
- return crypto.getRandomValues(rnds8), rnds8;
18
+ let rnds8 = new Uint8Array(length);
19
+ return crypto.getRandomValues(rnds8), rnds8;
22
20
  }
23
21
  function randomKey(length) {
24
- const table = getByteHexTable();
25
- return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
22
+ let table = getByteHexTable();
23
+ return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
26
24
  }
27
25
  const schema = compileSchema(defineSchema({}));
26
+ /**
27
+ * Builds a map of list item `_key`s to their index.
28
+ *
29
+ * Mutates the blocks in place by adding a `_key` if necessary.
30
+ */
28
31
  function buildListIndexMap(blocks) {
29
- const levelIndexMaps = /* @__PURE__ */ new Map(), listIndexMap = /* @__PURE__ */ new Map();
30
- let previousListItem;
31
- for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
32
- const block = blocks.at(blockIndex);
33
- if (block === void 0)
34
- continue;
35
- if (block._key || (block._key = defaultKeyGenerator()), !isTextBlock({ schema }, block)) {
36
- levelIndexMaps.clear(), previousListItem = void 0;
37
- continue;
38
- }
39
- if (block.listItem === void 0 || block.level === void 0) {
40
- levelIndexMaps.clear(), previousListItem = void 0;
41
- continue;
42
- }
43
- if (!previousListItem) {
44
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
45
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(block._key, 1), previousListItem = {
46
- listItem: block.listItem,
47
- level: block.level
48
- };
49
- continue;
50
- }
51
- if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
52
- const levelIndexMap2 = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
53
- levelIndexMap2.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap2), listIndexMap.set(block._key, 1), previousListItem = {
54
- listItem: block.listItem,
55
- level: block.level
56
- };
57
- continue;
58
- }
59
- levelIndexMaps.forEach((levelIndexMap2, listItem) => {
60
- if (listItem === block.listItem)
61
- return;
62
- const levelsToDelete = [];
63
- levelIndexMap2.forEach((_, level) => {
64
- level >= block.level && levelsToDelete.push(level);
65
- }), levelsToDelete.forEach((level) => {
66
- levelIndexMap2.delete(level);
67
- });
68
- });
69
- const levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
70
- levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(block._key, levelCounter + 1), previousListItem = {
71
- listItem: block.listItem,
72
- level: block.level
73
- };
74
- }
75
- return listIndexMap;
32
+ let levelIndexMaps = /* @__PURE__ */ new Map(), listIndexMap = /* @__PURE__ */ new Map(), previousListItem;
33
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
34
+ let block = blocks.at(blockIndex);
35
+ if (block === void 0) continue;
36
+ if (block._key ||= defaultKeyGenerator(), !isTextBlock({ schema }, block)) {
37
+ levelIndexMaps.clear(), previousListItem = void 0;
38
+ continue;
39
+ }
40
+ if (block.listItem === void 0 || block.level === void 0) {
41
+ levelIndexMaps.clear(), previousListItem = void 0;
42
+ continue;
43
+ }
44
+ if (!previousListItem) {
45
+ let levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
46
+ levelIndexMap.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(block._key, 1), previousListItem = {
47
+ listItem: block.listItem,
48
+ level: block.level
49
+ };
50
+ continue;
51
+ }
52
+ if (previousListItem.listItem === block.listItem && previousListItem.level < block.level) {
53
+ let levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map();
54
+ levelIndexMap.set(block.level, 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(block._key, 1), previousListItem = {
55
+ listItem: block.listItem,
56
+ level: block.level
57
+ };
58
+ continue;
59
+ }
60
+ levelIndexMaps.forEach((levelIndexMap, listItem) => {
61
+ if (listItem === block.listItem) return;
62
+ let levelsToDelete = [];
63
+ levelIndexMap.forEach((_, level) => {
64
+ level >= block.level && levelsToDelete.push(level);
65
+ }), levelsToDelete.forEach((level) => {
66
+ levelIndexMap.delete(level);
67
+ });
68
+ });
69
+ let levelIndexMap = levelIndexMaps.get(block.listItem) ?? /* @__PURE__ */ new Map(), levelCounter = levelIndexMap.get(block.level) ?? 0;
70
+ levelIndexMap.set(block.level, levelCounter + 1), levelIndexMaps.set(block.listItem, levelIndexMap), listIndexMap.set(block._key, levelCounter + 1), previousListItem = {
71
+ listItem: block.listItem,
72
+ level: block.level
73
+ };
74
+ }
75
+ return listIndexMap;
76
76
  }
77
77
  const createRenderNode = (renderers, listIndexMap) => {
78
- function renderNode(options) {
79
- const { node, index, isInline } = options;
80
- return isPortableTextListItemBlock(node) ? renderListItem(node, index) : isPortableTextToolkitSpan(node) ? renderSpan(node) : isPortableTextBlock(node) ? renderBlock(node, index, isInline) : isPortableTextToolkitTextNode(node) ? renderText(node) : renderCustomBlock(node, index, isInline);
81
- }
82
- function renderListItem(node, index) {
83
- const renderer = renderers.listItem, itemHandler = (typeof renderer == "function" ? renderer : renderer[node.listItem]) || renderers.unknownListItem;
84
- let children = buildMarksTree(node).map((child, i) => renderNode({ node: child, isInline: !0, index: i })).join("");
85
- if (node.style && node.style !== "normal") {
86
- const { listItem: _listItem, ...blockNode } = node;
87
- children = renderNode({
88
- node: blockNode,
89
- index,
90
- isInline: !1
91
- }), children = children.replace(/\n+$/, "");
92
- }
93
- return itemHandler({
94
- value: node,
95
- index,
96
- listIndex: node._key ? listIndexMap.get(node._key) : void 0,
97
- isInline: !1,
98
- renderNode,
99
- children
100
- });
101
- }
102
- function renderSpan(node) {
103
- const { markDef, markType, markKey } = node, span = renderers.marks[markType] || renderers.unknownMark, children = node.children.map(
104
- (child, childIndex) => renderNode({ node: child, index: childIndex, isInline: !0 })
105
- );
106
- return span({
107
- text: spanToPlainText(node),
108
- value: markDef,
109
- markType,
110
- markKey,
111
- renderNode,
112
- children: children.join("")
113
- });
114
- }
115
- function renderBlock(node, index, isInline) {
116
- const { _key, ...props } = serializeBlock({ node, index, isInline, renderNode }), style = props.node.style || "normal";
117
- return ((typeof renderers.block == "function" ? renderers.block : renderers.block[style]) || renderers.unknownBlockStyle)({ ...props, value: props.node, renderNode });
118
- }
119
- function renderText(node) {
120
- return node.text === `
121
- ` ? renderers.hardBreak() : node.text;
122
- }
123
- function renderCustomBlock(value, index, isInline) {
124
- return (renderers.types[value._type] ?? renderers.unknownType)({
125
- value,
126
- isInline,
127
- index,
128
- renderNode
129
- });
130
- }
131
- return renderNode;
78
+ function renderNode(options) {
79
+ let { node, index, isInline } = options;
80
+ return isPortableTextListItemBlock(node) ? renderListItem(node, index) : isPortableTextToolkitSpan(node) ? renderSpan(node) : isPortableTextBlock(node) ? renderBlock(node, index, isInline) : isPortableTextToolkitTextNode(node) ? renderText(node) : renderCustomBlock(node, index, isInline);
81
+ }
82
+ function renderListItem(node, index) {
83
+ let renderer = renderers.listItem, itemHandler = (typeof renderer == "function" ? renderer : renderer[node.listItem]) || renderers.unknownListItem, children = buildMarksTree(node).map((child, i) => renderNode({
84
+ node: child,
85
+ isInline: !0,
86
+ index: i,
87
+ renderNode
88
+ })).join("");
89
+ if (node.style && node.style !== "normal") {
90
+ let { listItem: _listItem, ...blockNode } = node;
91
+ children = renderNode({
92
+ node: blockNode,
93
+ index,
94
+ isInline: !1,
95
+ renderNode
96
+ }), children = children.replace(/\n+$/, "");
97
+ }
98
+ return itemHandler({
99
+ value: node,
100
+ index,
101
+ listIndex: node._key ? listIndexMap.get(node._key) : void 0,
102
+ isInline: !1,
103
+ renderNode,
104
+ children
105
+ });
106
+ }
107
+ function renderSpan(node) {
108
+ let { markDef, markType, markKey } = node, span = renderers.marks[markType] || renderers.unknownMark, children = node.children.map((child, childIndex) => renderNode({
109
+ node: child,
110
+ index: childIndex,
111
+ isInline: !0,
112
+ renderNode
113
+ }));
114
+ return span({
115
+ text: spanToPlainText(node),
116
+ value: markDef,
117
+ markType,
118
+ markKey,
119
+ renderNode,
120
+ children: children.join("")
121
+ });
122
+ }
123
+ function renderBlock(node, index, isInline) {
124
+ let { _key, ...props } = serializeBlock({
125
+ node,
126
+ index,
127
+ isInline,
128
+ renderNode
129
+ }), style = props.node.style || "normal";
130
+ return ((typeof renderers.block == "function" ? renderers.block : renderers.block[style]) || renderers.unknownBlockStyle)({
131
+ ...props,
132
+ value: props.node,
133
+ renderNode
134
+ });
135
+ }
136
+ function renderText(node) {
137
+ return node.text === "\n" ? renderers.hardBreak() : node.text;
138
+ }
139
+ function renderCustomBlock(value, index, isInline) {
140
+ return (renderers.types[value._type] ?? renderers.unknownType)({
141
+ value,
142
+ isInline,
143
+ index,
144
+ renderNode
145
+ });
146
+ }
147
+ return renderNode;
132
148
  };
133
149
  function serializeBlock(options) {
134
- const { node, index, isInline, renderNode } = options, renderedChildren = buildMarksTree(node).map(
135
- (child, i) => renderNode({ node: child, isInline: !0, index: i, renderNode })
136
- );
137
- return {
138
- _key: node._key || defaultKeyGenerator(),
139
- children: renderedChildren.join(""),
140
- index,
141
- isInline,
142
- node
143
- };
150
+ let { node, index, isInline, renderNode } = options, renderedChildren = buildMarksTree(node).map((child, i) => renderNode({
151
+ node: child,
152
+ isInline: !0,
153
+ index: i,
154
+ renderNode
155
+ }));
156
+ return {
157
+ _key: node._key || defaultKeyGenerator(),
158
+ children: renderedChildren.join(""),
159
+ index,
160
+ isInline,
161
+ node
162
+ };
144
163
  }
145
- const DefaultBlockSpacingRenderer = ({
146
- current,
147
- next
148
- }) => isPortableTextListItemBlock(current) && isPortableTextListItemBlock(next) ? `
149
- ` : isPortableTextBlock(current) && isPortableTextBlock(next) && current.style === "blockquote" && next.style === "blockquote" ? `
150
- >
151
- ` : `
152
-
153
- `, DefaultHardBreakRenderer = () => `
154
- `, DefaultListItemRenderer = ({
155
- children,
156
- value,
157
- listIndex
158
- }) => {
159
- const listStyle = value.listItem || "bullet", level = value.level || 1, indent = " ".repeat(level - 1);
160
- if (listStyle === "number")
161
- return `${indent}${listIndex ?? 1}. ${children}`;
162
- if (listStyle === "task") {
163
- const marker = "checked" in value && typeof value.checked == "boolean" && value.checked ? "[x]" : "[ ]";
164
- return `${indent}- ${marker} ${children}`;
165
- }
166
- return `${indent}- ${children}`;
167
- }, DefaultUnknownListItemRenderer = ({
168
- children
169
- }) => `- ${children}
170
- `;
164
+ /**
165
+ * @public
166
+ */
167
+ const DefaultBlockSpacingRenderer = ({ current, next }) => isPortableTextListItemBlock(current) && isPortableTextListItemBlock(next) ? "\n" : isPortableTextBlock(current) && isPortableTextBlock(next) && current.style === "blockquote" && next.style === "blockquote" ? "\n>\n" : "\n\n", DefaultHardBreakRenderer = () => " \n", DefaultListItemRenderer = ({ children, value, listIndex }) => {
168
+ let listStyle = value.listItem || "bullet", level = value.level || 1, indent = " ".repeat(level - 1);
169
+ return listStyle === "number" ? `${indent}${listIndex ?? 1}. ${children}` : listStyle === "task" ? `${indent}- ${"checked" in value && typeof value.checked == "boolean" && value.checked ? "[x]" : "[ ]"} ${children}` : `${indent}- ${children}`;
170
+ }, DefaultUnknownListItemRenderer = ({ children }) => `- ${children}\n`;
171
+ /**
172
+ * Escapes special characters in image alt texts and link texts.
173
+ */
171
174
  function escapeImageAndLinkText(text) {
172
- return text.replace(/([[\]\\])/g, "\\$1");
175
+ return text.replace(/([[\]\\])/g, "\\$1");
173
176
  }
177
+ /**
178
+ * Unescapes special characters in image alt texts and link texts.
179
+ */
174
180
  function unescapeImageAndLinkText(text) {
175
- return text.replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g, "$1");
181
+ return text.replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g, "$1");
176
182
  }
183
+ /**
184
+ * Escapes special characters in image/link titles (the part inside quotes).
185
+ */
177
186
  function escapeImageAndLinkTitle(text) {
178
- return text.replace(/([\\"])/g, "\\$1");
187
+ return text.replace(/([\\"])/g, "\\$1");
179
188
  }
189
+ /**
190
+ * Escapes characters that have special meaning at the row level of a GFM
191
+ * table cell.
192
+ *
193
+ * A literal `|` ends the cell, so unescaped pipes are replaced with `\|`.
194
+ * Newlines end the row, so they are replaced with `<br>` to keep the
195
+ * visible line break inside the cell. Already-escaped pipes (`\|`) are
196
+ * left intact so that escapes introduced by mark renderers survive the
197
+ * pass.
198
+ *
199
+ * Backslashes are intentionally not escaped here so that other escapes
200
+ * already in the rendered cell (such as `\[` and `\]` in link text) are
201
+ * not double-escaped.
202
+ */
180
203
  function escapeTableCell(text) {
181
- return text.replace(new RegExp("(?<!\\\\)\\|", "g"), "\\|").replace(/\n/g, "<br>");
204
+ return text.replace(RegExp("(?<!\\\\)\\|", "g"), "\\|").replace(/\n/g, "<br>");
182
205
  }
183
- const DefaultEmRenderer = ({ children }) => `_${children}_`, DefaultStrongRenderer = ({ children }) => `**${children}**`, DefaultCodeRenderer = ({ children }) => `\`${children}\``, DefaultUnderlineRenderer = ({
184
- children
185
- }) => `<u>${children}</u>`, DefaultStrikeThroughRenderer = ({
186
- children
187
- }) => `~~${children}~~`, DefaultLinkRenderer = ({
188
- children,
189
- value
190
- }) => {
191
- const href = value?.href || "", title = value?.title || "";
192
- if (uriLooksSafe(href)) {
193
- if (/["'][^"']*[<>]|[<>][^<>]*["']/.test(href)) {
194
- const encodedHref = href.replace(/["<>() ]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
195
- return `[${escapeImageAndLinkText(children)}](${encodedHref})`;
196
- }
197
- return `[${escapeImageAndLinkText(children)}](${href}${title ? ` "${escapeImageAndLinkTitle(title)}"` : ""})`;
198
- }
199
- return children;
206
+ /**
207
+ * @public
208
+ */
209
+ const DefaultEmRenderer = ({ children }) => `_${children}_`, DefaultStrongRenderer = ({ children }) => `**${children}**`, DefaultCodeRenderer = ({ children }) => `\`${children}\``, DefaultUnderlineRenderer = ({ children }) => `<u>${children}</u>`, DefaultStrikeThroughRenderer = ({ children }) => `~~${children}~~`, DefaultLinkRenderer = ({ children, value }) => {
210
+ let href = value?.href || "", title = value?.title || "";
211
+ if (uriLooksSafe(href)) {
212
+ if (/["'][^"']*[<>]|[<>][^<>]*["']/.test(href)) {
213
+ let encodedHref = href.replace(/["<>() ]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
214
+ return `[${escapeImageAndLinkText(children)}](${encodedHref})`;
215
+ }
216
+ return `[${escapeImageAndLinkText(children)}](${href}${title ? ` "${escapeImageAndLinkTitle(title)}"` : ""})`;
217
+ }
218
+ return children;
200
219
  };
201
220
  function uriLooksSafe(uri) {
202
- const url = (uri || "").trim(), first = url.charAt(0);
203
- if (first === "#" || first === "/")
204
- return !0;
205
- const colonIndex = url.indexOf(":");
206
- if (colonIndex === -1)
207
- return !0;
208
- const allowedProtocols = ["http", "https", "mailto", "tel"], proto = url.slice(0, colonIndex).toLowerCase();
209
- if (allowedProtocols.indexOf(proto) !== -1)
210
- return !0;
211
- const queryIndex = url.indexOf("?");
212
- if (queryIndex !== -1 && colonIndex > queryIndex)
213
- return !0;
214
- const hashIndex = url.indexOf("#");
215
- return hashIndex !== -1 && colonIndex > hashIndex;
221
+ let url = (uri || "").trim(), first = url.charAt(0);
222
+ if (first === "#" || first === "/") return !0;
223
+ let colonIndex = url.indexOf(":");
224
+ if (colonIndex === -1) return !0;
225
+ let allowedProtocols = [
226
+ "http",
227
+ "https",
228
+ "mailto",
229
+ "tel"
230
+ ], proto = url.slice(0, colonIndex).toLowerCase();
231
+ if (allowedProtocols.indexOf(proto) !== -1) return !0;
232
+ let queryIndex = url.indexOf("?");
233
+ if (queryIndex !== -1 && colonIndex > queryIndex) return !0;
234
+ let hashIndex = url.indexOf("#");
235
+ return hashIndex !== -1 && colonIndex > hashIndex;
216
236
  }
217
- const DefaultUnknownMarkRenderer = ({
218
- children
219
- }) => children, DefaultNormalRenderer = ({
220
- children
221
- }) => !children || children.trim() === "" ? "" : children, DefaultBlockquoteRenderer = ({
222
- children
223
- }) => children ? children.split(`
224
- `).map((line) => `> ${line}`).join(`
225
- `) : ">", DefaultH1Renderer = ({ children }) => `# ${children}`, DefaultH2Renderer = ({ children }) => `## ${children}`, DefaultH3Renderer = ({ children }) => `### ${children}`, DefaultH4Renderer = ({ children }) => `#### ${children}`, DefaultH5Renderer = ({ children }) => `##### ${children}`, DefaultH6Renderer = ({ children }) => `###### ${children}`, DefaultUnknownStyleRenderer = ({
226
- children
227
- }) => children ?? "", DefaultCodeBlockRenderer = ({ value }) => `\`\`\`${value.language ?? ""}
228
- ${value.code}
229
- \`\`\``, DefaultHorizontalRuleRenderer = () => "---", DefaultHtmlRenderer = ({ value }) => value.html, DefaultImageRenderer = ({ value }) => {
230
- const alt = escapeImageAndLinkText(value.alt ?? ""), title = value.title ? ` "${escapeImageAndLinkTitle(value.title)}"` : "";
231
- return `![${alt}](${value.src}${title})`;
237
+ /**
238
+ * @public
239
+ */
240
+ const DefaultUnknownMarkRenderer = ({ children }) => children, DefaultNormalRenderer = ({ children }) => !children || children.trim() === "" ? "" : children, DefaultBlockquoteRenderer = ({ children }) => children ? children.split("\n").map((line) => `> ${line}`).join("\n") : ">", DefaultH1Renderer = ({ children }) => `# ${children}`, DefaultH2Renderer = ({ children }) => `## ${children}`, DefaultH3Renderer = ({ children }) => `### ${children}`, DefaultH4Renderer = ({ children }) => `#### ${children}`, DefaultH5Renderer = ({ children }) => `##### ${children}`, DefaultH6Renderer = ({ children }) => `###### ${children}`, DefaultUnknownStyleRenderer = ({ children }) => children ?? "", DefaultCodeBlockRenderer = ({ value }) => `\`\`\`${value.language ?? ""}\n${value.code}\n\`\`\``, DefaultHorizontalRuleRenderer = () => "---", DefaultHtmlRenderer = ({ value }) => value.html, DefaultImageRenderer = ({ value }) => {
241
+ let alt = escapeImageAndLinkText(value.alt ?? ""), title = value.title ? ` "${escapeImageAndLinkTitle(value.title)}"` : "";
242
+ return `![${alt}](${value.src}${title})`;
232
243
  }, DefaultTableRenderer = ({ value, renderNode }) => {
233
- const rows = value.rows, alignment = value.alignment, headerRow = rows.at(0);
234
- if (!headerRow)
235
- return "";
236
- const getCellText = (cellBlocks) => cellBlocks.map(
237
- (block, index) => renderNode({
238
- node: block,
239
- index,
240
- isInline: !1,
241
- renderNode
242
- })
243
- ).join(" ").trim(), lines = [], columnCount = rows.reduce(
244
- (max, row) => Math.max(max, row.cells.length),
245
- 0
246
- ), renderCells = (texts) => {
247
- const padded = [...texts];
248
- for (; padded.length < columnCount; )
249
- padded.push("");
250
- return `| ${padded.join(" | ")} |`;
251
- }, renderRow = (cells) => renderCells(cells.map((cell) => escapeTableCell(getCellText(cell.value)))), delimiter = `|${Array.from({ length: columnCount }, (_, index) => {
252
- const align = alignment?.at(index);
253
- return align === "left" ? " :--- " : align === "center" ? " :---: " : align === "right" ? " ---: " : " --- ";
254
- }).join("|")}|`;
255
- if (value.headerRows === 0) {
256
- lines.push(renderCells([])), lines.push(delimiter);
257
- for (const row of rows)
258
- lines.push(renderRow(row.cells));
259
- } else {
260
- lines.push(renderRow(headerRow.cells)), lines.push(delimiter);
261
- for (let i = 1; i < rows.length; i++) {
262
- const row = rows.at(i);
263
- row && lines.push(renderRow(row.cells));
264
- }
265
- }
266
- return lines.join(`
267
- `);
244
+ let rows = value.rows, alignment = value.alignment, headerRow = rows.at(0);
245
+ if (!headerRow) return "";
246
+ let getCellText = (cellBlocks) => cellBlocks.map((block, index) => renderNode({
247
+ node: block,
248
+ index,
249
+ isInline: !1,
250
+ renderNode
251
+ })).join(" ").trim(), lines = [], columnCount = rows.reduce((max, row) => Math.max(max, row.cells.length), 0), renderCells = (texts) => {
252
+ let padded = [...texts];
253
+ for (; padded.length < columnCount;) padded.push("");
254
+ return `| ${padded.join(" | ")} |`;
255
+ }, renderRow = (cells) => renderCells(cells.map((cell) => escapeTableCell(getCellText(cell.value)))), delimiter = `|${Array.from({ length: columnCount }, (_, index) => {
256
+ let align = alignment?.at(index);
257
+ return align === "left" ? " :--- " : align === "center" ? " :---: " : align === "right" ? " ---: " : " --- ";
258
+ }).join("|")}|`;
259
+ if (value.headerRows === 0) {
260
+ lines.push(renderCells([])), lines.push(delimiter);
261
+ for (let row of rows) lines.push(renderRow(row.cells));
262
+ } else {
263
+ lines.push(renderRow(headerRow.cells)), lines.push(delimiter);
264
+ for (let i = 1; i < rows.length; i++) {
265
+ let row = rows.at(i);
266
+ row && lines.push(renderRow(row.cells));
267
+ }
268
+ }
269
+ return lines.join("\n");
268
270
  }, DefaultCalloutRenderer = ({ value, renderNode }) => {
269
- const prefixed = value.content.map(
270
- (block, index) => renderNode({
271
- node: { ...block, style: "normal" },
272
- index,
273
- isInline: !1,
274
- renderNode
275
- })
276
- ).join(`
277
-
278
- `).split(`
279
- `).map((line) => line === "" ? ">" : `> ${line}`).join(`
280
- `);
281
- return `> [!${value.tone.toUpperCase()}]
282
- ${prefixed}`;
283
- }, DefaultBlockquoteObjectRenderer = ({ value, renderNode }) => value.content.map(
284
- (block, index) => renderNode({
285
- node: { ...block, style: "normal" },
286
- index,
287
- isInline: !1,
288
- renderNode
289
- })
290
- ).join(`
291
-
292
- `).split(`
293
- `).map((line) => line === "" ? ">" : `> ${line}`).join(`
294
- `), DefaultListRenderer = ({ value, renderNode }) => {
295
- const itemSeparator = value.items.some((item) => item.content.filter(
296
- (block) => block._type !== "list"
297
- ).length > 1) ? `
298
-
299
- ` : `
300
- `;
301
- return value.items.map((item, itemIndex) => {
302
- const marker = getListMarker(value.kind, itemIndex, item.checked), indentWidth = value.kind === "task" ? 2 : marker.length, indent = " ".repeat(indentWidth), renderedBlocks = item.content.map((block, blockIndex) => ({
303
- isNestedList: block._type === "list",
304
- text: renderNode({
305
- node: block,
306
- index: blockIndex,
307
- isInline: !1,
308
- renderNode
309
- })
310
- })), [first, ...rest] = renderedBlocks, head = `${marker}${first?.text ?? ""}`.trimEnd();
311
- if (rest.length === 0)
312
- return head;
313
- const tail = rest.map((rendered) => {
314
- const indented = rendered.text.split(`
315
- `).map((line) => line === "" ? "" : `${indent}${line}`).join(`
316
- `);
317
- return rendered.isNestedList ? `
318
- ${indented}` : `
319
-
320
- ${indented}`;
321
- }).join("");
322
- return `${head}${tail}`;
323
- }).join(itemSeparator);
271
+ let prefixed = value.content.map((block, index) => renderNode({
272
+ node: {
273
+ ...block,
274
+ style: "normal"
275
+ },
276
+ index,
277
+ isInline: !1,
278
+ renderNode
279
+ })).join("\n\n").split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n");
280
+ return `> [!${value.tone.toUpperCase()}]\n${prefixed}`;
281
+ }, DefaultBlockquoteObjectRenderer = ({ value, renderNode }) => value.content.map((block, index) => renderNode({
282
+ node: {
283
+ ...block,
284
+ style: "normal"
285
+ },
286
+ index,
287
+ isInline: !1,
288
+ renderNode
289
+ })).join("\n\n").split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n"), DefaultListRenderer = ({ value, renderNode }) => {
290
+ let itemSeparator = value.items.some((item) => item.content.filter((block) => block._type !== "list").length > 1) ? "\n\n" : "\n";
291
+ return value.items.map((item, itemIndex) => {
292
+ let marker = getListMarker(value.kind, itemIndex, item.checked), indentWidth = value.kind === "task" ? 2 : marker.length, indent = " ".repeat(indentWidth), [first, ...rest] = item.content.map((block, blockIndex) => ({
293
+ isNestedList: block._type === "list",
294
+ text: renderNode({
295
+ node: block,
296
+ index: blockIndex,
297
+ isInline: !1,
298
+ renderNode
299
+ })
300
+ })), head = `${marker}${first?.text ?? ""}`.trimEnd();
301
+ return rest.length === 0 ? head : `${head}${rest.map((rendered) => {
302
+ let indented = rendered.text.split("\n").map((line) => line === "" ? "" : `${indent}${line}`).join("\n");
303
+ return rendered.isNestedList ? `\n${indented}` : `\n\n${indented}`;
304
+ }).join("")}`;
305
+ }).join(itemSeparator);
324
306
  };
325
307
  function getListMarker(kind, itemIndex, checked) {
326
- return kind === "number" ? `${itemIndex + 1}. ` : kind === "task" ? checked ? "- [x] " : "- [ ] " : "- ";
308
+ return kind === "number" ? `${itemIndex + 1}. ` : kind === "task" ? checked ? "- [x] " : "- [ ] " : "- ";
327
309
  }
328
- const DefaultUnknownTypeRenderer = ({
329
- value,
330
- isInline
331
- }) => {
332
- const json = `\`\`\`json
333
- ${JSON.stringify(value, null, 2)}
334
- \`\`\``;
335
- return isInline ? `
336
- ${json}
337
- ` : json;
310
+ /**
311
+ * @public
312
+ */
313
+ const DefaultUnknownTypeRenderer = ({ value, isInline }) => {
314
+ let json = `\`\`\`json\n${JSON.stringify(value, null, 2)}\n\`\`\``;
315
+ return isInline ? `\n${json}\n` : json;
338
316
  }, defaultRenderers = {
339
- types: {},
340
- block: {
341
- normal: DefaultNormalRenderer,
342
- blockquote: DefaultBlockquoteRenderer,
343
- h1: DefaultH1Renderer,
344
- h2: DefaultH2Renderer,
345
- h3: DefaultH3Renderer,
346
- h4: DefaultH4Renderer,
347
- h5: DefaultH5Renderer,
348
- h6: DefaultH6Renderer
349
- },
350
- marks: {
351
- em: DefaultEmRenderer,
352
- strong: DefaultStrongRenderer,
353
- code: DefaultCodeRenderer,
354
- underline: DefaultUnderlineRenderer,
355
- "strike-through": DefaultStrikeThroughRenderer,
356
- link: DefaultLinkRenderer
357
- },
358
- listItem: DefaultListItemRenderer,
359
- hardBreak: DefaultHardBreakRenderer,
360
- unknownType: DefaultUnknownTypeRenderer,
361
- unknownMark: DefaultUnknownMarkRenderer,
362
- unknownListItem: DefaultUnknownListItemRenderer,
363
- unknownBlockStyle: DefaultUnknownStyleRenderer
317
+ types: {},
318
+ block: {
319
+ normal: DefaultNormalRenderer,
320
+ blockquote: DefaultBlockquoteRenderer,
321
+ h1: DefaultH1Renderer,
322
+ h2: DefaultH2Renderer,
323
+ h3: DefaultH3Renderer,
324
+ h4: DefaultH4Renderer,
325
+ h5: DefaultH5Renderer,
326
+ h6: DefaultH6Renderer
327
+ },
328
+ marks: {
329
+ em: DefaultEmRenderer,
330
+ strong: DefaultStrongRenderer,
331
+ code: DefaultCodeRenderer,
332
+ underline: DefaultUnderlineRenderer,
333
+ "strike-through": DefaultStrikeThroughRenderer,
334
+ link: DefaultLinkRenderer
335
+ },
336
+ listItem: DefaultListItemRenderer,
337
+ hardBreak: DefaultHardBreakRenderer,
338
+ unknownType: DefaultUnknownTypeRenderer,
339
+ unknownMark: DefaultUnknownMarkRenderer,
340
+ unknownListItem: DefaultUnknownListItemRenderer,
341
+ unknownBlockStyle: DefaultUnknownStyleRenderer
364
342
  };
343
+ /**
344
+ * @public
345
+ */
365
346
  function portableTextToMarkdown(blocks, options = {}) {
366
- const renderers = {
367
- block: {
368
- ...defaultRenderers.block,
369
- ...options.block
370
- },
371
- listItem: options.listItem ?? defaultRenderers.listItem,
372
- marks: {
373
- ...defaultRenderers.marks,
374
- ...options.marks
375
- },
376
- types: {
377
- ...defaultRenderers.types,
378
- ...options.types
379
- },
380
- hardBreak: options.hardBreak ?? defaultRenderers.hardBreak,
381
- unknownType: options.unknownType ?? defaultRenderers.unknownType,
382
- unknownBlockStyle: options.unknownBlockStyle ?? defaultRenderers.unknownBlockStyle,
383
- unknownListItem: options.unknownListItem ?? defaultRenderers.unknownListItem,
384
- unknownMark: options.unknownMark ?? defaultRenderers.unknownMark
385
- }, renderBlockSpacing = options.blockSpacing ?? DefaultBlockSpacingRenderer, listIndexMap = buildListIndexMap(blocks), renderNode = createRenderNode(renderers, listIndexMap);
386
- return blocks.map((node, index) => {
387
- const renderedNode = renderNode({
388
- node,
389
- index,
390
- isInline: !1,
391
- renderNode
392
- });
393
- if (index === blocks.length - 1)
394
- return renderedNode;
395
- const nextNode = blocks.at(index + 1);
396
- if (!nextNode)
397
- return renderedNode;
398
- const blockSpacing = renderBlockSpacing({
399
- current: node,
400
- next: nextNode
401
- }) ?? `
402
-
403
- `;
404
- return `${renderedNode}${blockSpacing}`;
405
- }).join("");
347
+ let renderers = {
348
+ block: {
349
+ ...defaultRenderers.block,
350
+ ...options.block
351
+ },
352
+ listItem: options.listItem ?? defaultRenderers.listItem,
353
+ marks: {
354
+ ...defaultRenderers.marks,
355
+ ...options.marks
356
+ },
357
+ types: {
358
+ ...defaultRenderers.types,
359
+ ...options.types
360
+ },
361
+ hardBreak: options.hardBreak ?? defaultRenderers.hardBreak,
362
+ unknownType: options.unknownType ?? defaultRenderers.unknownType,
363
+ unknownBlockStyle: options.unknownBlockStyle ?? defaultRenderers.unknownBlockStyle,
364
+ unknownListItem: options.unknownListItem ?? defaultRenderers.unknownListItem,
365
+ unknownMark: options.unknownMark ?? defaultRenderers.unknownMark
366
+ }, renderBlockSpacing = options.blockSpacing ?? DefaultBlockSpacingRenderer, listIndexMap = buildListIndexMap(blocks), renderNode = createRenderNode(renderers, listIndexMap);
367
+ return blocks.map((node, index) => {
368
+ let renderedNode = renderNode({
369
+ node,
370
+ index,
371
+ isInline: !1,
372
+ renderNode
373
+ });
374
+ if (index === blocks.length - 1) return renderedNode;
375
+ let nextNode = blocks.at(index + 1);
376
+ return nextNode ? `${renderedNode}${renderBlockSpacing({
377
+ current: node,
378
+ next: nextNode
379
+ }) ?? "\n\n"}` : renderedNode;
380
+ }).join("");
406
381
  }
407
- const normalStyleDefinition = {
408
- name: "normal"
409
- }, h1StyleDefinition = {
410
- name: "h1"
411
- }, h2StyleDefinition = {
412
- name: "h2"
413
- }, h3StyleDefinition = {
414
- name: "h3"
415
- }, h4StyleDefinition = {
416
- name: "h4"
417
- }, h5StyleDefinition = {
418
- name: "h5"
419
- }, h6StyleDefinition = {
420
- name: "h6"
421
- }, blockquoteStyleDefinition = {
422
- name: "blockquote"
423
- }, defaultOrderedListItemDefinition = {
424
- name: "number"
425
- }, defaultUnorderedListItemDefinition = {
426
- name: "bullet"
427
- }, defaultTaskListItemDefinition = {
428
- name: "task"
429
- }, defaultStrongDecoratorDefinition = {
430
- name: "strong"
431
- }, defaultEmDecoratorDefinition = {
432
- name: "em"
433
- }, defaultCodeDecoratorDefinition = {
434
- name: "code"
435
- }, defaultStrikeThroughDecoratorDefinition = {
436
- name: "strike-through"
437
- }, defaultLinkObjectDefinition = {
438
- name: "link",
439
- fields: [
440
- { name: "href", type: "string" },
441
- { name: "title", type: "string" }
442
- ]
382
+ /********************
383
+ * Default style definitions
384
+ ********************/
385
+ const normalStyleDefinition = { name: "normal" }, h1StyleDefinition = { name: "h1" }, h2StyleDefinition = { name: "h2" }, h3StyleDefinition = { name: "h3" }, h4StyleDefinition = { name: "h4" }, h5StyleDefinition = { name: "h5" }, h6StyleDefinition = { name: "h6" }, blockquoteStyleDefinition = { name: "blockquote" }, defaultOrderedListItemDefinition = { name: "number" }, defaultUnorderedListItemDefinition = { name: "bullet" }, defaultTaskListItemDefinition = { name: "task" }, defaultStrongDecoratorDefinition = { name: "strong" }, defaultEmDecoratorDefinition = { name: "em" }, defaultCodeDecoratorDefinition = { name: "code" }, defaultStrikeThroughDecoratorDefinition = { name: "strike-through" }, defaultLinkObjectDefinition = {
386
+ name: "link",
387
+ fields: [{
388
+ name: "href",
389
+ type: "string"
390
+ }, {
391
+ name: "title",
392
+ type: "string"
393
+ }]
443
394
  }, defaultCodeObjectDefinition = {
444
- name: "code",
445
- fields: [
446
- { name: "language", type: "string" },
447
- { name: "code", type: "string" }
448
- ]
395
+ name: "code",
396
+ fields: [{
397
+ name: "language",
398
+ type: "string"
399
+ }, {
400
+ name: "code",
401
+ type: "string"
402
+ }]
449
403
  }, defaultImageObjectDefinition = {
450
- name: "image",
451
- fields: [
452
- { name: "src", type: "string" },
453
- { name: "alt", type: "string" },
454
- { name: "title", type: "string" }
455
- ]
456
- }, defaultHorizontalRuleObjectDefinition = {
457
- name: "horizontal-rule"
458
- }, defaultHtmlObjectDefinition = {
459
- name: "html",
460
- fields: [{ name: "html", type: "string" }]
404
+ name: "image",
405
+ fields: [
406
+ {
407
+ name: "src",
408
+ type: "string"
409
+ },
410
+ {
411
+ name: "alt",
412
+ type: "string"
413
+ },
414
+ {
415
+ name: "title",
416
+ type: "string"
417
+ }
418
+ ]
419
+ }, defaultHorizontalRuleObjectDefinition = { name: "horizontal-rule" }, defaultHtmlObjectDefinition = {
420
+ name: "html",
421
+ fields: [{
422
+ name: "html",
423
+ type: "string"
424
+ }]
461
425
  }, defaultTableObjectDefinition = {
462
- name: "table",
463
- fields: [
464
- { name: "headerRows", type: "number" },
465
- { name: "alignment", type: "array" },
466
- { name: "rows", type: "array" }
467
- ]
426
+ name: "table",
427
+ fields: [
428
+ {
429
+ name: "headerRows",
430
+ type: "number"
431
+ },
432
+ {
433
+ name: "alignment",
434
+ type: "array"
435
+ },
436
+ {
437
+ name: "rows",
438
+ type: "array"
439
+ }
440
+ ]
468
441
  }, defaultCalloutObjectDefinition = {
469
- name: "callout",
470
- fields: [
471
- { name: "tone", type: "string" },
472
- { name: "content", type: "array" }
473
- ]
474
- }, defaultSchema = compileSchema(
475
- defineSchema({
476
- block: {
477
- fields: [{ name: "checked", type: "boolean" }]
478
- },
479
- styles: [
480
- normalStyleDefinition,
481
- h1StyleDefinition,
482
- h2StyleDefinition,
483
- h3StyleDefinition,
484
- h4StyleDefinition,
485
- h5StyleDefinition,
486
- h6StyleDefinition,
487
- blockquoteStyleDefinition
488
- ],
489
- lists: [
490
- defaultOrderedListItemDefinition,
491
- defaultUnorderedListItemDefinition,
492
- defaultTaskListItemDefinition
493
- ],
494
- decorators: [
495
- defaultStrongDecoratorDefinition,
496
- defaultEmDecoratorDefinition,
497
- defaultCodeDecoratorDefinition,
498
- defaultStrikeThroughDecoratorDefinition
499
- ],
500
- annotations: [defaultLinkObjectDefinition],
501
- blockObjects: [
502
- defaultCalloutObjectDefinition,
503
- defaultCodeObjectDefinition,
504
- defaultHorizontalRuleObjectDefinition,
505
- defaultHtmlObjectDefinition,
506
- defaultImageObjectDefinition,
507
- defaultTableObjectDefinition
508
- ],
509
- inlineObjects: [defaultImageObjectDefinition]
510
- })
511
- );
442
+ name: "callout",
443
+ fields: [{
444
+ name: "tone",
445
+ type: "string"
446
+ }, {
447
+ name: "content",
448
+ type: "array"
449
+ }]
450
+ }, defaultSchema = compileSchema(defineSchema({
451
+ block: { fields: [{
452
+ name: "checked",
453
+ type: "boolean"
454
+ }] },
455
+ styles: [
456
+ normalStyleDefinition,
457
+ h1StyleDefinition,
458
+ h2StyleDefinition,
459
+ h3StyleDefinition,
460
+ h4StyleDefinition,
461
+ h5StyleDefinition,
462
+ h6StyleDefinition,
463
+ blockquoteStyleDefinition
464
+ ],
465
+ lists: [
466
+ defaultOrderedListItemDefinition,
467
+ defaultUnorderedListItemDefinition,
468
+ defaultTaskListItemDefinition
469
+ ],
470
+ decorators: [
471
+ defaultStrongDecoratorDefinition,
472
+ defaultEmDecoratorDefinition,
473
+ defaultCodeDecoratorDefinition,
474
+ defaultStrikeThroughDecoratorDefinition
475
+ ],
476
+ annotations: [defaultLinkObjectDefinition],
477
+ blockObjects: [
478
+ defaultCalloutObjectDefinition,
479
+ defaultCodeObjectDefinition,
480
+ defaultHorizontalRuleObjectDefinition,
481
+ defaultHtmlObjectDefinition,
482
+ defaultImageObjectDefinition,
483
+ defaultTableObjectDefinition
484
+ ],
485
+ inlineObjects: [defaultImageObjectDefinition]
486
+ }));
512
487
  function buildStyleMatcher(definition) {
513
- return ({ context }) => {
514
- const schemaDefinition = context.schema.styles.find(
515
- (item) => item.name === definition.name
516
- );
517
- if (schemaDefinition)
518
- return schemaDefinition.name;
519
- };
488
+ return ({ context }) => {
489
+ let schemaDefinition = context.schema.styles.find((item) => item.name === definition.name);
490
+ if (schemaDefinition) return schemaDefinition.name;
491
+ };
520
492
  }
521
493
  function buildListItemMatcher(definition) {
522
- return ({ context }) => {
523
- const schemaDefinition = context.schema.lists.find(
524
- (item) => item.name === definition.name
525
- );
526
- if (schemaDefinition)
527
- return schemaDefinition.name;
528
- };
494
+ return ({ context }) => {
495
+ let schemaDefinition = context.schema.lists.find((item) => item.name === definition.name);
496
+ if (schemaDefinition) return schemaDefinition.name;
497
+ };
529
498
  }
530
499
  function buildDecoratorMatcher(definition) {
531
- return ({ context }) => {
532
- const schemaDefinition = context.schema.decorators.find(
533
- (item) => item.name === definition.name
534
- );
535
- if (schemaDefinition)
536
- return schemaDefinition.name;
537
- };
500
+ return ({ context }) => {
501
+ let schemaDefinition = context.schema.decorators.find((item) => item.name === definition.name);
502
+ if (schemaDefinition) return schemaDefinition.name;
503
+ };
538
504
  }
539
505
  function buildAnnotationMatcher(definition) {
540
- return ({ context, value }) => {
541
- const schemaDefinition = context.schema.annotations.find(
542
- (item) => item.name === definition.name
543
- );
544
- if (!schemaDefinition)
545
- return;
546
- const filteredValue = schemaDefinition.fields.reduce((filteredValue2, field) => {
547
- const fieldValue = value[field.name];
548
- return fieldValue !== void 0 && (filteredValue2[field.name] = fieldValue), filteredValue2;
549
- }, {});
550
- return {
551
- _key: context.keyGenerator(),
552
- _type: schemaDefinition.name,
553
- ...filteredValue
554
- };
555
- };
506
+ return ({ context, value }) => {
507
+ let schemaDefinition = context.schema.annotations.find((item) => item.name === definition.name);
508
+ if (!schemaDefinition) return;
509
+ let filteredValue = schemaDefinition.fields.reduce((filteredValue, field) => {
510
+ let fieldValue = value[field.name];
511
+ return fieldValue !== void 0 && (filteredValue[field.name] = fieldValue), filteredValue;
512
+ }, {});
513
+ return {
514
+ _key: context.keyGenerator(),
515
+ _type: schemaDefinition.name,
516
+ ...filteredValue
517
+ };
518
+ };
556
519
  }
557
520
  function buildObjectMatcher(definition) {
558
- return ({ context, value, isInline }) => {
559
- const schemaDefinition = (isInline ? context.schema.inlineObjects : context.schema.blockObjects).find(
560
- (item) => item.name === definition.name
561
- );
562
- if (!schemaDefinition)
563
- return;
564
- const filteredValue = schemaDefinition.fields.reduce((filteredValue2, field) => {
565
- const fieldValue = value[field.name];
566
- return fieldValue !== void 0 && (filteredValue2[field.name] = fieldValue), filteredValue2;
567
- }, {});
568
- return {
569
- _key: context.keyGenerator(),
570
- _type: schemaDefinition.name,
571
- ...filteredValue
572
- };
573
- };
521
+ return ({ context, value, isInline }) => {
522
+ let schemaDefinition = (isInline ? context.schema.inlineObjects : context.schema.blockObjects).find((item) => item.name === definition.name);
523
+ if (!schemaDefinition) return;
524
+ let filteredValue = schemaDefinition.fields.reduce((filteredValue, field) => {
525
+ let fieldValue = value[field.name];
526
+ return fieldValue !== void 0 && (filteredValue[field.name] = fieldValue), filteredValue;
527
+ }, {});
528
+ return {
529
+ _key: context.keyGenerator(),
530
+ _type: schemaDefinition.name,
531
+ ...filteredValue
532
+ };
533
+ };
574
534
  }
575
535
  const codeBlockMatcher = ({ context, value, isInline }) => {
576
- const codeObject = buildObjectMatcher(defaultCodeObjectDefinition)({ context, value, isInline });
577
- if (codeObject && "code" in codeObject)
578
- return codeObject;
536
+ let codeObject = buildObjectMatcher(defaultCodeObjectDefinition)({
537
+ context,
538
+ value,
539
+ isInline
540
+ });
541
+ if (codeObject && "code" in codeObject) return codeObject;
579
542
  }, imageBlockMatcher = ({ context, value, isInline }) => {
580
- const imageObject = buildObjectMatcher(defaultImageObjectDefinition)({ context, value, isInline });
581
- if (imageObject && "src" in imageObject)
582
- return imageObject;
543
+ let imageObject = buildObjectMatcher(defaultImageObjectDefinition)({
544
+ context,
545
+ value,
546
+ isInline
547
+ });
548
+ if (imageObject && "src" in imageObject) return imageObject;
583
549
  }, defaultOptions = {
584
- block: {
585
- normal: buildStyleMatcher(normalStyleDefinition),
586
- blockquote: buildStyleMatcher(blockquoteStyleDefinition),
587
- h1: buildStyleMatcher(h1StyleDefinition),
588
- h2: buildStyleMatcher(h2StyleDefinition),
589
- h3: buildStyleMatcher(h3StyleDefinition),
590
- h4: buildStyleMatcher(h4StyleDefinition),
591
- h5: buildStyleMatcher(h5StyleDefinition),
592
- h6: buildStyleMatcher(h6StyleDefinition)
593
- },
594
- listItem: {
595
- number: buildListItemMatcher(defaultOrderedListItemDefinition),
596
- bullet: buildListItemMatcher(defaultUnorderedListItemDefinition),
597
- task: buildListItemMatcher(defaultTaskListItemDefinition)
598
- },
599
- marks: {
600
- strong: buildDecoratorMatcher(defaultStrongDecoratorDefinition),
601
- em: buildDecoratorMatcher(defaultEmDecoratorDefinition),
602
- code: buildDecoratorMatcher(defaultCodeDecoratorDefinition),
603
- strikeThrough: buildDecoratorMatcher(
604
- defaultStrikeThroughDecoratorDefinition
605
- ),
606
- link: buildAnnotationMatcher(defaultLinkObjectDefinition)
607
- },
608
- types: {
609
- code: codeBlockMatcher,
610
- horizontalRule: buildObjectMatcher(defaultHorizontalRuleObjectDefinition),
611
- html: buildObjectMatcher(defaultHtmlObjectDefinition),
612
- image: imageBlockMatcher,
613
- callout: buildObjectMatcher(defaultCalloutObjectDefinition)
614
- }
550
+ schema: defaultSchema,
551
+ keyGenerator: defaultKeyGenerator,
552
+ html: { inline: "skip" },
553
+ block: {
554
+ normal: buildStyleMatcher(normalStyleDefinition),
555
+ blockquote: buildStyleMatcher(blockquoteStyleDefinition),
556
+ h1: buildStyleMatcher(h1StyleDefinition),
557
+ h2: buildStyleMatcher(h2StyleDefinition),
558
+ h3: buildStyleMatcher(h3StyleDefinition),
559
+ h4: buildStyleMatcher(h4StyleDefinition),
560
+ h5: buildStyleMatcher(h5StyleDefinition),
561
+ h6: buildStyleMatcher(h6StyleDefinition)
562
+ },
563
+ listItem: {
564
+ number: buildListItemMatcher(defaultOrderedListItemDefinition),
565
+ bullet: buildListItemMatcher(defaultUnorderedListItemDefinition),
566
+ task: buildListItemMatcher(defaultTaskListItemDefinition)
567
+ },
568
+ marks: {
569
+ strong: buildDecoratorMatcher(defaultStrongDecoratorDefinition),
570
+ em: buildDecoratorMatcher(defaultEmDecoratorDefinition),
571
+ code: buildDecoratorMatcher(defaultCodeDecoratorDefinition),
572
+ strikeThrough: buildDecoratorMatcher(defaultStrikeThroughDecoratorDefinition),
573
+ link: buildAnnotationMatcher(defaultLinkObjectDefinition)
574
+ },
575
+ types: {
576
+ code: codeBlockMatcher,
577
+ horizontalRule: buildObjectMatcher(defaultHorizontalRuleObjectDefinition),
578
+ html: buildObjectMatcher(defaultHtmlObjectDefinition),
579
+ image: imageBlockMatcher,
580
+ callout: buildObjectMatcher(defaultCalloutObjectDefinition)
581
+ }
615
582
  };
583
+ /**
584
+ * Reads GFM column alignment from a markdown-it cell token's `style`
585
+ * attribute. Tolerates other CSS declarations sharing the value.
586
+ */
616
587
  function extractAlignmentFromStyleAttr(styleAttr) {
617
- if (!styleAttr)
618
- return null;
619
- const match = styleAttr.match(/text-align\s*:\s*(left|center|right)/);
620
- return match ? match[1] : null;
588
+ if (!styleAttr) return null;
589
+ let match = styleAttr.match(/text-align\s*:\s*(left|center|right)/);
590
+ return match ? match[1] : null;
621
591
  }
592
+ /**
593
+ * A table row is empty when every cell holds only blank spans, no non-empty
594
+ * text, no inline objects, no non-text blocks. Used to detect a headerless
595
+ * GFM table: `portableTextToMarkdown` emits an empty header row for
596
+ * `headerRows: 0`, and an empty header must round-trip back to
597
+ * `headerRows: 0` rather than a phantom header row.
598
+ */
622
599
  function isEmptyTableRow(cells, context) {
623
- return cells.every(
624
- (cell) => cell.value.every(
625
- (block) => isTextBlock(context, block) && block.children.every(
626
- (child) => isSpan(context, child) && (child.text ?? "").trim() === ""
627
- )
628
- )
629
- );
600
+ return cells.every((cell) => cell.value.every((block) => isTextBlock(context, block) && block.children.every((child) => isSpan(context, child) && (child.text ?? "").trim() === "")));
630
601
  }
602
+ /**
603
+ * Flattens a table structure by lifting all blocks from all cells.
604
+ */
631
605
  function flattenTable(table, portableText) {
632
- for (const row of table.rows)
633
- for (const cell of row.cells)
634
- for (const block of cell.value)
635
- portableText.push(block);
606
+ for (let row of table.rows) for (let cell of row.cells) for (let block of cell.value) portableText.push(block);
636
607
  }
608
+ /**
609
+ * Converts a markdown string to an array of Portable Text blocks.
610
+ *
611
+ * @public
612
+ */
637
613
  function markdownToPortableText(markdown, options) {
638
- const consolidatedOptions = {
639
- schema: options?.schema ?? defaultSchema,
640
- keyGenerator: options?.keyGenerator ?? defaultKeyGenerator,
641
- html: {
642
- inline: options?.html?.inline ?? "skip"
643
- },
644
- marks: {
645
- ...defaultOptions.marks,
646
- ...options?.marks
647
- },
648
- block: {
649
- ...defaultOptions.block,
650
- ...options?.block
651
- },
652
- listItem: {
653
- ...defaultOptions.listItem,
654
- ...options?.listItem
655
- },
656
- types: {
657
- ...defaultOptions.types,
658
- ...options?.types
659
- }
660
- }, tokens = markdownit({
661
- html: !0,
662
- linkify: !0,
663
- typographer: !1
664
- }).enable(["strikethrough", "table"]).use(alert).parse(markdown, {}), taskCheckedByListItemIndex = /* @__PURE__ */ new Map();
665
- for (let i = 0; i < tokens.length; i++) {
666
- if (tokens[i]?.type !== "list_item_open")
667
- continue;
668
- let inlineIndex = -1;
669
- for (let j = i + 1; j < tokens.length; j++) {
670
- const candidate = tokens[j];
671
- if (candidate) {
672
- if (candidate.type === "list_item_close")
673
- break;
674
- if (candidate.type === "inline") {
675
- inlineIndex = j;
676
- break;
677
- }
678
- }
679
- }
680
- if (inlineIndex === -1)
681
- continue;
682
- const inlineToken = tokens[inlineIndex];
683
- if (!inlineToken)
684
- continue;
685
- const match = inlineToken.content.match(/^\[([ xX])\] /);
686
- if (!match)
687
- continue;
688
- const checked = match[1] !== " ";
689
- taskCheckedByListItemIndex.set(i, checked), inlineToken.content = inlineToken.content.slice(match[0].length);
690
- const firstChild = inlineToken.children?.[0];
691
- firstChild && typeof firstChild.content == "string" && (firstChild.content = firstChild.content.slice(match[0].length));
692
- }
693
- const portableText = [];
694
- let currentBlock = null;
695
- const currentListStack = [], markDefRefs = [];
696
- let currentMarkDefs = [], currentBlockquoteStyle = null, inListItem = !1, calloutStartIndex = null, calloutStartTarget = null, calloutType = null;
697
- const blockquoteStack = [];
698
- let currentTable = null, currentTableRow = null, inTableHead = !1;
699
- const listContainerStack = [], blockTarget = () => {
700
- for (let i = listContainerStack.length - 1; i >= 0; i--) {
701
- const frame = listContainerStack[i];
702
- if (frame && frame.currentItem)
703
- return frame.currentItem.content;
704
- }
705
- return portableText;
706
- }, pushBlock = (block) => {
707
- blockTarget().push(block);
708
- }, startBlock = (style) => {
709
- flushBlock(), currentBlock = {
710
- _type: "block",
711
- style,
712
- children: [],
713
- _key: consolidatedOptions.keyGenerator(),
714
- markDefs: []
715
- }, currentMarkDefs = [];
716
- }, flushBlock = () => {
717
- currentBlock && (currentBlock.children.length === 0 && currentBlock.children.push({
718
- _type: consolidatedOptions.schema.span.name,
719
- _key: consolidatedOptions.keyGenerator(),
720
- text: "",
721
- marks: []
722
- }), currentBlock.markDefs = currentMarkDefs, pushBlock(currentBlock), currentBlock = null, currentMarkDefs = []);
723
- }, addSpan = (text) => {
724
- if (text.length === 0)
725
- return;
726
- if (!currentBlock) {
727
- const style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({
728
- context: { schema: consolidatedOptions.schema }
729
- });
730
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal"));
731
- }
732
- if (!currentBlock)
733
- throw new Error("Expected current block");
734
- const lastChild = currentBlock.children.at(-1);
735
- isSpan({ schema: consolidatedOptions.schema }, lastChild) && lastChild.marks?.every((mark) => markDefRefs.includes(mark)) && markDefRefs.every((mark) => lastChild.marks?.includes(mark)) ? lastChild.text += text : currentBlock.children.push({
736
- _type: consolidatedOptions.schema.span.name,
737
- _key: consolidatedOptions.keyGenerator(),
738
- text,
739
- marks: [...markDefRefs]
740
- });
741
- }, listLevel = () => currentListStack.length, ensureListBlock = (listItem, checked) => {
742
- if (!currentBlock) {
743
- const style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({
744
- context: { schema: consolidatedOptions.schema }
745
- });
746
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal"));
747
- }
748
- if (!currentBlock)
749
- throw new Error("Expected current block");
750
- (currentBlock.listItem !== listItem || currentBlock.level !== listLevel()) && (currentBlock.listItem = listItem, currentBlock.level = listLevel()), checked !== void 0 && (currentBlock.checked = checked);
751
- };
752
- for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
753
- const token = tokens[tokenIndex];
754
- if (token)
755
- switch (token.type) {
756
- // Paragraphs
757
- case "paragraph_open": {
758
- if (inListItem) {
759
- if (listContainerStack.at(-1)) {
760
- if (!currentBlock) {
761
- const style2 = currentBlockquoteStyle ?? consolidatedOptions.block.normal({
762
- context: { schema: consolidatedOptions.schema }
763
- }) ?? "normal";
764
- startBlock(style2);
765
- }
766
- break;
767
- }
768
- if (!currentBlock) {
769
- const listType = currentListStack.at(-1);
770
- listType && ensureListBlock(listType);
771
- }
772
- break;
773
- }
774
- const style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({
775
- context: { schema: consolidatedOptions.schema }
776
- });
777
- if (!style) {
778
- console.warn('No default style found, using "normal"'), startBlock("normal");
779
- break;
780
- }
781
- startBlock(style);
782
- break;
783
- }
784
- case "paragraph_close":
785
- if (inListItem) {
786
- listContainerStack.at(-1) && flushBlock();
787
- break;
788
- }
789
- flushBlock();
790
- break;
791
- // Headings
792
- case "heading_open": {
793
- const level = Number(token?.tag?.slice(1)), headingMatcher = {
794
- 1: consolidatedOptions.block.h1,
795
- 2: consolidatedOptions.block.h2,
796
- 3: consolidatedOptions.block.h3,
797
- 4: consolidatedOptions.block.h4,
798
- 5: consolidatedOptions.block.h5,
799
- 6: consolidatedOptions.block.h6
800
- }[level], style = headingMatcher?.({
801
- context: { schema: consolidatedOptions.schema }
802
- }) ?? consolidatedOptions.block.normal({
803
- context: { schema: consolidatedOptions.schema }
804
- });
805
- if (!style) {
806
- console.warn('No heading style found, using "normal"'), startBlock("normal");
807
- break;
808
- }
809
- startBlock(style);
810
- break;
811
- }
812
- case "heading_close":
813
- flushBlock();
814
- break;
815
- // Blockquote
816
- case "blockquote_open": {
817
- if (flushBlock(), consolidatedOptions.types.blockquote) {
818
- const startTarget = blockTarget();
819
- blockquoteStack.push({
820
- startTarget,
821
- startIndex: startTarget.length
822
- });
823
- break;
824
- }
825
- currentBlockquoteStyle = consolidatedOptions.block.blockquote({
826
- context: { schema: consolidatedOptions.schema }
827
- }) ?? consolidatedOptions.block.normal({
828
- context: { schema: consolidatedOptions.schema }
829
- }) ?? "normal";
830
- break;
831
- }
832
- case "blockquote_close": {
833
- if (flushBlock(), consolidatedOptions.types.blockquote && blockquoteStack.length > 0) {
834
- const frame = blockquoteStack.pop();
835
- if (frame) {
836
- const contentBlocks = frame.startTarget.splice(
837
- frame.startIndex
838
- ), blockquoteObject = consolidatedOptions.types.blockquote({
839
- context: {
840
- schema: consolidatedOptions.schema,
841
- keyGenerator: consolidatedOptions.keyGenerator
842
- },
843
- value: { content: contentBlocks },
844
- isInline: !1
845
- });
846
- if (blockquoteObject)
847
- pushBlock(blockquoteObject);
848
- else {
849
- const blockquoteStyle = consolidatedOptions.block.blockquote({
850
- context: { schema: consolidatedOptions.schema }
851
- }) ?? consolidatedOptions.block.normal({
852
- context: { schema: consolidatedOptions.schema }
853
- }) ?? "blockquote";
854
- for (const block of contentBlocks)
855
- block._type === "block" ? pushBlock({
856
- ...block,
857
- style: blockquoteStyle
858
- }) : pushBlock(block);
859
- }
860
- }
861
- break;
862
- }
863
- currentBlockquoteStyle = null;
864
- break;
865
- }
866
- // Lists
867
- case "bullet_list_open": {
868
- if (flushBlock(), consolidatedOptions.types.list) {
869
- listContainerStack.push({
870
- kind: "bullet",
871
- items: [],
872
- currentItem: null
873
- }), currentListStack.push(null);
874
- break;
875
- }
876
- const listItem = consolidatedOptions.listItem.bullet({
877
- context: { schema: consolidatedOptions.schema }
878
- });
879
- if (listContainerStack.push(null), !listItem) {
880
- currentListStack.push(null);
881
- break;
882
- }
883
- currentListStack.push(listItem);
884
- break;
885
- }
886
- case "ordered_list_open": {
887
- if (flushBlock(), consolidatedOptions.types.list) {
888
- listContainerStack.push({
889
- kind: "number",
890
- items: [],
891
- currentItem: null
892
- }), currentListStack.push(null);
893
- break;
894
- }
895
- const listItem = consolidatedOptions.listItem.number({
896
- context: { schema: consolidatedOptions.schema }
897
- });
898
- if (listContainerStack.push(null), !listItem) {
899
- currentListStack.push(null);
900
- break;
901
- }
902
- currentListStack.push(listItem);
903
- break;
904
- }
905
- case "bullet_list_close":
906
- case "ordered_list_close": {
907
- const frame = listContainerStack.pop();
908
- if (currentListStack.pop(), frame && consolidatedOptions.types.list) {
909
- const kind = frame.items.some(
910
- (item) => "checked" in item
911
- ) ? "task" : frame.kind, listObject = consolidatedOptions.types.list({
912
- context: {
913
- schema: consolidatedOptions.schema,
914
- keyGenerator: consolidatedOptions.keyGenerator
915
- },
916
- value: { kind, items: frame.items },
917
- isInline: !1
918
- });
919
- if (listObject)
920
- pushBlock(listObject);
921
- else {
922
- const flatListItem = (kind === "task" ? consolidatedOptions.listItem.task?.({
923
- context: { schema: consolidatedOptions.schema }
924
- }) : kind === "number" ? consolidatedOptions.listItem.number({
925
- context: { schema: consolidatedOptions.schema }
926
- }) : consolidatedOptions.listItem.bullet({
927
- context: { schema: consolidatedOptions.schema }
928
- })) ?? null, level = listContainerStack.length + 1;
929
- for (const item of frame.items)
930
- for (const block of item.content)
931
- if (block._type === "block" && flatListItem !== null && !("listItem" in block)) {
932
- const flatBlock = {
933
- ...block,
934
- listItem: flatListItem,
935
- level,
936
- ...item.checked === void 0 ? {} : { checked: item.checked }
937
- };
938
- pushBlock(flatBlock);
939
- } else
940
- pushBlock(block);
941
- }
942
- }
943
- break;
944
- }
945
- case "list_item_open": {
946
- const frame = listContainerStack.at(-1);
947
- if (currentBlock && flushBlock(), frame) {
948
- const taskChecked2 = taskCheckedByListItemIndex.get(tokenIndex);
949
- frame.currentItem = {
950
- _type: "list-item",
951
- _key: consolidatedOptions.keyGenerator(),
952
- ...taskChecked2 === void 0 ? {} : { checked: taskChecked2 },
953
- content: []
954
- }, inListItem = !0;
955
- break;
956
- }
957
- const baseListType = currentListStack.at(-1);
958
- if (baseListType === void 0)
959
- throw new Error("Expected an open list");
960
- const taskChecked = taskCheckedByListItemIndex.get(tokenIndex);
961
- let listType = baseListType, checked;
962
- if (taskChecked !== void 0) {
963
- const taskListType = consolidatedOptions.listItem.task?.({
964
- context: { schema: consolidatedOptions.schema }
965
- });
966
- taskListType && (listType = taskListType, checked = taskChecked);
967
- }
968
- if (listType === null) {
969
- const style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({
970
- context: { schema: consolidatedOptions.schema }
971
- });
972
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal")), inListItem = !0;
973
- break;
974
- }
975
- ensureListBlock(listType, checked), inListItem = !0;
976
- break;
977
- }
978
- case "list_item_close": {
979
- const frame = listContainerStack.at(-1);
980
- if (frame && frame.currentItem) {
981
- flushBlock(), frame.items.push(frame.currentItem), frame.currentItem = null, inListItem = !1;
982
- break;
983
- }
984
- inListItem = !1, flushBlock();
985
- break;
986
- }
987
- // Code fences / blocks
988
- case "fence": {
989
- flushBlock();
990
- const language = token.info.trim() || void 0, code = token.content.replace(/\n$/, ""), codeObject = consolidatedOptions.types.code({
991
- context: {
992
- schema: consolidatedOptions.schema,
993
- keyGenerator: consolidatedOptions.keyGenerator
994
- },
995
- value: { language, code },
996
- isInline: !1
997
- });
998
- if (!codeObject) {
999
- const style = consolidatedOptions.block.normal({
1000
- context: { schema: consolidatedOptions.schema }
1001
- });
1002
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal")), addSpan(code), flushBlock();
1003
- break;
1004
- }
1005
- pushBlock(codeObject);
1006
- break;
1007
- }
1008
- // Horizontal rule
1009
- case "hr": {
1010
- flushBlock();
1011
- const hrObject = consolidatedOptions.types.horizontalRule({
1012
- context: {
1013
- schema: consolidatedOptions.schema,
1014
- keyGenerator: consolidatedOptions.keyGenerator
1015
- },
1016
- value: {},
1017
- isInline: !1
1018
- });
1019
- if (!hrObject) {
1020
- const style = consolidatedOptions.block.normal({
1021
- context: { schema: consolidatedOptions.schema }
1022
- });
1023
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal")), addSpan("---"), flushBlock();
1024
- break;
1025
- }
1026
- pushBlock(hrObject);
1027
- break;
1028
- }
1029
- // HTML block
1030
- case "html_block": {
1031
- flushBlock();
1032
- const htmlContent = token.content.trim();
1033
- if (!htmlContent)
1034
- break;
1035
- const htmlObject = consolidatedOptions.types.html({
1036
- context: {
1037
- schema: consolidatedOptions.schema,
1038
- keyGenerator: consolidatedOptions.keyGenerator
1039
- },
1040
- value: { html: htmlContent },
1041
- isInline: !1
1042
- });
1043
- if (!htmlObject) {
1044
- const style = consolidatedOptions.block.normal({
1045
- context: { schema: consolidatedOptions.schema }
1046
- });
1047
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal")), addSpan(htmlContent), flushBlock();
1048
- break;
1049
- }
1050
- pushBlock(htmlObject);
1051
- break;
1052
- }
1053
- case "code_block": {
1054
- flushBlock();
1055
- const code = token.content.replace(/\n$/, ""), codeObject = consolidatedOptions.types.code({
1056
- context: {
1057
- schema: consolidatedOptions.schema,
1058
- keyGenerator: consolidatedOptions.keyGenerator
1059
- },
1060
- value: { language: void 0, code },
1061
- isInline: !1
1062
- });
1063
- if (codeObject)
1064
- pushBlock(codeObject);
1065
- else {
1066
- const style = consolidatedOptions.block.normal({
1067
- context: { schema: consolidatedOptions.schema }
1068
- });
1069
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal")), addSpan(code), flushBlock();
1070
- }
1071
- break;
1072
- }
1073
- // Tables
1074
- case "table_open":
1075
- flushBlock(), currentTable = {
1076
- rows: [],
1077
- headerRows: 0,
1078
- emptyHeaderDropped: !1,
1079
- alignment: []
1080
- };
1081
- break;
1082
- case "table_close": {
1083
- if (!currentTable)
1084
- break;
1085
- if (consolidatedOptions.types.table) {
1086
- const hasAlignment = currentTable.alignment.some((a) => a !== null), tableObject = consolidatedOptions.types.table({
1087
- context: {
1088
- schema: consolidatedOptions.schema,
1089
- keyGenerator: consolidatedOptions.keyGenerator
1090
- },
1091
- value: {
1092
- rows: currentTable.rows,
1093
- headerRows: currentTable.headerRows > 0 ? currentTable.headerRows : currentTable.emptyHeaderDropped ? 0 : void 0,
1094
- alignment: hasAlignment ? currentTable.alignment : void 0
1095
- },
1096
- isInline: !1
1097
- });
1098
- tableObject ? pushBlock(tableObject) : flattenTable(
1099
- currentTable,
1100
- blockTarget()
1101
- );
1102
- } else
1103
- flattenTable(currentTable, blockTarget());
1104
- currentTable = null;
1105
- break;
1106
- }
1107
- case "thead_open":
1108
- inTableHead = !0;
1109
- break;
1110
- case "thead_close":
1111
- inTableHead = !1;
1112
- break;
1113
- case "tbody_open":
1114
- case "tbody_close":
1115
- break;
1116
- case "tr_open":
1117
- currentTableRow = [];
1118
- break;
1119
- case "tr_close":
1120
- currentTable && currentTableRow && (inTableHead && isEmptyTableRow(currentTableRow, {
1121
- schema: consolidatedOptions.schema
1122
- }) ? currentTable.emptyHeaderDropped = !0 : (currentTable.rows.push({
1123
- _key: consolidatedOptions.keyGenerator(),
1124
- _type: "row",
1125
- cells: currentTableRow
1126
- }), inTableHead && currentTable.headerRows++)), currentTableRow = null;
1127
- break;
1128
- case "th_open":
1129
- case "td_open": {
1130
- currentTable && inTableHead && token.type === "th_open" && currentTable.alignment.push(
1131
- extractAlignmentFromStyleAttr(token.attrGet("style"))
1132
- );
1133
- const style = consolidatedOptions.block.normal({
1134
- context: { schema: consolidatedOptions.schema }
1135
- });
1136
- style ? startBlock(style) : (console.warn('No default style found, using "normal"'), startBlock("normal"));
1137
- break;
1138
- }
1139
- case "th_close":
1140
- case "td_close": {
1141
- flushBlock();
1142
- const cellBlocks = [], target = blockTarget();
1143
- if (target.length > 0) {
1144
- const lastBlock = target.at(-1);
1145
- lastBlock && lastBlock._type === "block" && cellBlocks.push(target.pop());
1146
- }
1147
- cellBlocks.length === 0 && cellBlocks.push({
1148
- _type: "block",
1149
- style: consolidatedOptions.block.normal({
1150
- context: { schema: consolidatedOptions.schema }
1151
- }) || "normal",
1152
- children: [
1153
- {
1154
- _type: consolidatedOptions.schema.span.name,
1155
- _key: consolidatedOptions.keyGenerator(),
1156
- text: "",
1157
- marks: []
1158
- }
1159
- ],
1160
- _key: consolidatedOptions.keyGenerator(),
1161
- markDefs: []
1162
- });
1163
- const firstBlock = cellBlocks[0];
1164
- if (cellBlocks.length === 1 && firstBlock && firstBlock._type === "block" && "children" in firstBlock && Array.isArray(firstBlock.children) && firstBlock.children.length === 1) {
1165
- const onlyChild = firstBlock.children[0];
1166
- typeof onlyChild == "object" && onlyChild !== null && "_type" in onlyChild && onlyChild._type !== consolidatedOptions.schema.span.name && onlyChild._type === "image" && (cellBlocks[0] = onlyChild);
1167
- }
1168
- currentTableRow !== null && currentTableRow.push({
1169
- _type: "cell",
1170
- _key: consolidatedOptions.keyGenerator(),
1171
- value: cellBlocks
1172
- });
1173
- break;
1174
- }
1175
- // Inline container
1176
- case "inline": {
1177
- const inTableCell = currentTableRow !== null;
1178
- if (token.children?.length === 1 && token.children[0]?.type === "image") {
1179
- const imageToken = token.children[0];
1180
- if (!imageToken)
1181
- break;
1182
- const src = imageToken.attrs?.find(([name]) => name === "src")?.at(1) || "", alt = unescapeImageAndLinkText(imageToken.content || ""), title = imageToken.attrs?.find(([name]) => name === "title")?.at(1) || void 0, blockImageObject = consolidatedOptions.types.image({
1183
- context: {
1184
- schema: consolidatedOptions.schema,
1185
- keyGenerator: consolidatedOptions.keyGenerator
1186
- },
1187
- value: { src, alt, title },
1188
- isInline: !1
1189
- });
1190
- if (blockImageObject) {
1191
- inTableCell ? currentBlock && "children" in currentBlock && currentBlock.children.push(
1192
- blockImageObject
1193
- ) : (currentBlock && "children" in currentBlock && currentBlock.children.length > 0 ? flushBlock() : (currentBlock = null, currentMarkDefs = []), pushBlock(blockImageObject));
1194
- break;
1195
- }
1196
- const inlineImageObject = consolidatedOptions.types.image({
1197
- context: {
1198
- schema: consolidatedOptions.schema,
1199
- keyGenerator: consolidatedOptions.keyGenerator
1200
- },
1201
- value: { src, alt, title },
1202
- isInline: !0
1203
- });
1204
- if (inlineImageObject) {
1205
- if (!currentBlock)
1206
- if (inListItem)
1207
- if (listContainerStack.at(-1)) {
1208
- const style = consolidatedOptions.block.normal({
1209
- context: { schema: consolidatedOptions.schema }
1210
- }) ?? "normal";
1211
- startBlock(style);
1212
- } else {
1213
- const listType = currentListStack.at(-1);
1214
- listType && ensureListBlock(listType);
1215
- }
1216
- else {
1217
- const style = consolidatedOptions.block.normal({
1218
- context: { schema: consolidatedOptions.schema }
1219
- });
1220
- style && startBlock(style);
1221
- }
1222
- currentBlock && "children" in currentBlock && currentBlock.children.push(
1223
- inlineImageObject
1224
- );
1225
- break;
1226
- }
1227
- addSpan(`![${alt}](${src})`);
1228
- break;
1229
- }
1230
- for (const childToken of token.children ?? [])
1231
- switch (childToken.type) {
1232
- case "text":
1233
- addSpan(childToken.content);
1234
- break;
1235
- case "softbreak":
1236
- case "hardbreak":
1237
- addSpan(`
1238
- `);
1239
- break;
1240
- case "code_inline": {
1241
- const decorator = consolidatedOptions.marks.code({
1242
- context: { schema: consolidatedOptions.schema }
1243
- });
1244
- if (!decorator) {
1245
- addSpan(childToken.content);
1246
- break;
1247
- }
1248
- markDefRefs.push(decorator), addSpan(childToken.content);
1249
- const index = markDefRefs.lastIndexOf(decorator);
1250
- index !== -1 && markDefRefs.splice(index, 1);
1251
- break;
1252
- }
1253
- case "strong_open": {
1254
- const decorator = consolidatedOptions.marks.strong({
1255
- context: { schema: consolidatedOptions.schema }
1256
- });
1257
- if (!decorator)
1258
- break;
1259
- markDefRefs.push(decorator);
1260
- break;
1261
- }
1262
- case "strong_close": {
1263
- const decorator = consolidatedOptions.marks.strong({
1264
- context: { schema: consolidatedOptions.schema }
1265
- });
1266
- if (!decorator)
1267
- break;
1268
- const index = markDefRefs.lastIndexOf(decorator);
1269
- index !== -1 && markDefRefs.splice(index, 1);
1270
- break;
1271
- }
1272
- case "em_open": {
1273
- const decorator = consolidatedOptions.marks.em({
1274
- context: { schema: consolidatedOptions.schema }
1275
- });
1276
- if (!decorator)
1277
- break;
1278
- markDefRefs.push(decorator);
1279
- break;
1280
- }
1281
- case "em_close": {
1282
- const decorator = consolidatedOptions.marks.em({
1283
- context: { schema: consolidatedOptions.schema }
1284
- });
1285
- if (!decorator)
1286
- break;
1287
- const index = markDefRefs.lastIndexOf(decorator);
1288
- index !== -1 && markDefRefs.splice(index, 1);
1289
- break;
1290
- }
1291
- case "s_open": {
1292
- const decorator = consolidatedOptions.marks.strikeThrough({
1293
- context: { schema: consolidatedOptions.schema }
1294
- });
1295
- if (!decorator)
1296
- break;
1297
- markDefRefs.push(decorator);
1298
- break;
1299
- }
1300
- case "s_close": {
1301
- const decorator = consolidatedOptions.marks.strikeThrough({
1302
- context: { schema: consolidatedOptions.schema }
1303
- });
1304
- if (!decorator)
1305
- break;
1306
- const index = markDefRefs.lastIndexOf(decorator);
1307
- index !== -1 && markDefRefs.splice(index, 1);
1308
- break;
1309
- }
1310
- case "link_open": {
1311
- const href = childToken.attrs?.find(([name]) => name === "href")?.at(1);
1312
- if (!href)
1313
- break;
1314
- const title = childToken.attrs?.find(([name]) => name === "title")?.at(1), linkObject = consolidatedOptions.marks.link({
1315
- context: {
1316
- schema: consolidatedOptions.schema,
1317
- keyGenerator: consolidatedOptions.keyGenerator
1318
- },
1319
- value: { href, title }
1320
- });
1321
- if (!linkObject)
1322
- break;
1323
- currentMarkDefs.push(linkObject), markDefRefs.push(linkObject._key);
1324
- break;
1325
- }
1326
- case "link_close": {
1327
- const markDefKeys = new Set(currentMarkDefs.map((d) => d._key));
1328
- let lastLinkIndex;
1329
- for (const markDefRef of markDefRefs.reverse())
1330
- if (markDefKeys.has(markDefRef)) {
1331
- lastLinkIndex = markDefRefs.indexOf(markDefRef);
1332
- break;
1333
- }
1334
- if (lastLinkIndex !== void 0) {
1335
- const realIndex = markDefRefs.length - 1 - lastLinkIndex;
1336
- markDefRefs.splice(realIndex, 1);
1337
- }
1338
- break;
1339
- }
1340
- case "image": {
1341
- const src = childToken.attrs?.find(([name]) => name === "src")?.at(1) || "", alt = unescapeImageAndLinkText(childToken.content || ""), inlineImageObject = consolidatedOptions.types.image({
1342
- context: {
1343
- schema: consolidatedOptions.schema,
1344
- keyGenerator: consolidatedOptions.keyGenerator
1345
- },
1346
- value: { src, alt, title: void 0 },
1347
- isInline: !0
1348
- });
1349
- if (inlineImageObject) {
1350
- if (!currentBlock) {
1351
- const style2 = consolidatedOptions.block.normal({
1352
- context: { schema: consolidatedOptions.schema }
1353
- });
1354
- style2 ? startBlock(style2) : (console.warn('No default style found, using "normal"'), startBlock("normal"));
1355
- }
1356
- if (!currentBlock)
1357
- throw new Error("Expected current block after startBlock");
1358
- currentBlock.children.push(
1359
- inlineImageObject
1360
- );
1361
- break;
1362
- }
1363
- const blockImageObject = consolidatedOptions.types.image({
1364
- context: {
1365
- schema: consolidatedOptions.schema,
1366
- keyGenerator: consolidatedOptions.keyGenerator
1367
- },
1368
- value: { src, alt, title: void 0 },
1369
- isInline: !1
1370
- });
1371
- if (!blockImageObject) {
1372
- addSpan(`![${alt}](${src})`);
1373
- break;
1374
- }
1375
- if (inTableCell) {
1376
- currentBlock && "children" in currentBlock && currentBlock.children.push(
1377
- blockImageObject
1378
- );
1379
- break;
1380
- }
1381
- flushBlock(), pushBlock(blockImageObject);
1382
- const style = consolidatedOptions.block.normal({
1383
- context: { schema: consolidatedOptions.schema }
1384
- });
1385
- style && startBlock(style);
1386
- break;
1387
- }
1388
- case "html_inline": {
1389
- consolidatedOptions.html.inline === "text" && addSpan(childToken.content);
1390
- break;
1391
- }
1392
- }
1393
- break;
1394
- }
1395
- // Callouts (GFM alerts)
1396
- case "alert_open": {
1397
- flushBlock(), calloutStartTarget = blockTarget(), calloutStartIndex = calloutStartTarget.length, calloutType = token.markup, currentBlockquoteStyle = consolidatedOptions.block.blockquote({
1398
- context: { schema: consolidatedOptions.schema }
1399
- }) ?? consolidatedOptions.block.normal({
1400
- context: { schema: consolidatedOptions.schema }
1401
- }) ?? "normal";
1402
- break;
1403
- }
1404
- case "alert_title":
1405
- break;
1406
- case "alert_close": {
1407
- if (flushBlock(), calloutStartIndex !== null && calloutType !== null && calloutStartTarget !== null) {
1408
- const contentBlocks = calloutStartTarget.splice(
1409
- calloutStartIndex
1410
- ), calloutObject = consolidatedOptions.types.callout?.({
1411
- context: {
1412
- schema: consolidatedOptions.schema,
1413
- keyGenerator: consolidatedOptions.keyGenerator
1414
- },
1415
- value: { tone: calloutType, content: contentBlocks },
1416
- isInline: !1
1417
- });
1418
- if (calloutObject)
1419
- pushBlock(calloutObject);
1420
- else
1421
- for (const block of contentBlocks)
1422
- pushBlock(block);
1423
- }
1424
- calloutStartIndex = null, calloutStartTarget = null, calloutType = null, currentBlockquoteStyle = null;
1425
- break;
1426
- }
1427
- }
1428
- }
1429
- return flushBlock(), portableText;
614
+ let consolidatedOptions = {
615
+ schema: options?.schema ?? defaultSchema,
616
+ keyGenerator: options?.keyGenerator ?? defaultKeyGenerator,
617
+ html: { inline: options?.html?.inline ?? "skip" },
618
+ marks: {
619
+ ...defaultOptions.marks,
620
+ ...options?.marks
621
+ },
622
+ block: {
623
+ ...defaultOptions.block,
624
+ ...options?.block
625
+ },
626
+ listItem: {
627
+ ...defaultOptions.listItem,
628
+ ...options?.listItem
629
+ },
630
+ types: {
631
+ ...defaultOptions.types,
632
+ ...options?.types
633
+ }
634
+ }, tokens = markdownit({
635
+ html: !0,
636
+ linkify: !0,
637
+ typographer: !1
638
+ }).enable(["strikethrough", "table"]).use(alert).parse(markdown, {}), taskCheckedByListItemIndex = /* @__PURE__ */ new Map();
639
+ for (let i = 0; i < tokens.length; i++) {
640
+ if (tokens[i]?.type !== "list_item_open") continue;
641
+ let inlineIndex = -1;
642
+ for (let j = i + 1; j < tokens.length; j++) {
643
+ let candidate = tokens[j];
644
+ if (candidate) {
645
+ if (candidate.type === "list_item_close") break;
646
+ if (candidate.type === "inline") {
647
+ inlineIndex = j;
648
+ break;
649
+ }
650
+ }
651
+ }
652
+ if (inlineIndex === -1) continue;
653
+ let inlineToken = tokens[inlineIndex];
654
+ if (!inlineToken) continue;
655
+ let match = inlineToken.content.match(/^\[([ xX])\] /);
656
+ if (!match) continue;
657
+ let checked = match[1] !== " ";
658
+ taskCheckedByListItemIndex.set(i, checked), inlineToken.content = inlineToken.content.slice(match[0].length);
659
+ let firstChild = inlineToken.children?.[0];
660
+ firstChild && typeof firstChild.content == "string" && (firstChild.content = firstChild.content.slice(match[0].length));
661
+ }
662
+ let portableText = [], currentBlock = null, currentListStack = [], markDefRefs = [], currentMarkDefs = [], currentBlockquoteStyle = null, inListItem = !1, calloutStartIndex = null, calloutStartTarget = null, calloutType = null, blockquoteStack = [], currentTable = null, currentTableRow = null, inTableHead = !1, listContainerStack = [], blockTarget = () => {
663
+ for (let i = listContainerStack.length - 1; i >= 0; i--) {
664
+ let frame = listContainerStack[i];
665
+ if (frame && frame.currentItem) return frame.currentItem.content;
666
+ }
667
+ return portableText;
668
+ }, pushBlock = (block) => {
669
+ blockTarget().push(block);
670
+ }, startBlock = (style) => {
671
+ flushBlock(), currentBlock = {
672
+ _type: "block",
673
+ style,
674
+ children: [],
675
+ _key: consolidatedOptions.keyGenerator(),
676
+ markDefs: []
677
+ }, currentMarkDefs = [];
678
+ }, flushBlock = () => {
679
+ currentBlock && (currentBlock.children.length === 0 && currentBlock.children.push({
680
+ _type: consolidatedOptions.schema.span.name,
681
+ _key: consolidatedOptions.keyGenerator(),
682
+ text: "",
683
+ marks: []
684
+ }), currentBlock.markDefs = currentMarkDefs, pushBlock(currentBlock), currentBlock = null, currentMarkDefs = []);
685
+ }, addSpan = (text) => {
686
+ if (text.length === 0) return;
687
+ if (!currentBlock) {
688
+ let style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
689
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal"));
690
+ }
691
+ if (!currentBlock) throw Error("Expected current block");
692
+ let lastChild = currentBlock.children.at(-1);
693
+ isSpan({ schema: consolidatedOptions.schema }, lastChild) && lastChild.marks?.every((mark) => markDefRefs.includes(mark)) && markDefRefs.every((mark) => lastChild.marks?.includes(mark)) ? lastChild.text += text : currentBlock.children.push({
694
+ _type: consolidatedOptions.schema.span.name,
695
+ _key: consolidatedOptions.keyGenerator(),
696
+ text,
697
+ marks: [...markDefRefs]
698
+ });
699
+ }, listLevel = () => currentListStack.length, ensureListBlock = (listItem, checked) => {
700
+ if (!currentBlock) {
701
+ let style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
702
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal"));
703
+ }
704
+ if (!currentBlock) throw Error("Expected current block");
705
+ (currentBlock.listItem !== listItem || currentBlock.level !== listLevel()) && (currentBlock.listItem = listItem, currentBlock.level = listLevel()), checked !== void 0 && (currentBlock.checked = checked);
706
+ };
707
+ for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
708
+ let token = tokens[tokenIndex];
709
+ if (token) switch (token.type) {
710
+ case "paragraph_open": {
711
+ if (inListItem) {
712
+ if (listContainerStack.at(-1)) {
713
+ currentBlock || startBlock(currentBlockquoteStyle ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) ?? "normal");
714
+ break;
715
+ }
716
+ if (!currentBlock) {
717
+ let listType = currentListStack.at(-1);
718
+ listType && ensureListBlock(listType);
719
+ }
720
+ break;
721
+ }
722
+ let style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
723
+ if (!style) {
724
+ console.warn("No default style found, using \"normal\""), startBlock("normal");
725
+ break;
726
+ }
727
+ startBlock(style);
728
+ break;
729
+ }
730
+ case "paragraph_close":
731
+ if (inListItem) {
732
+ listContainerStack.at(-1) && flushBlock();
733
+ break;
734
+ }
735
+ flushBlock();
736
+ break;
737
+ case "heading_open": {
738
+ let level = Number(token?.tag?.slice(1)), headingMatcher = {
739
+ 1: consolidatedOptions.block.h1,
740
+ 2: consolidatedOptions.block.h2,
741
+ 3: consolidatedOptions.block.h3,
742
+ 4: consolidatedOptions.block.h4,
743
+ 5: consolidatedOptions.block.h5,
744
+ 6: consolidatedOptions.block.h6
745
+ }[level], style = headingMatcher?.({ context: { schema: consolidatedOptions.schema } }) ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
746
+ if (!style) {
747
+ console.warn("No heading style found, using \"normal\""), startBlock("normal");
748
+ break;
749
+ }
750
+ startBlock(style);
751
+ break;
752
+ }
753
+ case "heading_close":
754
+ flushBlock();
755
+ break;
756
+ case "blockquote_open":
757
+ if (flushBlock(), consolidatedOptions.types.blockquote) {
758
+ let startTarget = blockTarget();
759
+ blockquoteStack.push({
760
+ startTarget,
761
+ startIndex: startTarget.length
762
+ });
763
+ break;
764
+ }
765
+ currentBlockquoteStyle = consolidatedOptions.block.blockquote({ context: { schema: consolidatedOptions.schema } }) ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) ?? "normal";
766
+ break;
767
+ case "blockquote_close":
768
+ if (flushBlock(), consolidatedOptions.types.blockquote && blockquoteStack.length > 0) {
769
+ let frame = blockquoteStack.pop();
770
+ if (frame) {
771
+ let contentBlocks = frame.startTarget.splice(frame.startIndex), blockquoteObject = consolidatedOptions.types.blockquote({
772
+ context: {
773
+ schema: consolidatedOptions.schema,
774
+ keyGenerator: consolidatedOptions.keyGenerator
775
+ },
776
+ value: { content: contentBlocks },
777
+ isInline: !1
778
+ });
779
+ if (blockquoteObject) pushBlock(blockquoteObject);
780
+ else {
781
+ let blockquoteStyle = consolidatedOptions.block.blockquote({ context: { schema: consolidatedOptions.schema } }) ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) ?? "blockquote";
782
+ for (let block of contentBlocks) block._type === "block" ? pushBlock({
783
+ ...block,
784
+ style: blockquoteStyle
785
+ }) : pushBlock(block);
786
+ }
787
+ }
788
+ break;
789
+ }
790
+ currentBlockquoteStyle = null;
791
+ break;
792
+ case "bullet_list_open": {
793
+ if (flushBlock(), consolidatedOptions.types.list) {
794
+ listContainerStack.push({
795
+ kind: "bullet",
796
+ items: [],
797
+ currentItem: null
798
+ }), currentListStack.push(null);
799
+ break;
800
+ }
801
+ let listItem = consolidatedOptions.listItem.bullet({ context: { schema: consolidatedOptions.schema } });
802
+ if (listContainerStack.push(null), !listItem) {
803
+ currentListStack.push(null);
804
+ break;
805
+ }
806
+ currentListStack.push(listItem);
807
+ break;
808
+ }
809
+ case "ordered_list_open": {
810
+ if (flushBlock(), consolidatedOptions.types.list) {
811
+ listContainerStack.push({
812
+ kind: "number",
813
+ items: [],
814
+ currentItem: null
815
+ }), currentListStack.push(null);
816
+ break;
817
+ }
818
+ let listItem = consolidatedOptions.listItem.number({ context: { schema: consolidatedOptions.schema } });
819
+ if (listContainerStack.push(null), !listItem) {
820
+ currentListStack.push(null);
821
+ break;
822
+ }
823
+ currentListStack.push(listItem);
824
+ break;
825
+ }
826
+ case "bullet_list_close":
827
+ case "ordered_list_close": {
828
+ let frame = listContainerStack.pop();
829
+ if (currentListStack.pop(), frame && consolidatedOptions.types.list) {
830
+ let kind = frame.items.some((item) => "checked" in item) ? "task" : frame.kind, listObject = consolidatedOptions.types.list({
831
+ context: {
832
+ schema: consolidatedOptions.schema,
833
+ keyGenerator: consolidatedOptions.keyGenerator
834
+ },
835
+ value: {
836
+ kind,
837
+ items: frame.items
838
+ },
839
+ isInline: !1
840
+ });
841
+ if (listObject) pushBlock(listObject);
842
+ else {
843
+ let flatListItem = (kind === "task" ? consolidatedOptions.listItem.task?.({ context: { schema: consolidatedOptions.schema } }) : kind === "number" ? consolidatedOptions.listItem.number({ context: { schema: consolidatedOptions.schema } }) : consolidatedOptions.listItem.bullet({ context: { schema: consolidatedOptions.schema } })) ?? null, level = listContainerStack.length + 1;
844
+ for (let item of frame.items) for (let block of item.content) block._type === "block" && flatListItem !== null && !("listItem" in block) ? pushBlock({
845
+ ...block,
846
+ listItem: flatListItem,
847
+ level,
848
+ ...item.checked === void 0 ? {} : { checked: item.checked }
849
+ }) : pushBlock(block);
850
+ }
851
+ }
852
+ break;
853
+ }
854
+ case "list_item_open": {
855
+ let frame = listContainerStack.at(-1);
856
+ if (currentBlock && flushBlock(), frame) {
857
+ let taskChecked = taskCheckedByListItemIndex.get(tokenIndex);
858
+ frame.currentItem = {
859
+ _type: "list-item",
860
+ _key: consolidatedOptions.keyGenerator(),
861
+ ...taskChecked === void 0 ? {} : { checked: taskChecked },
862
+ content: []
863
+ }, inListItem = !0;
864
+ break;
865
+ }
866
+ let baseListType = currentListStack.at(-1);
867
+ if (baseListType === void 0) throw Error("Expected an open list");
868
+ let taskChecked = taskCheckedByListItemIndex.get(tokenIndex), listType = baseListType, checked;
869
+ if (taskChecked !== void 0) {
870
+ let taskListType = consolidatedOptions.listItem.task?.({ context: { schema: consolidatedOptions.schema } });
871
+ taskListType && (listType = taskListType, checked = taskChecked);
872
+ }
873
+ if (listType === null) {
874
+ let style = currentBlockquoteStyle ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
875
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal")), inListItem = !0;
876
+ break;
877
+ }
878
+ ensureListBlock(listType, checked), inListItem = !0;
879
+ break;
880
+ }
881
+ case "list_item_close": {
882
+ let frame = listContainerStack.at(-1);
883
+ if (frame && frame.currentItem) {
884
+ flushBlock(), frame.items.push(frame.currentItem), frame.currentItem = null, inListItem = !1;
885
+ break;
886
+ }
887
+ inListItem = !1, flushBlock();
888
+ break;
889
+ }
890
+ case "fence": {
891
+ flushBlock();
892
+ let language = token.info.trim() || void 0, code = token.content.replace(/\n$/, ""), codeObject = consolidatedOptions.types.code({
893
+ context: {
894
+ schema: consolidatedOptions.schema,
895
+ keyGenerator: consolidatedOptions.keyGenerator
896
+ },
897
+ value: {
898
+ language,
899
+ code
900
+ },
901
+ isInline: !1
902
+ });
903
+ if (!codeObject) {
904
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
905
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal")), addSpan(code), flushBlock();
906
+ break;
907
+ }
908
+ pushBlock(codeObject);
909
+ break;
910
+ }
911
+ case "hr": {
912
+ flushBlock();
913
+ let hrObject = consolidatedOptions.types.horizontalRule({
914
+ context: {
915
+ schema: consolidatedOptions.schema,
916
+ keyGenerator: consolidatedOptions.keyGenerator
917
+ },
918
+ value: {},
919
+ isInline: !1
920
+ });
921
+ if (!hrObject) {
922
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
923
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal")), addSpan("---"), flushBlock();
924
+ break;
925
+ }
926
+ pushBlock(hrObject);
927
+ break;
928
+ }
929
+ case "html_block": {
930
+ flushBlock();
931
+ let htmlContent = token.content.trim();
932
+ if (!htmlContent) break;
933
+ let htmlObject = consolidatedOptions.types.html({
934
+ context: {
935
+ schema: consolidatedOptions.schema,
936
+ keyGenerator: consolidatedOptions.keyGenerator
937
+ },
938
+ value: { html: htmlContent },
939
+ isInline: !1
940
+ });
941
+ if (!htmlObject) {
942
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
943
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal")), addSpan(htmlContent), flushBlock();
944
+ break;
945
+ }
946
+ pushBlock(htmlObject);
947
+ break;
948
+ }
949
+ case "code_block": {
950
+ flushBlock();
951
+ let code = token.content.replace(/\n$/, ""), codeObject = consolidatedOptions.types.code({
952
+ context: {
953
+ schema: consolidatedOptions.schema,
954
+ keyGenerator: consolidatedOptions.keyGenerator
955
+ },
956
+ value: {
957
+ language: void 0,
958
+ code
959
+ },
960
+ isInline: !1
961
+ });
962
+ if (codeObject) pushBlock(codeObject);
963
+ else {
964
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
965
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal")), addSpan(code), flushBlock();
966
+ }
967
+ break;
968
+ }
969
+ case "table_open":
970
+ flushBlock(), currentTable = {
971
+ rows: [],
972
+ headerRows: 0,
973
+ emptyHeaderDropped: !1,
974
+ alignment: []
975
+ };
976
+ break;
977
+ case "table_close":
978
+ if (!currentTable) break;
979
+ if (consolidatedOptions.types.table) {
980
+ let hasAlignment = currentTable.alignment.some((a) => a !== null), tableObject = consolidatedOptions.types.table({
981
+ context: {
982
+ schema: consolidatedOptions.schema,
983
+ keyGenerator: consolidatedOptions.keyGenerator
984
+ },
985
+ value: {
986
+ rows: currentTable.rows,
987
+ headerRows: currentTable.headerRows > 0 ? currentTable.headerRows : currentTable.emptyHeaderDropped ? 0 : void 0,
988
+ alignment: hasAlignment ? currentTable.alignment : void 0
989
+ },
990
+ isInline: !1
991
+ });
992
+ tableObject ? pushBlock(tableObject) : flattenTable(currentTable, blockTarget());
993
+ } else flattenTable(currentTable, blockTarget());
994
+ currentTable = null;
995
+ break;
996
+ case "thead_open":
997
+ inTableHead = !0;
998
+ break;
999
+ case "thead_close":
1000
+ inTableHead = !1;
1001
+ break;
1002
+ case "tbody_open":
1003
+ case "tbody_close": break;
1004
+ case "tr_open":
1005
+ currentTableRow = [];
1006
+ break;
1007
+ case "tr_close":
1008
+ currentTable && currentTableRow && (inTableHead && isEmptyTableRow(currentTableRow, { schema: consolidatedOptions.schema }) ? currentTable.emptyHeaderDropped = !0 : (currentTable.rows.push({
1009
+ _key: consolidatedOptions.keyGenerator(),
1010
+ _type: "row",
1011
+ cells: currentTableRow
1012
+ }), inTableHead && currentTable.headerRows++)), currentTableRow = null;
1013
+ break;
1014
+ case "th_open":
1015
+ case "td_open": {
1016
+ currentTable && inTableHead && token.type === "th_open" && currentTable.alignment.push(extractAlignmentFromStyleAttr(token.attrGet("style")));
1017
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
1018
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal"));
1019
+ break;
1020
+ }
1021
+ case "th_close":
1022
+ case "td_close": {
1023
+ flushBlock();
1024
+ let cellBlocks = [], target = blockTarget();
1025
+ if (target.length > 0) {
1026
+ let lastBlock = target.at(-1);
1027
+ lastBlock && lastBlock._type === "block" && cellBlocks.push(target.pop());
1028
+ }
1029
+ cellBlocks.length === 0 && cellBlocks.push({
1030
+ _type: "block",
1031
+ style: consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) || "normal",
1032
+ children: [{
1033
+ _type: consolidatedOptions.schema.span.name,
1034
+ _key: consolidatedOptions.keyGenerator(),
1035
+ text: "",
1036
+ marks: []
1037
+ }],
1038
+ _key: consolidatedOptions.keyGenerator(),
1039
+ markDefs: []
1040
+ });
1041
+ let firstBlock = cellBlocks[0];
1042
+ if (cellBlocks.length === 1 && firstBlock && firstBlock._type === "block" && "children" in firstBlock && Array.isArray(firstBlock.children) && firstBlock.children.length === 1) {
1043
+ let onlyChild = firstBlock.children[0];
1044
+ typeof onlyChild == "object" && onlyChild && "_type" in onlyChild && onlyChild._type !== consolidatedOptions.schema.span.name && onlyChild._type === "image" && (cellBlocks[0] = onlyChild);
1045
+ }
1046
+ currentTableRow !== null && currentTableRow.push({
1047
+ _type: "cell",
1048
+ _key: consolidatedOptions.keyGenerator(),
1049
+ value: cellBlocks
1050
+ });
1051
+ break;
1052
+ }
1053
+ case "inline": {
1054
+ let inTableCell = currentTableRow !== null;
1055
+ if (token.children?.length === 1 && token.children[0]?.type === "image") {
1056
+ let imageToken = token.children[0];
1057
+ if (!imageToken) break;
1058
+ let src = imageToken.attrs?.find(([name]) => name === "src")?.at(1) || "", alt = unescapeImageAndLinkText(imageToken.content || ""), title = imageToken.attrs?.find(([name]) => name === "title")?.at(1) || void 0, blockImageObject = consolidatedOptions.types.image({
1059
+ context: {
1060
+ schema: consolidatedOptions.schema,
1061
+ keyGenerator: consolidatedOptions.keyGenerator
1062
+ },
1063
+ value: {
1064
+ src,
1065
+ alt,
1066
+ title
1067
+ },
1068
+ isInline: !1
1069
+ });
1070
+ if (blockImageObject) {
1071
+ inTableCell ? currentBlock && "children" in currentBlock && currentBlock.children.push(blockImageObject) : (currentBlock && "children" in currentBlock && currentBlock.children.length > 0 ? flushBlock() : (currentBlock = null, currentMarkDefs = []), pushBlock(blockImageObject));
1072
+ break;
1073
+ }
1074
+ let inlineImageObject = consolidatedOptions.types.image({
1075
+ context: {
1076
+ schema: consolidatedOptions.schema,
1077
+ keyGenerator: consolidatedOptions.keyGenerator
1078
+ },
1079
+ value: {
1080
+ src,
1081
+ alt,
1082
+ title
1083
+ },
1084
+ isInline: !0
1085
+ });
1086
+ if (inlineImageObject) {
1087
+ if (!currentBlock) if (inListItem) if (listContainerStack.at(-1)) startBlock(consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) ?? "normal");
1088
+ else {
1089
+ let listType = currentListStack.at(-1);
1090
+ listType && ensureListBlock(listType);
1091
+ }
1092
+ else {
1093
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
1094
+ style && startBlock(style);
1095
+ }
1096
+ currentBlock && "children" in currentBlock && currentBlock.children.push(inlineImageObject);
1097
+ break;
1098
+ }
1099
+ addSpan(`![${alt}](${src})`);
1100
+ break;
1101
+ }
1102
+ for (let childToken of token.children ?? []) switch (childToken.type) {
1103
+ case "text":
1104
+ addSpan(childToken.content);
1105
+ break;
1106
+ case "softbreak":
1107
+ case "hardbreak":
1108
+ addSpan("\n");
1109
+ break;
1110
+ case "code_inline": {
1111
+ let decorator = consolidatedOptions.marks.code({ context: { schema: consolidatedOptions.schema } });
1112
+ if (!decorator) {
1113
+ addSpan(childToken.content);
1114
+ break;
1115
+ }
1116
+ markDefRefs.push(decorator), addSpan(childToken.content);
1117
+ let index = markDefRefs.lastIndexOf(decorator);
1118
+ index !== -1 && markDefRefs.splice(index, 1);
1119
+ break;
1120
+ }
1121
+ case "strong_open": {
1122
+ let decorator = consolidatedOptions.marks.strong({ context: { schema: consolidatedOptions.schema } });
1123
+ if (!decorator) break;
1124
+ markDefRefs.push(decorator);
1125
+ break;
1126
+ }
1127
+ case "strong_close": {
1128
+ let decorator = consolidatedOptions.marks.strong({ context: { schema: consolidatedOptions.schema } });
1129
+ if (!decorator) break;
1130
+ let index = markDefRefs.lastIndexOf(decorator);
1131
+ index !== -1 && markDefRefs.splice(index, 1);
1132
+ break;
1133
+ }
1134
+ case "em_open": {
1135
+ let decorator = consolidatedOptions.marks.em({ context: { schema: consolidatedOptions.schema } });
1136
+ if (!decorator) break;
1137
+ markDefRefs.push(decorator);
1138
+ break;
1139
+ }
1140
+ case "em_close": {
1141
+ let decorator = consolidatedOptions.marks.em({ context: { schema: consolidatedOptions.schema } });
1142
+ if (!decorator) break;
1143
+ let index = markDefRefs.lastIndexOf(decorator);
1144
+ index !== -1 && markDefRefs.splice(index, 1);
1145
+ break;
1146
+ }
1147
+ case "s_open": {
1148
+ let decorator = consolidatedOptions.marks.strikeThrough({ context: { schema: consolidatedOptions.schema } });
1149
+ if (!decorator) break;
1150
+ markDefRefs.push(decorator);
1151
+ break;
1152
+ }
1153
+ case "s_close": {
1154
+ let decorator = consolidatedOptions.marks.strikeThrough({ context: { schema: consolidatedOptions.schema } });
1155
+ if (!decorator) break;
1156
+ let index = markDefRefs.lastIndexOf(decorator);
1157
+ index !== -1 && markDefRefs.splice(index, 1);
1158
+ break;
1159
+ }
1160
+ case "link_open": {
1161
+ let href = childToken.attrs?.find(([name]) => name === "href")?.at(1);
1162
+ if (!href) break;
1163
+ let title = childToken.attrs?.find(([name]) => name === "title")?.at(1), linkObject = consolidatedOptions.marks.link({
1164
+ context: {
1165
+ schema: consolidatedOptions.schema,
1166
+ keyGenerator: consolidatedOptions.keyGenerator
1167
+ },
1168
+ value: {
1169
+ href,
1170
+ title
1171
+ }
1172
+ });
1173
+ if (!linkObject) break;
1174
+ currentMarkDefs.push(linkObject), markDefRefs.push(linkObject._key);
1175
+ break;
1176
+ }
1177
+ case "link_close": {
1178
+ let markDefKeys = new Set(currentMarkDefs.map((d) => d._key)), lastLinkIndex;
1179
+ for (let markDefRef of markDefRefs.reverse()) if (markDefKeys.has(markDefRef)) {
1180
+ lastLinkIndex = markDefRefs.indexOf(markDefRef);
1181
+ break;
1182
+ }
1183
+ if (lastLinkIndex !== void 0) {
1184
+ let realIndex = markDefRefs.length - 1 - lastLinkIndex;
1185
+ markDefRefs.splice(realIndex, 1);
1186
+ }
1187
+ break;
1188
+ }
1189
+ case "image": {
1190
+ let src = childToken.attrs?.find(([name]) => name === "src")?.at(1) || "", alt = unescapeImageAndLinkText(childToken.content || ""), inlineImageObject = consolidatedOptions.types.image({
1191
+ context: {
1192
+ schema: consolidatedOptions.schema,
1193
+ keyGenerator: consolidatedOptions.keyGenerator
1194
+ },
1195
+ value: {
1196
+ src,
1197
+ alt,
1198
+ title: void 0
1199
+ },
1200
+ isInline: !0
1201
+ });
1202
+ if (inlineImageObject) {
1203
+ if (!currentBlock) {
1204
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
1205
+ style ? startBlock(style) : (console.warn("No default style found, using \"normal\""), startBlock("normal"));
1206
+ }
1207
+ if (!currentBlock) throw Error("Expected current block after startBlock");
1208
+ currentBlock.children.push(inlineImageObject);
1209
+ break;
1210
+ }
1211
+ let blockImageObject = consolidatedOptions.types.image({
1212
+ context: {
1213
+ schema: consolidatedOptions.schema,
1214
+ keyGenerator: consolidatedOptions.keyGenerator
1215
+ },
1216
+ value: {
1217
+ src,
1218
+ alt,
1219
+ title: void 0
1220
+ },
1221
+ isInline: !1
1222
+ });
1223
+ if (!blockImageObject) {
1224
+ addSpan(`![${alt}](${src})`);
1225
+ break;
1226
+ }
1227
+ if (inTableCell) {
1228
+ currentBlock && "children" in currentBlock && currentBlock.children.push(blockImageObject);
1229
+ break;
1230
+ }
1231
+ flushBlock(), pushBlock(blockImageObject);
1232
+ let style = consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } });
1233
+ style && startBlock(style);
1234
+ break;
1235
+ }
1236
+ case "html_inline": consolidatedOptions.html.inline === "text" && addSpan(childToken.content);
1237
+ }
1238
+ break;
1239
+ }
1240
+ case "alert_open":
1241
+ flushBlock(), calloutStartTarget = blockTarget(), calloutStartIndex = calloutStartTarget.length, calloutType = token.markup, currentBlockquoteStyle = consolidatedOptions.block.blockquote({ context: { schema: consolidatedOptions.schema } }) ?? consolidatedOptions.block.normal({ context: { schema: consolidatedOptions.schema } }) ?? "normal";
1242
+ break;
1243
+ case "alert_title": break;
1244
+ case "alert_close":
1245
+ if (flushBlock(), calloutStartIndex !== null && calloutType !== null && calloutStartTarget !== null) {
1246
+ let contentBlocks = calloutStartTarget.splice(calloutStartIndex), calloutObject = consolidatedOptions.types.callout?.({
1247
+ context: {
1248
+ schema: consolidatedOptions.schema,
1249
+ keyGenerator: consolidatedOptions.keyGenerator
1250
+ },
1251
+ value: {
1252
+ tone: calloutType,
1253
+ content: contentBlocks
1254
+ },
1255
+ isInline: !1
1256
+ });
1257
+ if (calloutObject) pushBlock(calloutObject);
1258
+ else for (let block of contentBlocks) pushBlock(block);
1259
+ }
1260
+ calloutStartIndex = null, calloutStartTarget = null, calloutType = null, currentBlockquoteStyle = null;
1261
+ }
1262
+ }
1263
+ return flushBlock(), portableText;
1430
1264
  }
1431
- export {
1432
- DefaultBlockSpacingRenderer,
1433
- DefaultBlockquoteObjectRenderer,
1434
- DefaultBlockquoteRenderer,
1435
- DefaultCalloutRenderer,
1436
- DefaultCodeBlockRenderer,
1437
- DefaultCodeRenderer,
1438
- DefaultEmRenderer,
1439
- DefaultH1Renderer,
1440
- DefaultH2Renderer,
1441
- DefaultH3Renderer,
1442
- DefaultH4Renderer,
1443
- DefaultH5Renderer,
1444
- DefaultH6Renderer,
1445
- DefaultHardBreakRenderer,
1446
- DefaultHorizontalRuleRenderer,
1447
- DefaultHtmlRenderer,
1448
- DefaultImageRenderer,
1449
- DefaultLinkRenderer,
1450
- DefaultListItemRenderer,
1451
- DefaultListRenderer,
1452
- DefaultNormalRenderer,
1453
- DefaultStrikeThroughRenderer,
1454
- DefaultStrongRenderer,
1455
- DefaultTableRenderer,
1456
- DefaultUnderlineRenderer,
1457
- markdownToPortableText,
1458
- portableTextToMarkdown
1459
- };
1460
- //# sourceMappingURL=index.js.map
1265
+ export { DefaultBlockSpacingRenderer, DefaultBlockquoteObjectRenderer, DefaultBlockquoteRenderer, DefaultCalloutRenderer, DefaultCodeBlockRenderer, DefaultCodeRenderer, DefaultEmRenderer, DefaultH1Renderer, DefaultH2Renderer, DefaultH3Renderer, DefaultH4Renderer, DefaultH5Renderer, DefaultH6Renderer, DefaultHardBreakRenderer, DefaultHorizontalRuleRenderer, DefaultHtmlRenderer, DefaultImageRenderer, DefaultLinkRenderer, DefaultListItemRenderer, DefaultListRenderer, DefaultNormalRenderer, DefaultStrikeThroughRenderer, DefaultStrongRenderer, DefaultTableRenderer, DefaultUnderlineRenderer, markdownToPortableText, portableTextToMarkdown };
1266
+
1267
+ //# sourceMappingURL=index.js.map