@scrider/formatter 1.4.4 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +211 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +209 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -999,6 +999,25 @@ declare const tableColAlignFormat: Format<TableColAlignType>;
|
|
|
999
999
|
*/
|
|
1000
1000
|
declare const blockFormat: Format<Record<string, unknown>>;
|
|
1001
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* Code Widget embed format (Phase 8 Part 3.5)
|
|
1004
|
+
*
|
|
1005
|
+
* Delta: { insert: { codeWidget: "https://codesandbox.io/s/abc123" } }
|
|
1006
|
+
*
|
|
1007
|
+
* Value is a URL to an interactive code playground (StackBlitz, CodeSandbox,
|
|
1008
|
+
* Replit, CodePen, JSFiddle). Rendered as an <iframe> carrying a
|
|
1009
|
+
* `data-code-widget` marker so it can be told apart from a plain video iframe
|
|
1010
|
+
* during HTML → Delta (see videoFormat.match guard).
|
|
1011
|
+
*
|
|
1012
|
+
* Markdown: 
|
|
1013
|
+
* HTML: <iframe data-code-widget src="<embed-url>" frameborder="0" allowfullscreen>
|
|
1014
|
+
*
|
|
1015
|
+
* The src is run through `toCodeWidgetEmbedUrl` at render time, which is
|
|
1016
|
+
* idempotent, so resize/float attributes and the Delta ↔ HTML round-trip stay
|
|
1017
|
+
* stable regardless of whether the stored value is the user URL or embed URL.
|
|
1018
|
+
*/
|
|
1019
|
+
declare const codeWidgetFormat: Format<string>;
|
|
1020
|
+
|
|
1002
1021
|
/**
|
|
1003
1022
|
* Divider (Horizontal Rule) embed format
|
|
1004
1023
|
*
|
|
@@ -1580,6 +1599,26 @@ declare function escapeHtml(text: string): string;
|
|
|
1580
1599
|
* Unescape HTML entities
|
|
1581
1600
|
*/
|
|
1582
1601
|
declare function unescapeHtml(text: string): string;
|
|
1602
|
+
/**
|
|
1603
|
+
* Convert a code-playground URL to an embeddable iframe URL (Phase 8 Part 3.5).
|
|
1604
|
+
*
|
|
1605
|
+
* Idempotent: a URL that is already in embed form is returned unchanged, so the
|
|
1606
|
+
* Delta → HTML → Delta round-trip is stable regardless of which form is stored.
|
|
1607
|
+
*
|
|
1608
|
+
* Provider | User URL | Embed URL
|
|
1609
|
+
* -------------|----------------------------------|-----------------------------------
|
|
1610
|
+
* StackBlitz | stackblitz.com/edit/{id} | …?embed=1
|
|
1611
|
+
* | stackblitz.com/github/{u}/{r} | …?embed=1
|
|
1612
|
+
* CodeSandbox | codesandbox.io/s/{id} | codesandbox.io/embed/{id}
|
|
1613
|
+
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1614
|
+
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1615
|
+
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1616
|
+
*
|
|
1617
|
+
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1618
|
+
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
|
1619
|
+
* editor layer).
|
|
1620
|
+
*/
|
|
1621
|
+
declare function toCodeWidgetEmbedUrl(url: string): string;
|
|
1583
1622
|
|
|
1584
1623
|
/**
|
|
1585
1624
|
* GitHub-compatible slugify for heading anchor links.
|
|
@@ -1944,4 +1983,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1944
1983
|
*/
|
|
1945
1984
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1946
1985
|
|
|
1947
|
-
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 DocumentPresentation, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, LINE_HEIGHT_BLOCK_TAGS, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, PARAGRAPH_SPACING_BLOCK_TAGS, Registry, type ResolvedDocumentPresentation, type ResolvedTablePresentation, SCRIDER_LINE_HEIGHT_KEY, SCRIDER_MARGIN_AFTER_KEY, SCRIDER_MARGIN_BEFORE_KEY, type SanitizeOptions, type TableBlockData, type TableCellAlign, type TableColAlignType, type TablePresentation, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockLineHeightStyleParts, blockMarginAfterStyleParts, blockMarginBeforeStyleParts, blockParagraphMarginStyleParts, blockPresentationStyleParts, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, documentPresentationStyleParts, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, isZebraBodyRow, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, parseScriderLineHeightMultiplier, parseScriderMarginAfterEm, parseScriderMarginBeforeEm, parseScriderMarginEm, preloadRemark, resolveDocumentPresentation, resolveTablePresentation, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
|
1986
|
+
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 DocumentPresentation, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, LINE_HEIGHT_BLOCK_TAGS, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, PARAGRAPH_SPACING_BLOCK_TAGS, Registry, type ResolvedDocumentPresentation, type ResolvedTablePresentation, SCRIDER_LINE_HEIGHT_KEY, SCRIDER_MARGIN_AFTER_KEY, SCRIDER_MARGIN_BEFORE_KEY, type SanitizeOptions, type TableBlockData, type TableCellAlign, type TableColAlignType, type TablePresentation, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockLineHeightStyleParts, blockMarginAfterStyleParts, blockMarginBeforeStyleParts, blockParagraphMarginStyleParts, blockPresentationStyleParts, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, codeWidgetFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, documentPresentationStyleParts, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, isZebraBodyRow, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, parseScriderLineHeightMultiplier, parseScriderMarginAfterEm, parseScriderMarginBeforeEm, parseScriderMarginEm, preloadRemark, resolveDocumentPresentation, resolveTablePresentation, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toCodeWidgetEmbedUrl, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
package/dist/index.d.ts
CHANGED
|
@@ -999,6 +999,25 @@ declare const tableColAlignFormat: Format<TableColAlignType>;
|
|
|
999
999
|
*/
|
|
1000
1000
|
declare const blockFormat: Format<Record<string, unknown>>;
|
|
1001
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* Code Widget embed format (Phase 8 Part 3.5)
|
|
1004
|
+
*
|
|
1005
|
+
* Delta: { insert: { codeWidget: "https://codesandbox.io/s/abc123" } }
|
|
1006
|
+
*
|
|
1007
|
+
* Value is a URL to an interactive code playground (StackBlitz, CodeSandbox,
|
|
1008
|
+
* Replit, CodePen, JSFiddle). Rendered as an <iframe> carrying a
|
|
1009
|
+
* `data-code-widget` marker so it can be told apart from a plain video iframe
|
|
1010
|
+
* during HTML → Delta (see videoFormat.match guard).
|
|
1011
|
+
*
|
|
1012
|
+
* Markdown: 
|
|
1013
|
+
* HTML: <iframe data-code-widget src="<embed-url>" frameborder="0" allowfullscreen>
|
|
1014
|
+
*
|
|
1015
|
+
* The src is run through `toCodeWidgetEmbedUrl` at render time, which is
|
|
1016
|
+
* idempotent, so resize/float attributes and the Delta ↔ HTML round-trip stay
|
|
1017
|
+
* stable regardless of whether the stored value is the user URL or embed URL.
|
|
1018
|
+
*/
|
|
1019
|
+
declare const codeWidgetFormat: Format<string>;
|
|
1020
|
+
|
|
1002
1021
|
/**
|
|
1003
1022
|
* Divider (Horizontal Rule) embed format
|
|
1004
1023
|
*
|
|
@@ -1580,6 +1599,26 @@ declare function escapeHtml(text: string): string;
|
|
|
1580
1599
|
* Unescape HTML entities
|
|
1581
1600
|
*/
|
|
1582
1601
|
declare function unescapeHtml(text: string): string;
|
|
1602
|
+
/**
|
|
1603
|
+
* Convert a code-playground URL to an embeddable iframe URL (Phase 8 Part 3.5).
|
|
1604
|
+
*
|
|
1605
|
+
* Idempotent: a URL that is already in embed form is returned unchanged, so the
|
|
1606
|
+
* Delta → HTML → Delta round-trip is stable regardless of which form is stored.
|
|
1607
|
+
*
|
|
1608
|
+
* Provider | User URL | Embed URL
|
|
1609
|
+
* -------------|----------------------------------|-----------------------------------
|
|
1610
|
+
* StackBlitz | stackblitz.com/edit/{id} | …?embed=1
|
|
1611
|
+
* | stackblitz.com/github/{u}/{r} | …?embed=1
|
|
1612
|
+
* CodeSandbox | codesandbox.io/s/{id} | codesandbox.io/embed/{id}
|
|
1613
|
+
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1614
|
+
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1615
|
+
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1616
|
+
*
|
|
1617
|
+
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1618
|
+
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
|
1619
|
+
* editor layer).
|
|
1620
|
+
*/
|
|
1621
|
+
declare function toCodeWidgetEmbedUrl(url: string): string;
|
|
1583
1622
|
|
|
1584
1623
|
/**
|
|
1585
1624
|
* GitHub-compatible slugify for heading anchor links.
|
|
@@ -1944,4 +1983,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1944
1983
|
*/
|
|
1945
1984
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1946
1985
|
|
|
1947
|
-
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 DocumentPresentation, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, LINE_HEIGHT_BLOCK_TAGS, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, PARAGRAPH_SPACING_BLOCK_TAGS, Registry, type ResolvedDocumentPresentation, type ResolvedTablePresentation, SCRIDER_LINE_HEIGHT_KEY, SCRIDER_MARGIN_AFTER_KEY, SCRIDER_MARGIN_BEFORE_KEY, type SanitizeOptions, type TableBlockData, type TableCellAlign, type TableColAlignType, type TablePresentation, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockLineHeightStyleParts, blockMarginAfterStyleParts, blockMarginBeforeStyleParts, blockParagraphMarginStyleParts, blockPresentationStyleParts, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, documentPresentationStyleParts, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, isZebraBodyRow, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, parseScriderLineHeightMultiplier, parseScriderMarginAfterEm, parseScriderMarginBeforeEm, parseScriderMarginEm, preloadRemark, resolveDocumentPresentation, resolveTablePresentation, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
|
1986
|
+
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 DocumentPresentation, type FootnotesBlockData, type Format, type FormatDefinition, type FormatMatchResult, type FormatScope, type HtmlToDeltaOptions, LINE_HEIGHT_BLOCK_TAGS, type ListType, type MarkdownToDeltaOptions, NODE_TYPE, NodeDOMAdapter, PARAGRAPH_SPACING_BLOCK_TAGS, Registry, type ResolvedDocumentPresentation, type ResolvedTablePresentation, SCRIDER_LINE_HEIGHT_KEY, SCRIDER_MARGIN_AFTER_KEY, SCRIDER_MARGIN_BEFORE_KEY, type SanitizeOptions, type TableBlockData, type TableCellAlign, type TableColAlignType, type TablePresentation, type TableRegion, alertBlockHandler, alignFormat, backgroundFormat, blockFormat, blockLineHeightStyleParts, blockMarginAfterStyleParts, blockMarginBeforeStyleParts, blockParagraphMarginStyleParts, blockPresentationStyleParts, blockquoteFormat, boldFormat, boxBlockHandler, browserAdapter, cloneDelta, codeBlockFormat, codeFormat, codeWidgetFormat, colorFormat, columnsBlockHandler, createDefaultBlockHandlers, createDefaultRegistry, defaultBlockFormats, defaultEmbedFormats, defaultFormats, defaultInlineFormats, deltaToHtml, deltaToMarkdown, dividerFormat, documentPresentationStyleParts, escapeHtml, extractBoxOpAttributes, extractTableRegion, fontFormat, footnoteRefFormat, footnotesBlockHandler, formulaFormat, getAdapter, getNamedColors, headerFormat, headerIdFormat, htmlToDelta, imageFormat, indentFormat, isAdapterAvailable, isElement, isRemarkAvailable, isTableNewlineOp, isTextNode, isValidColor, isValidHexColor, isZebraBodyRow, italicFormat, kbdFormat, linkFormat, listFormat, markFormat, markdownToDelta, markdownToDeltaSync, nodeAdapter, normalizeDelta, parseScriderLineHeightMultiplier, parseScriderMarginAfterEm, parseScriderMarginBeforeEm, parseScriderMarginEm, preloadRemark, resolveDocumentPresentation, resolveTablePresentation, sanitizeDelta, sizeFormat, slugify, slugifyWithDedup, softBreakFormat, strikeFormat, subscriptFormat, superscriptFormat, tableBlockHandler, tableColAlignFormat, tableColFormat, tableHeaderFormat, tableRowFormat, toCodeWidgetEmbedUrl, toHexColor, underlineFormat, unescapeHtml, validateDelta, videoFormat };
|
package/dist/index.js
CHANGED
|
@@ -1897,6 +1897,25 @@ var EMBED_RENDERERS = {
|
|
|
1897
1897
|
}
|
|
1898
1898
|
return `<video src="${escapeHtml(src)}" controls${float}${style}></video>`;
|
|
1899
1899
|
},
|
|
1900
|
+
codeWidget: (value, attrs) => {
|
|
1901
|
+
const src = typeof value === "string" ? value : "";
|
|
1902
|
+
const floatVal = attrs?.float;
|
|
1903
|
+
const widthVal = attrs?.width;
|
|
1904
|
+
const heightVal = attrs?.height;
|
|
1905
|
+
const float = floatVal != null && typeof floatVal === "string" && floatVal !== "none" ? ` data-float="${escapeHtml(floatVal)}"` : "";
|
|
1906
|
+
const styles = [];
|
|
1907
|
+
if (widthVal != null && (typeof widthVal === "string" || typeof widthVal === "number")) {
|
|
1908
|
+
const w = String(widthVal);
|
|
1909
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
1910
|
+
}
|
|
1911
|
+
if (heightVal != null && (typeof heightVal === "string" || typeof heightVal === "number")) {
|
|
1912
|
+
const h = String(heightVal);
|
|
1913
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
1914
|
+
}
|
|
1915
|
+
const style = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
1916
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
1917
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${float}${style}></iframe>`;
|
|
1918
|
+
},
|
|
1900
1919
|
formula: (value) => {
|
|
1901
1920
|
const latex = typeof value === "string" ? value : "";
|
|
1902
1921
|
return `<span class="formula" data-formula="${escapeHtml(latex)}">${escapeHtml(latex)}</span>`;
|
|
@@ -1990,6 +2009,124 @@ function fromVideoEmbedUrl(embedUrl) {
|
|
|
1990
2009
|
}
|
|
1991
2010
|
return embedUrl;
|
|
1992
2011
|
}
|
|
2012
|
+
function splitUrl(url) {
|
|
2013
|
+
let rest = url;
|
|
2014
|
+
let hash = "";
|
|
2015
|
+
const hashIdx = rest.indexOf("#");
|
|
2016
|
+
if (hashIdx >= 0) {
|
|
2017
|
+
hash = rest.slice(hashIdx);
|
|
2018
|
+
rest = rest.slice(0, hashIdx);
|
|
2019
|
+
}
|
|
2020
|
+
let query = "";
|
|
2021
|
+
const qIdx = rest.indexOf("?");
|
|
2022
|
+
if (qIdx >= 0) {
|
|
2023
|
+
query = rest.slice(qIdx);
|
|
2024
|
+
rest = rest.slice(0, qIdx);
|
|
2025
|
+
}
|
|
2026
|
+
return { base: rest, query, hash };
|
|
2027
|
+
}
|
|
2028
|
+
function hasQueryParam(url, key) {
|
|
2029
|
+
const { query } = splitUrl(url);
|
|
2030
|
+
return new RegExp(`[?&]${key}=`, "i").test(query);
|
|
2031
|
+
}
|
|
2032
|
+
function appendQueryParam(url, key, value) {
|
|
2033
|
+
const { base, query, hash } = splitUrl(url);
|
|
2034
|
+
const next = query ? `${query}&${key}=${value}` : `?${key}=${value}`;
|
|
2035
|
+
return `${base}${next}${hash}`;
|
|
2036
|
+
}
|
|
2037
|
+
function toCodeWidgetEmbedUrl(url) {
|
|
2038
|
+
const u = typeof url === "string" ? url.trim() : "";
|
|
2039
|
+
if (!u) return "";
|
|
2040
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*stackblitz\.com\//i.test(u)) {
|
|
2041
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "1");
|
|
2042
|
+
}
|
|
2043
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codesandbox\.io\//i.test(u)) {
|
|
2044
|
+
if (/codesandbox\.io\/embed\//i.test(u)) return u;
|
|
2045
|
+
return u.replace(/codesandbox\.io\/s\//i, "codesandbox.io/embed/");
|
|
2046
|
+
}
|
|
2047
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*replit\.com\//i.test(u)) {
|
|
2048
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "true");
|
|
2049
|
+
}
|
|
2050
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codepen\.io\//i.test(u)) {
|
|
2051
|
+
if (/codepen\.io\/[^/]+\/embed\//i.test(u)) return u;
|
|
2052
|
+
return u.replace(/(codepen\.io\/[^/]+)\/pen\//i, "$1/embed/");
|
|
2053
|
+
}
|
|
2054
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*jsfiddle\.net\//i.test(u)) {
|
|
2055
|
+
const { base, query, hash } = splitUrl(u);
|
|
2056
|
+
if (/\/embedded(?:\/|$)/i.test(base)) return u;
|
|
2057
|
+
const trimmed = base.replace(/\/+$/, "");
|
|
2058
|
+
return `${trimmed}/embedded/${query}${hash}`;
|
|
2059
|
+
}
|
|
2060
|
+
return u;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
// src/schema/formats/embed/codeWidget.ts
|
|
2064
|
+
var codeWidgetFormat = {
|
|
2065
|
+
name: "codeWidget",
|
|
2066
|
+
scope: "embed",
|
|
2067
|
+
normalize(value) {
|
|
2068
|
+
return typeof value === "string" ? value.trim() : value;
|
|
2069
|
+
},
|
|
2070
|
+
validate(value) {
|
|
2071
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2072
|
+
return false;
|
|
2073
|
+
}
|
|
2074
|
+
const trimmed = value.trim();
|
|
2075
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
if (trimmed.startsWith("//")) {
|
|
2079
|
+
return true;
|
|
2080
|
+
}
|
|
2081
|
+
try {
|
|
2082
|
+
const url = new URL(trimmed);
|
|
2083
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2084
|
+
} catch {
|
|
2085
|
+
return false;
|
|
2086
|
+
}
|
|
2087
|
+
},
|
|
2088
|
+
render(value, attributes) {
|
|
2089
|
+
const src = typeof value === "string" ? value : "";
|
|
2090
|
+
const floatVal = attributes?.float;
|
|
2091
|
+
const widthVal = attributes?.width;
|
|
2092
|
+
const heightVal = attributes?.height;
|
|
2093
|
+
const float = floatVal != null && typeof floatVal === "string" && floatVal !== "none" ? ` data-float="${escapeHtml(floatVal)}"` : "";
|
|
2094
|
+
const styles = [];
|
|
2095
|
+
if (widthVal != null && (typeof widthVal === "string" || typeof widthVal === "number")) {
|
|
2096
|
+
const w = String(widthVal);
|
|
2097
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
2098
|
+
}
|
|
2099
|
+
if (heightVal != null && (typeof heightVal === "string" || typeof heightVal === "number")) {
|
|
2100
|
+
const h = String(heightVal);
|
|
2101
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
2102
|
+
}
|
|
2103
|
+
const style = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
2104
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
2105
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${float}${style}></iframe>`;
|
|
2106
|
+
},
|
|
2107
|
+
match(element) {
|
|
2108
|
+
if (element.tagName.toLowerCase() !== "iframe") return null;
|
|
2109
|
+
if (element.getAttribute("data-code-widget") === null) return null;
|
|
2110
|
+
const src = element.getAttribute("src");
|
|
2111
|
+
if (!src) return null;
|
|
2112
|
+
const attrs = {};
|
|
2113
|
+
const float = element.getAttribute("data-float");
|
|
2114
|
+
const styleAttr = element.getAttribute("style") || "";
|
|
2115
|
+
if (float) attrs.float = float;
|
|
2116
|
+
const widthMatch = styleAttr.match(/(?:^|;\s*)width:\s*([^;]+)/);
|
|
2117
|
+
if (widthMatch?.[1]) attrs.width = widthMatch[1].trim().replace(/px$/, "");
|
|
2118
|
+
const heightMatch = styleAttr.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
2119
|
+
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
2120
|
+
if (Object.keys(attrs).length > 0) {
|
|
2121
|
+
return { value: src, attributes: attrs };
|
|
2122
|
+
}
|
|
2123
|
+
return { value: src };
|
|
2124
|
+
},
|
|
2125
|
+
toMarkdown(value) {
|
|
2126
|
+
const src = typeof value === "string" ? value : "";
|
|
2127
|
+
return ``;
|
|
2128
|
+
}
|
|
2129
|
+
};
|
|
1993
2130
|
|
|
1994
2131
|
// src/schema/formats/embed/divider.ts
|
|
1995
2132
|
var dividerFormat = {
|
|
@@ -2234,6 +2371,7 @@ var videoFormat = {
|
|
|
2234
2371
|
return `<video src="${escapeHtml(src)}" controls${float}${style}></video>`;
|
|
2235
2372
|
},
|
|
2236
2373
|
match(element) {
|
|
2374
|
+
if (element.getAttribute("data-code-widget") !== null) return null;
|
|
2237
2375
|
const tagName = element.tagName.toLowerCase();
|
|
2238
2376
|
if (tagName !== "video" && tagName !== "iframe") return null;
|
|
2239
2377
|
const src = element.getAttribute("src");
|
|
@@ -2286,6 +2424,7 @@ var defaultBlockFormats = [
|
|
|
2286
2424
|
var defaultEmbedFormats = [
|
|
2287
2425
|
imageFormat,
|
|
2288
2426
|
videoFormat,
|
|
2427
|
+
codeWidgetFormat,
|
|
2289
2428
|
formulaFormat,
|
|
2290
2429
|
dividerFormat,
|
|
2291
2430
|
softBreakFormat,
|
|
@@ -2732,7 +2871,16 @@ function deltaToHtml(delta, options = {}) {
|
|
|
2732
2871
|
counters = [];
|
|
2733
2872
|
const codeLines = collectCodeBlockLines(lines, i);
|
|
2734
2873
|
const language = getCodeBlockLanguage(line.attributes);
|
|
2735
|
-
|
|
2874
|
+
const codeBlockId = getCodeBlockId(line.attributes);
|
|
2875
|
+
html += renderCodeBlock(
|
|
2876
|
+
codeLines,
|
|
2877
|
+
language,
|
|
2878
|
+
embedRenderers,
|
|
2879
|
+
pretty,
|
|
2880
|
+
blockHandlers,
|
|
2881
|
+
options,
|
|
2882
|
+
codeBlockId
|
|
2883
|
+
);
|
|
2736
2884
|
i += codeLines.length - 1;
|
|
2737
2885
|
continue;
|
|
2738
2886
|
}
|
|
@@ -3003,11 +3151,13 @@ function collectCodeBlockLines(lines, startIndex) {
|
|
|
3003
3151
|
const startLine = lines[startIndex];
|
|
3004
3152
|
if (!startLine) return codeLines;
|
|
3005
3153
|
const startLang = getCodeBlockLanguage(startLine.attributes);
|
|
3154
|
+
const startId = getCodeBlockId(startLine.attributes);
|
|
3006
3155
|
for (let i = startIndex; i < lines.length; i++) {
|
|
3007
3156
|
const line = lines[i];
|
|
3008
3157
|
if (!line || !line.attributes?.["code-block"]) break;
|
|
3009
3158
|
const lang = getCodeBlockLanguage(line.attributes);
|
|
3010
|
-
|
|
3159
|
+
const id = getCodeBlockId(line.attributes);
|
|
3160
|
+
if (i > startIndex && (lang !== startLang || id !== startId)) break;
|
|
3011
3161
|
codeLines.push(line);
|
|
3012
3162
|
}
|
|
3013
3163
|
return codeLines;
|
|
@@ -3020,14 +3170,20 @@ function getCodeBlockLanguage(attributes) {
|
|
|
3020
3170
|
}
|
|
3021
3171
|
return void 0;
|
|
3022
3172
|
}
|
|
3023
|
-
function
|
|
3173
|
+
function getCodeBlockId(attributes) {
|
|
3174
|
+
if (!attributes) return void 0;
|
|
3175
|
+
const id = attributes["code-block-id"];
|
|
3176
|
+
return typeof id === "string" ? id : void 0;
|
|
3177
|
+
}
|
|
3178
|
+
function renderCodeBlock(codeLines, language, embedRenderers, pretty, blockHandlers, options, codeBlockId) {
|
|
3024
3179
|
const lineContents = codeLines.map(
|
|
3025
3180
|
(line) => renderLineContent(line.ops, embedRenderers, blockHandlers, options)
|
|
3026
3181
|
);
|
|
3027
3182
|
const code = lineContents.join("\n");
|
|
3028
3183
|
const langClass = language ? ` class="language-${escapeHtml(language)}"` : "";
|
|
3029
3184
|
const langAttr = language ? ` data-language="${escapeHtml(language)}"` : "";
|
|
3030
|
-
const
|
|
3185
|
+
const idAttr = codeBlockId ? ` data-code-block-id="${escapeHtml(codeBlockId)}"` : "";
|
|
3186
|
+
const html = `<pre${langAttr}${idAttr}><code${langClass}>${code}
|
|
3031
3187
|
</code></pre>`;
|
|
3032
3188
|
return pretty ? html + "\n" : html;
|
|
3033
3189
|
}
|
|
@@ -3241,6 +3397,7 @@ function htmlToDelta(html, options = {}) {
|
|
|
3241
3397
|
let currentBlockAttributes = {};
|
|
3242
3398
|
let pendingText = "";
|
|
3243
3399
|
let atLineStart = true;
|
|
3400
|
+
let codeBlockIdSeq = 0;
|
|
3244
3401
|
const context = {
|
|
3245
3402
|
delta,
|
|
3246
3403
|
get attributes() {
|
|
@@ -3453,6 +3610,8 @@ function htmlToDelta(html, options = {}) {
|
|
|
3453
3610
|
}
|
|
3454
3611
|
const codeBlockValue = language || true;
|
|
3455
3612
|
currentBlockAttributes["code-block"] = codeBlockValue;
|
|
3613
|
+
const existingId = element.getAttribute("data-code-block-id");
|
|
3614
|
+
currentBlockAttributes["code-block-id"] = existingId || `cb-${++codeBlockIdSeq}`;
|
|
3456
3615
|
const sourceElement = codeElement || element;
|
|
3457
3616
|
const rawText = sourceElement.textContent ?? "";
|
|
3458
3617
|
const text = rawText.endsWith("\n") ? rawText.slice(0, -1) : rawText;
|
|
@@ -3608,6 +3767,10 @@ function htmlToDelta(html, options = {}) {
|
|
|
3608
3767
|
const heightMatch = style.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
3609
3768
|
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
3610
3769
|
const embedAttrs = Object.keys(attrs).length > 0 ? attrs : void 0;
|
|
3770
|
+
if (element.getAttribute("data-code-widget") !== null) {
|
|
3771
|
+
context.pushEmbed({ codeWidget: src }, embedAttrs);
|
|
3772
|
+
return;
|
|
3773
|
+
}
|
|
3611
3774
|
context.pushEmbed({ video: fromVideoEmbedUrl(src) }, embedAttrs);
|
|
3612
3775
|
}
|
|
3613
3776
|
function processFootnotesSection(section) {
|
|
@@ -4188,11 +4351,13 @@ function collectCodeBlock(lines, startIndex) {
|
|
|
4188
4351
|
const startLine = lines[startIndex];
|
|
4189
4352
|
if (!startLine) return codeLines;
|
|
4190
4353
|
const startLang = getCodeBlockLanguage2(startLine.attributes);
|
|
4354
|
+
const startId = getCodeBlockId2(startLine.attributes);
|
|
4191
4355
|
for (let i = startIndex; i < lines.length; i++) {
|
|
4192
4356
|
const line = lines[i];
|
|
4193
4357
|
if (!line || !line.attributes["code-block"]) break;
|
|
4194
4358
|
const lang = getCodeBlockLanguage2(line.attributes);
|
|
4195
|
-
|
|
4359
|
+
const id = getCodeBlockId2(line.attributes);
|
|
4360
|
+
if (i > startIndex && (lang !== startLang || id !== startId)) break;
|
|
4196
4361
|
codeLines.push(line);
|
|
4197
4362
|
}
|
|
4198
4363
|
return codeLines;
|
|
@@ -4310,6 +4475,10 @@ function getCodeBlockLanguage2(attributes) {
|
|
|
4310
4475
|
}
|
|
4311
4476
|
return void 0;
|
|
4312
4477
|
}
|
|
4478
|
+
function getCodeBlockId2(attributes) {
|
|
4479
|
+
const id = attributes["code-block-id"];
|
|
4480
|
+
return typeof id === "string" ? id : void 0;
|
|
4481
|
+
}
|
|
4313
4482
|
function renderLineContent2(ops, embedRenderers, inCodeBlock, useLatexDelimiters = false, blockHandlers, prettyHtml = false, registry, softBreakStyle = "spaces", inTableCell = false) {
|
|
4314
4483
|
let result = "";
|
|
4315
4484
|
for (const op of ops) {
|
|
@@ -4459,6 +4628,28 @@ function renderEmbed2(embed, attributes, customRenderers, useLatexDelimiters = f
|
|
|
4459
4628
|
}
|
|
4460
4629
|
return ``;
|
|
4461
4630
|
}
|
|
4631
|
+
if (embedType === "codeWidget") {
|
|
4632
|
+
const src = typeof embedValue === "string" ? embedValue : "";
|
|
4633
|
+
const hasFloat = attributes?.float != null && typeof attributes.float === "string" && attributes.float !== "none";
|
|
4634
|
+
const hasWidth = attributes?.width != null;
|
|
4635
|
+
const hasHeight = attributes?.height != null;
|
|
4636
|
+
if (hasFloat || hasWidth || hasHeight) {
|
|
4637
|
+
const floatAttr = hasFloat ? ` data-float="${escapeHtml(String(attributes.float))}"` : "";
|
|
4638
|
+
const styles = [];
|
|
4639
|
+
if (hasWidth) {
|
|
4640
|
+
const w = typeof attributes.width === "string" || typeof attributes.width === "number" ? String(attributes.width) : "";
|
|
4641
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
4642
|
+
}
|
|
4643
|
+
if (hasHeight) {
|
|
4644
|
+
const h = typeof attributes.height === "string" || typeof attributes.height === "number" ? String(attributes.height) : "";
|
|
4645
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
4646
|
+
}
|
|
4647
|
+
const styleAttr = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
4648
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
4649
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${floatAttr}${styleAttr}></iframe>`;
|
|
4650
|
+
}
|
|
4651
|
+
return ``;
|
|
4652
|
+
}
|
|
4462
4653
|
if (embedType === "formula") {
|
|
4463
4654
|
const latex = typeof embedValue === "string" ? embedValue : "";
|
|
4464
4655
|
return useLatexDelimiters ? `\\(${latex}\\)` : `$${latex}$`;
|
|
@@ -4663,6 +4854,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4663
4854
|
let pendingText = "";
|
|
4664
4855
|
const spanAttrStack = [];
|
|
4665
4856
|
const footnoteDefinitions = /* @__PURE__ */ new Map();
|
|
4857
|
+
let codeBlockIdSeq = 0;
|
|
4666
4858
|
const context = {
|
|
4667
4859
|
delta,
|
|
4668
4860
|
pushText(text, attrs) {
|
|
@@ -4924,6 +5116,10 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4924
5116
|
context.pushEmbed({ video: url });
|
|
4925
5117
|
return;
|
|
4926
5118
|
}
|
|
5119
|
+
if (alt.toLowerCase() === "widget") {
|
|
5120
|
+
context.pushEmbed({ codeWidget: url });
|
|
5121
|
+
return;
|
|
5122
|
+
}
|
|
4927
5123
|
const attrs = {};
|
|
4928
5124
|
if (node.alt) attrs.alt = node.alt;
|
|
4929
5125
|
if (url.toLowerCase().endsWith(".drawio")) {
|
|
@@ -4978,7 +5174,8 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4978
5174
|
}
|
|
4979
5175
|
const lines = code.split("\n");
|
|
4980
5176
|
const codeBlockAttr = {
|
|
4981
|
-
"code-block": lang ?? true
|
|
5177
|
+
"code-block": lang ?? true,
|
|
5178
|
+
"code-block-id": `cb-${++codeBlockIdSeq}`
|
|
4982
5179
|
};
|
|
4983
5180
|
for (const line of lines) {
|
|
4984
5181
|
context.pushText(line);
|
|
@@ -4992,7 +5189,10 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4992
5189
|
context.pushNewline();
|
|
4993
5190
|
} else {
|
|
4994
5191
|
const lines = value.split("\n");
|
|
4995
|
-
const mathBlockAttr = {
|
|
5192
|
+
const mathBlockAttr = {
|
|
5193
|
+
"code-block": "math",
|
|
5194
|
+
"code-block-id": `cb-${++codeBlockIdSeq}`
|
|
5195
|
+
};
|
|
4996
5196
|
for (const line of lines) {
|
|
4997
5197
|
context.pushText(line);
|
|
4998
5198
|
context.pushNewline(mathBlockAttr);
|
|
@@ -5286,6 +5486,7 @@ export {
|
|
|
5286
5486
|
cloneDelta,
|
|
5287
5487
|
codeBlockFormat,
|
|
5288
5488
|
codeFormat,
|
|
5489
|
+
codeWidgetFormat,
|
|
5289
5490
|
colorFormat,
|
|
5290
5491
|
columnsBlockHandler,
|
|
5291
5492
|
createDefaultBlockHandlers,
|
|
@@ -5349,6 +5550,7 @@ export {
|
|
|
5349
5550
|
tableColFormat,
|
|
5350
5551
|
tableHeaderFormat,
|
|
5351
5552
|
tableRowFormat,
|
|
5553
|
+
toCodeWidgetEmbedUrl,
|
|
5352
5554
|
toHexColor,
|
|
5353
5555
|
underlineFormat,
|
|
5354
5556
|
unescapeHtml,
|