@scrider/formatter 1.2.0 → 1.3.1
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/README.md +31 -2
- package/dist/index.cjs +104 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +103 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1039,6 +1039,27 @@ declare const formulaFormat: Format<string>;
|
|
|
1039
1039
|
*/
|
|
1040
1040
|
declare const imageFormat: Format<string>;
|
|
1041
1041
|
|
|
1042
|
+
/**
|
|
1043
|
+
* Soft Line Break embed format
|
|
1044
|
+
*
|
|
1045
|
+
* Represents a "Shift+Enter" style line break that does NOT split the
|
|
1046
|
+
* containing block (paragraph, list item, table cell, etc.). This is the
|
|
1047
|
+
* Delta-level analogue of HTML `<br>` used as an inline line break and
|
|
1048
|
+
* of the GFM "hard break" Markdown construct (two trailing spaces + `\n`).
|
|
1049
|
+
*
|
|
1050
|
+
* Delta: `{ insert: { softBreak: true } }`
|
|
1051
|
+
* HTML: `<br data-scrider-embed>` (with the explicit marker so that
|
|
1052
|
+
* round-trip parsing can distinguish a soft break from the
|
|
1053
|
+
* placeholder `<br>` that appears inside an empty paragraph)
|
|
1054
|
+
* Markdown: ` \n` (default GFM hard break) or inline `<br>` (configurable
|
|
1055
|
+
* via `softBreakStyle` option on `deltaToMarkdown`)
|
|
1056
|
+
*
|
|
1057
|
+
* Value is always `true` — the embed has no additional data.
|
|
1058
|
+
*
|
|
1059
|
+
* @see {@link https://github.github.com/gfm/#hard-line-breaks GFM hard line break}
|
|
1060
|
+
*/
|
|
1061
|
+
declare const softBreakFormat: Format<boolean>;
|
|
1062
|
+
|
|
1042
1063
|
/**
|
|
1043
1064
|
* Video embed format
|
|
1044
1065
|
*
|
|
@@ -1557,6 +1578,22 @@ interface DeltaToMarkdownOptions {
|
|
|
1557
1578
|
* `render()` is used as HTML fallback in Markdown.
|
|
1558
1579
|
*/
|
|
1559
1580
|
registry?: Registry;
|
|
1581
|
+
/**
|
|
1582
|
+
* Rendering style for `{ softBreak: true }` embeds (Phase 7 Part 0).
|
|
1583
|
+
*
|
|
1584
|
+
* - `'spaces'` (default): GFM-canonical hard break — two trailing spaces
|
|
1585
|
+
* followed by `\n` (`" \n"`). Round-trips losslessly through remark.
|
|
1586
|
+
* - `'html'`: inline `<br>` tag. Slightly more visible in source view
|
|
1587
|
+
* and immune to editor whitespace trimming. Recommended for the
|
|
1588
|
+
* LFM (LLM-Flavored Markdown) flavour exposed by the editor's
|
|
1589
|
+
* "source" toggle.
|
|
1590
|
+
*
|
|
1591
|
+
* Does not affect how soft breaks are rendered inside table cells —
|
|
1592
|
+
* those always use inline `<br>` because GFM tables forbid raw `\n`.
|
|
1593
|
+
*
|
|
1594
|
+
* @default 'spaces'
|
|
1595
|
+
*/
|
|
1596
|
+
softBreakStyle?: 'spaces' | 'html';
|
|
1560
1597
|
/**
|
|
1561
1598
|
* Strip trailing newlines from the final output.
|
|
1562
1599
|
*
|
|
@@ -1779,4 +1816,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1779
1816
|
*/
|
|
1780
1817
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1781
1818
|
|
|
1782
|
-
export { ALERT_TYPES, type AlertBlockData, type AlertType, type AlignType, BOX_FLOAT_VALUES, BOX_OVERFLOW_VALUES, type BlockContext, type BlockHandler, BlockHandlerRegistry, type BlockRenderOptions, type BoxBlockData, type BoxFloat, type BoxOpAttributes, type BoxOverflow, BrowserDOMAdapter, type CellAlign, type CellData, type ColumnsBlockData, type DOMAdapter, type DOMDocument, type DOMDocumentFragment, type DOMElement, type DOMNode, type DOMNodeList, type DeltaToHtmlOptions, type DeltaToMarkdownOptions, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, Registry, type SanitizeOptions, type TableBlockData, type TableColAlignType, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, preloadRemark, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
|
1819
|
+
export { ALERT_TYPES, type AlertBlockData, type AlertType, type AlignType, BOX_FLOAT_VALUES, BOX_OVERFLOW_VALUES, type BlockContext, type BlockHandler, BlockHandlerRegistry, type BlockRenderOptions, type BoxBlockData, type BoxFloat, type BoxOpAttributes, type BoxOverflow, BrowserDOMAdapter, type CellAlign, type CellData, type ColumnsBlockData, type DOMAdapter, type DOMDocument, type DOMDocumentFragment, type DOMElement, type DOMNode, type DOMNodeList, type DeltaToHtmlOptions, type DeltaToMarkdownOptions, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, Registry, type SanitizeOptions, type TableBlockData, type TableColAlignType, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, preloadRemark, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
package/dist/index.d.ts
CHANGED
|
@@ -1039,6 +1039,27 @@ declare const formulaFormat: Format<string>;
|
|
|
1039
1039
|
*/
|
|
1040
1040
|
declare const imageFormat: Format<string>;
|
|
1041
1041
|
|
|
1042
|
+
/**
|
|
1043
|
+
* Soft Line Break embed format
|
|
1044
|
+
*
|
|
1045
|
+
* Represents a "Shift+Enter" style line break that does NOT split the
|
|
1046
|
+
* containing block (paragraph, list item, table cell, etc.). This is the
|
|
1047
|
+
* Delta-level analogue of HTML `<br>` used as an inline line break and
|
|
1048
|
+
* of the GFM "hard break" Markdown construct (two trailing spaces + `\n`).
|
|
1049
|
+
*
|
|
1050
|
+
* Delta: `{ insert: { softBreak: true } }`
|
|
1051
|
+
* HTML: `<br data-scrider-embed>` (with the explicit marker so that
|
|
1052
|
+
* round-trip parsing can distinguish a soft break from the
|
|
1053
|
+
* placeholder `<br>` that appears inside an empty paragraph)
|
|
1054
|
+
* Markdown: ` \n` (default GFM hard break) or inline `<br>` (configurable
|
|
1055
|
+
* via `softBreakStyle` option on `deltaToMarkdown`)
|
|
1056
|
+
*
|
|
1057
|
+
* Value is always `true` — the embed has no additional data.
|
|
1058
|
+
*
|
|
1059
|
+
* @see {@link https://github.github.com/gfm/#hard-line-breaks GFM hard line break}
|
|
1060
|
+
*/
|
|
1061
|
+
declare const softBreakFormat: Format<boolean>;
|
|
1062
|
+
|
|
1042
1063
|
/**
|
|
1043
1064
|
* Video embed format
|
|
1044
1065
|
*
|
|
@@ -1557,6 +1578,22 @@ interface DeltaToMarkdownOptions {
|
|
|
1557
1578
|
* `render()` is used as HTML fallback in Markdown.
|
|
1558
1579
|
*/
|
|
1559
1580
|
registry?: Registry;
|
|
1581
|
+
/**
|
|
1582
|
+
* Rendering style for `{ softBreak: true }` embeds (Phase 7 Part 0).
|
|
1583
|
+
*
|
|
1584
|
+
* - `'spaces'` (default): GFM-canonical hard break — two trailing spaces
|
|
1585
|
+
* followed by `\n` (`" \n"`). Round-trips losslessly through remark.
|
|
1586
|
+
* - `'html'`: inline `<br>` tag. Slightly more visible in source view
|
|
1587
|
+
* and immune to editor whitespace trimming. Recommended for the
|
|
1588
|
+
* LFM (LLM-Flavored Markdown) flavour exposed by the editor's
|
|
1589
|
+
* "source" toggle.
|
|
1590
|
+
*
|
|
1591
|
+
* Does not affect how soft breaks are rendered inside table cells —
|
|
1592
|
+
* those always use inline `<br>` because GFM tables forbid raw `\n`.
|
|
1593
|
+
*
|
|
1594
|
+
* @default 'spaces'
|
|
1595
|
+
*/
|
|
1596
|
+
softBreakStyle?: 'spaces' | 'html';
|
|
1560
1597
|
/**
|
|
1561
1598
|
* Strip trailing newlines from the final output.
|
|
1562
1599
|
*
|
|
@@ -1779,4 +1816,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1779
1816
|
*/
|
|
1780
1817
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1781
1818
|
|
|
1782
|
-
export { ALERT_TYPES, type AlertBlockData, type AlertType, type AlignType, BOX_FLOAT_VALUES, BOX_OVERFLOW_VALUES, type BlockContext, type BlockHandler, BlockHandlerRegistry, type BlockRenderOptions, type BoxBlockData, type BoxFloat, type BoxOpAttributes, type BoxOverflow, BrowserDOMAdapter, type CellAlign, type CellData, type ColumnsBlockData, type DOMAdapter, type DOMDocument, type DOMDocumentFragment, type DOMElement, type DOMNode, type DOMNodeList, type DeltaToHtmlOptions, type DeltaToMarkdownOptions, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, Registry, type SanitizeOptions, type TableBlockData, type TableColAlignType, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, preloadRemark, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
|
1819
|
+
export { ALERT_TYPES, type AlertBlockData, type AlertType, type AlignType, BOX_FLOAT_VALUES, BOX_OVERFLOW_VALUES, type BlockContext, type BlockHandler, BlockHandlerRegistry, type BlockRenderOptions, type BoxBlockData, type BoxFloat, type BoxOpAttributes, type BoxOverflow, BrowserDOMAdapter, type CellAlign, type CellData, type ColumnsBlockData, type DOMAdapter, type DOMDocument, type DOMDocumentFragment, type DOMElement, type DOMNode, type DOMNodeList, type DeltaToHtmlOptions, type DeltaToMarkdownOptions, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, Registry, type SanitizeOptions, type TableBlockData, type TableColAlignType, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, preloadRemark, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
package/dist/index.js
CHANGED
|
@@ -1915,7 +1915,13 @@ var EMBED_RENDERERS = {
|
|
|
1915
1915
|
const id = typeof value === "string" ? value : String(value);
|
|
1916
1916
|
return `<sup class="footnote-ref"><a href="#fn-${escapeHtml(id)}" id="fnref-${escapeHtml(id)}">[${escapeHtml(id)}]</a></sup>`;
|
|
1917
1917
|
},
|
|
1918
|
-
divider: () => "<hr>"
|
|
1918
|
+
divider: () => "<hr>",
|
|
1919
|
+
// Soft line break (Shift+Enter equivalent). Emitted with an explicit
|
|
1920
|
+
// `data-scrider-embed` marker so that html-to-delta can distinguish this
|
|
1921
|
+
// embed from the placeholder `<br>` that appears inside an empty
|
|
1922
|
+
// paragraph (`<p><br></p>`) without relying solely on positional
|
|
1923
|
+
// heuristics. See `soft-break.ts` for the format definition.
|
|
1924
|
+
softBreak: () => "<br data-scrider-embed>"
|
|
1919
1925
|
};
|
|
1920
1926
|
var TAG_TO_INLINE_FORMAT = {
|
|
1921
1927
|
strong: { format: "bold", value: true },
|
|
@@ -2153,6 +2159,33 @@ var imageFormat = {
|
|
|
2153
2159
|
}
|
|
2154
2160
|
};
|
|
2155
2161
|
|
|
2162
|
+
// src/schema/formats/embed/soft-break.ts
|
|
2163
|
+
var softBreakFormat = {
|
|
2164
|
+
name: "softBreak",
|
|
2165
|
+
scope: "embed",
|
|
2166
|
+
normalize(value) {
|
|
2167
|
+
return !!value;
|
|
2168
|
+
},
|
|
2169
|
+
validate(value) {
|
|
2170
|
+
return value === true;
|
|
2171
|
+
},
|
|
2172
|
+
render() {
|
|
2173
|
+
return "<br data-scrider-embed>";
|
|
2174
|
+
},
|
|
2175
|
+
match(element) {
|
|
2176
|
+
if (element.tagName.toLowerCase() !== "br") return null;
|
|
2177
|
+
if (!element.hasAttribute("data-scrider-embed")) return null;
|
|
2178
|
+
return { value: true };
|
|
2179
|
+
}
|
|
2180
|
+
// NB: Markdown rendering is intentionally NOT implemented on the format
|
|
2181
|
+
// itself. The choice between `" \n"` (GFM spaces) and inline `<br>`
|
|
2182
|
+
// depends on the caller-provided `softBreakStyle` option on
|
|
2183
|
+
// `deltaToMarkdown`, so the converter handles it as a built-in special
|
|
2184
|
+
// case instead of going through `Format.toMarkdown`. The Markdown side
|
|
2185
|
+
// of the round-trip is symmetric: `markdownToDelta` recognises both
|
|
2186
|
+
// `break` AST nodes and inline `<br>` HTML and emits this embed.
|
|
2187
|
+
};
|
|
2188
|
+
|
|
2156
2189
|
// src/schema/formats/embed/video.ts
|
|
2157
2190
|
var videoFormat = {
|
|
2158
2191
|
name: "video",
|
|
@@ -2255,6 +2288,7 @@ var defaultEmbedFormats = [
|
|
|
2255
2288
|
videoFormat,
|
|
2256
2289
|
formulaFormat,
|
|
2257
2290
|
dividerFormat,
|
|
2291
|
+
softBreakFormat,
|
|
2258
2292
|
blockFormat,
|
|
2259
2293
|
footnoteRefFormat
|
|
2260
2294
|
];
|
|
@@ -3085,7 +3119,12 @@ function htmlToDelta(html, options = {}) {
|
|
|
3085
3119
|
return;
|
|
3086
3120
|
}
|
|
3087
3121
|
if (tagName === "br") {
|
|
3088
|
-
|
|
3122
|
+
const hasMarker = node.hasAttribute("data-scrider-embed");
|
|
3123
|
+
if (hasMarker || hasMeaningfulPrevSibling(node)) {
|
|
3124
|
+
context.pushEmbed({ softBreak: true });
|
|
3125
|
+
} else {
|
|
3126
|
+
context.pushNewline();
|
|
3127
|
+
}
|
|
3089
3128
|
return;
|
|
3090
3129
|
}
|
|
3091
3130
|
processChildren(node);
|
|
@@ -3480,7 +3519,7 @@ function htmlToDelta(html, options = {}) {
|
|
|
3480
3519
|
}
|
|
3481
3520
|
const children2 = element.childNodes;
|
|
3482
3521
|
const firstChild = children2[0];
|
|
3483
|
-
const isBrOnlyParagraph = children2.length === 1 && firstChild !== void 0 && isElement(firstChild) && firstChild.tagName.toLowerCase() === "br";
|
|
3522
|
+
const isBrOnlyParagraph = children2.length === 1 && firstChild !== void 0 && isElement(firstChild) && firstChild.tagName.toLowerCase() === "br" && !firstChild.hasAttribute("data-scrider-embed");
|
|
3484
3523
|
if (!isBrOnlyParagraph) {
|
|
3485
3524
|
processChildren(element);
|
|
3486
3525
|
}
|
|
@@ -3519,6 +3558,23 @@ function normalizeText(text, pendingText, atLineStart) {
|
|
|
3519
3558
|
}
|
|
3520
3559
|
return text;
|
|
3521
3560
|
}
|
|
3561
|
+
function hasMeaningfulPrevSibling(brNode) {
|
|
3562
|
+
const parent = brNode.parentNode;
|
|
3563
|
+
if (!parent) return false;
|
|
3564
|
+
const children = parent.childNodes;
|
|
3565
|
+
for (let i = 0; i < children.length; i++) {
|
|
3566
|
+
const child = children[i];
|
|
3567
|
+
if (!child) continue;
|
|
3568
|
+
if (child === brNode) return false;
|
|
3569
|
+
if (child.nodeType === NODE_TYPE.TEXT_NODE) {
|
|
3570
|
+
const text = child.textContent ?? "";
|
|
3571
|
+
if (text.trim().length > 0) return true;
|
|
3572
|
+
} else if (isElement(child)) {
|
|
3573
|
+
return true;
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
return false;
|
|
3577
|
+
}
|
|
3522
3578
|
function findTagHandler(handlers, element, tagName) {
|
|
3523
3579
|
const className = element.getAttribute("class");
|
|
3524
3580
|
if (className) {
|
|
@@ -3655,6 +3711,7 @@ function deltaToMarkdown(delta, options = {}) {
|
|
|
3655
3711
|
blockHandlers,
|
|
3656
3712
|
prettyHtml = false,
|
|
3657
3713
|
registry,
|
|
3714
|
+
softBreakStyle = "spaces",
|
|
3658
3715
|
trimTrailingNewlines = false
|
|
3659
3716
|
} = options;
|
|
3660
3717
|
const useLatexDelimiters = mathSyntax === "latex";
|
|
@@ -3671,7 +3728,9 @@ function deltaToMarkdown(delta, options = {}) {
|
|
|
3671
3728
|
const isBlockquote = !!attrs.blockquote;
|
|
3672
3729
|
if (typeof attrs["table-row"] === "number" && typeof attrs["table-col"] === "number") {
|
|
3673
3730
|
const tableLines = collectTableLines2(lines, i);
|
|
3674
|
-
result.push(
|
|
3731
|
+
result.push(
|
|
3732
|
+
renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
|
|
3733
|
+
);
|
|
3675
3734
|
result.push("");
|
|
3676
3735
|
i += tableLines.length - 1;
|
|
3677
3736
|
lastListType = null;
|
|
@@ -3687,7 +3746,16 @@ function deltaToMarkdown(delta, options = {}) {
|
|
|
3687
3746
|
const codeLines = collectCodeBlock(lines, i);
|
|
3688
3747
|
const language = getCodeBlockLanguage2(attrs);
|
|
3689
3748
|
const code = codeLines.map(
|
|
3690
|
-
(l) => renderLineContent2(
|
|
3749
|
+
(l) => renderLineContent2(
|
|
3750
|
+
l.ops,
|
|
3751
|
+
embedRenderers,
|
|
3752
|
+
true,
|
|
3753
|
+
false,
|
|
3754
|
+
blockHandlers,
|
|
3755
|
+
false,
|
|
3756
|
+
registry,
|
|
3757
|
+
softBreakStyle
|
|
3758
|
+
)
|
|
3691
3759
|
).join("\n");
|
|
3692
3760
|
if (language === "math") {
|
|
3693
3761
|
if (mathBlock === false) {
|
|
@@ -3737,7 +3805,8 @@ ${code}
|
|
|
3737
3805
|
useLatexDelimiters,
|
|
3738
3806
|
blockHandlers,
|
|
3739
3807
|
prettyHtml,
|
|
3740
|
-
registry
|
|
3808
|
+
registry,
|
|
3809
|
+
softBreakStyle
|
|
3741
3810
|
);
|
|
3742
3811
|
if (!content && !hasBlockFormat(attrs)) {
|
|
3743
3812
|
result.push(preserveEmptyLines ? "<br>" : "");
|
|
@@ -3839,7 +3908,7 @@ function collectTableLines2(lines, startIndex) {
|
|
|
3839
3908
|
}
|
|
3840
3909
|
return result;
|
|
3841
3910
|
}
|
|
3842
|
-
function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = false, registry) {
|
|
3911
|
+
function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces") {
|
|
3843
3912
|
const rows = /* @__PURE__ */ new Map();
|
|
3844
3913
|
for (const line of tableLines) {
|
|
3845
3914
|
const attrs = line.attributes;
|
|
@@ -3876,7 +3945,9 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
|
|
|
3876
3945
|
const mdLines = [];
|
|
3877
3946
|
if (headerRows.length > 0) {
|
|
3878
3947
|
for (const [, row] of headerRows) {
|
|
3879
|
-
mdLines.push(
|
|
3948
|
+
mdLines.push(
|
|
3949
|
+
renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
|
|
3950
|
+
);
|
|
3880
3951
|
}
|
|
3881
3952
|
mdLines.push(renderMdSeparator(maxCol, colAligns));
|
|
3882
3953
|
} else {
|
|
@@ -3884,15 +3955,19 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
|
|
|
3884
3955
|
for (let col = 0; col <= maxCol; col++) {
|
|
3885
3956
|
emptyRow.set(col, { ops: [] });
|
|
3886
3957
|
}
|
|
3887
|
-
mdLines.push(
|
|
3958
|
+
mdLines.push(
|
|
3959
|
+
renderMdRow(emptyRow, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
|
|
3960
|
+
);
|
|
3888
3961
|
mdLines.push(renderMdSeparator(maxCol, colAligns));
|
|
3889
3962
|
}
|
|
3890
3963
|
for (const [, row] of bodyRows) {
|
|
3891
|
-
mdLines.push(
|
|
3964
|
+
mdLines.push(
|
|
3965
|
+
renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
|
|
3966
|
+
);
|
|
3892
3967
|
}
|
|
3893
3968
|
return mdLines.join("\n");
|
|
3894
3969
|
}
|
|
3895
|
-
function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry) {
|
|
3970
|
+
function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces") {
|
|
3896
3971
|
const parts = [];
|
|
3897
3972
|
for (let col = 0; col <= maxCol; col++) {
|
|
3898
3973
|
const cell = cells.get(col);
|
|
@@ -3903,7 +3978,10 @@ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false,
|
|
|
3903
3978
|
useLatexDelimiters,
|
|
3904
3979
|
void 0,
|
|
3905
3980
|
false,
|
|
3906
|
-
registry
|
|
3981
|
+
registry,
|
|
3982
|
+
softBreakStyle,
|
|
3983
|
+
true
|
|
3984
|
+
// inTableCell — softBreak must use <br>, never " \n"
|
|
3907
3985
|
) : "";
|
|
3908
3986
|
parts.push(content.replace(/\|/g, "\\|"));
|
|
3909
3987
|
}
|
|
@@ -3932,7 +4010,7 @@ function getCodeBlockLanguage2(attributes) {
|
|
|
3932
4010
|
}
|
|
3933
4011
|
return void 0;
|
|
3934
4012
|
}
|
|
3935
|
-
function renderLineContent2(ops, embedRenderers, inCodeBlock, useLatexDelimiters = false, blockHandlers, prettyHtml = false, registry) {
|
|
4013
|
+
function renderLineContent2(ops, embedRenderers, inCodeBlock, useLatexDelimiters = false, blockHandlers, prettyHtml = false, registry, softBreakStyle = "spaces", inTableCell = false) {
|
|
3936
4014
|
let result = "";
|
|
3937
4015
|
for (const op of ops) {
|
|
3938
4016
|
const attrs = op.attributes;
|
|
@@ -3952,7 +4030,9 @@ function renderLineContent2(ops, embedRenderers, inCodeBlock, useLatexDelimiters
|
|
|
3952
4030
|
useLatexDelimiters,
|
|
3953
4031
|
blockHandlers,
|
|
3954
4032
|
prettyHtml,
|
|
3955
|
-
registry
|
|
4033
|
+
registry,
|
|
4034
|
+
softBreakStyle,
|
|
4035
|
+
inTableCell
|
|
3956
4036
|
);
|
|
3957
4037
|
}
|
|
3958
4038
|
}
|
|
@@ -3986,13 +4066,17 @@ function renderInlineText2(text, attributes) {
|
|
|
3986
4066
|
}
|
|
3987
4067
|
return result;
|
|
3988
4068
|
}
|
|
3989
|
-
function renderEmbed2(embed, attributes, customRenderers, useLatexDelimiters = false, blockHandlers, prettyHtml = false, registry) {
|
|
4069
|
+
function renderEmbed2(embed, attributes, customRenderers, useLatexDelimiters = false, blockHandlers, prettyHtml = false, registry, softBreakStyle = "spaces", inTableCell = false) {
|
|
3990
4070
|
const entries = Object.entries(embed);
|
|
3991
4071
|
if (entries.length === 0) return "";
|
|
3992
4072
|
const firstEntry = entries[0];
|
|
3993
4073
|
if (!firstEntry) return "";
|
|
3994
4074
|
const embedType = firstEntry[0];
|
|
3995
4075
|
const embedValue = firstEntry[1];
|
|
4076
|
+
if (embedType === "softBreak") {
|
|
4077
|
+
if (inTableCell) return "<br>";
|
|
4078
|
+
return softBreakStyle === "html" ? "<br>" : " \n";
|
|
4079
|
+
}
|
|
3996
4080
|
if (embedType === "block" && blockHandlers) {
|
|
3997
4081
|
const blockData = embedValue;
|
|
3998
4082
|
if (blockData && typeof blockData.type === "string") {
|
|
@@ -4481,7 +4565,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4481
4565
|
footnoteDefinitions.set(node.identifier ?? "", node);
|
|
4482
4566
|
break;
|
|
4483
4567
|
case "break":
|
|
4484
|
-
context.
|
|
4568
|
+
context.pushEmbed({ softBreak: true });
|
|
4485
4569
|
break;
|
|
4486
4570
|
case "html": {
|
|
4487
4571
|
const htmlContent = node.value ?? "";
|
|
@@ -4787,8 +4871,8 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4787
4871
|
context.pushNewline();
|
|
4788
4872
|
return;
|
|
4789
4873
|
}
|
|
4790
|
-
if (/^<br\
|
|
4791
|
-
context.
|
|
4874
|
+
if (/^<br\b[^>]*\/?>$/i.test(html)) {
|
|
4875
|
+
context.pushEmbed({ softBreak: true });
|
|
4792
4876
|
return;
|
|
4793
4877
|
}
|
|
4794
4878
|
}
|
|
@@ -4938,6 +5022,7 @@ export {
|
|
|
4938
5022
|
sizeFormat,
|
|
4939
5023
|
slugify,
|
|
4940
5024
|
slugifyWithDedup,
|
|
5025
|
+
softBreakFormat,
|
|
4941
5026
|
strikeFormat,
|
|
4942
5027
|
subscriptFormat,
|
|
4943
5028
|
superscriptFormat,
|