@scrider/formatter 1.5.0 → 1.6.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/dist/index.cjs +174 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +172 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -999,6 +999,30 @@ 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
|
+
* allow="…; cross-origin-isolated">
|
|
1015
|
+
*
|
|
1016
|
+
* The `allow="…; cross-origin-isolated"` list (see CODE_WIDGET_IFRAME_ALLOW)
|
|
1017
|
+
* delegates the cross-origin-isolated capability so StackBlitz WebContainer
|
|
1018
|
+
* embeds can boot SharedArrayBuffer; without it those embeds render blank.
|
|
1019
|
+
*
|
|
1020
|
+
* The src is run through `toCodeWidgetEmbedUrl` at render time, which is
|
|
1021
|
+
* idempotent, so resize/float attributes and the Delta ↔ HTML round-trip stay
|
|
1022
|
+
* stable regardless of whether the stored value is the user URL or embed URL.
|
|
1023
|
+
*/
|
|
1024
|
+
declare const codeWidgetFormat: Format<string>;
|
|
1025
|
+
|
|
1002
1026
|
/**
|
|
1003
1027
|
* Divider (Horizontal Rule) embed format
|
|
1004
1028
|
*
|
|
@@ -1580,6 +1604,26 @@ declare function escapeHtml(text: string): string;
|
|
|
1580
1604
|
* Unescape HTML entities
|
|
1581
1605
|
*/
|
|
1582
1606
|
declare function unescapeHtml(text: string): string;
|
|
1607
|
+
/**
|
|
1608
|
+
* Convert a code-playground URL to an embeddable iframe URL (Phase 8 Part 3.5).
|
|
1609
|
+
*
|
|
1610
|
+
* Idempotent: a URL that is already in embed form is returned unchanged, so the
|
|
1611
|
+
* Delta → HTML → Delta round-trip is stable regardless of which form is stored.
|
|
1612
|
+
*
|
|
1613
|
+
* Provider | User URL | Embed URL
|
|
1614
|
+
* -------------|----------------------------------|-----------------------------------
|
|
1615
|
+
* StackBlitz | stackblitz.com/edit/{id} | …?embed=1
|
|
1616
|
+
* | stackblitz.com/github/{u}/{r} | …?embed=1
|
|
1617
|
+
* CodeSandbox | codesandbox.io/s/{id} | codesandbox.io/embed/{id}
|
|
1618
|
+
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1619
|
+
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1620
|
+
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1621
|
+
*
|
|
1622
|
+
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1623
|
+
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
|
1624
|
+
* editor layer).
|
|
1625
|
+
*/
|
|
1626
|
+
declare function toCodeWidgetEmbedUrl(url: string): string;
|
|
1583
1627
|
|
|
1584
1628
|
/**
|
|
1585
1629
|
* GitHub-compatible slugify for heading anchor links.
|
|
@@ -1944,4 +1988,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1944
1988
|
*/
|
|
1945
1989
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1946
1990
|
|
|
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 };
|
|
1991
|
+
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,30 @@ 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
|
+
* allow="…; cross-origin-isolated">
|
|
1015
|
+
*
|
|
1016
|
+
* The `allow="…; cross-origin-isolated"` list (see CODE_WIDGET_IFRAME_ALLOW)
|
|
1017
|
+
* delegates the cross-origin-isolated capability so StackBlitz WebContainer
|
|
1018
|
+
* embeds can boot SharedArrayBuffer; without it those embeds render blank.
|
|
1019
|
+
*
|
|
1020
|
+
* The src is run through `toCodeWidgetEmbedUrl` at render time, which is
|
|
1021
|
+
* idempotent, so resize/float attributes and the Delta ↔ HTML round-trip stay
|
|
1022
|
+
* stable regardless of whether the stored value is the user URL or embed URL.
|
|
1023
|
+
*/
|
|
1024
|
+
declare const codeWidgetFormat: Format<string>;
|
|
1025
|
+
|
|
1002
1026
|
/**
|
|
1003
1027
|
* Divider (Horizontal Rule) embed format
|
|
1004
1028
|
*
|
|
@@ -1580,6 +1604,26 @@ declare function escapeHtml(text: string): string;
|
|
|
1580
1604
|
* Unescape HTML entities
|
|
1581
1605
|
*/
|
|
1582
1606
|
declare function unescapeHtml(text: string): string;
|
|
1607
|
+
/**
|
|
1608
|
+
* Convert a code-playground URL to an embeddable iframe URL (Phase 8 Part 3.5).
|
|
1609
|
+
*
|
|
1610
|
+
* Idempotent: a URL that is already in embed form is returned unchanged, so the
|
|
1611
|
+
* Delta → HTML → Delta round-trip is stable regardless of which form is stored.
|
|
1612
|
+
*
|
|
1613
|
+
* Provider | User URL | Embed URL
|
|
1614
|
+
* -------------|----------------------------------|-----------------------------------
|
|
1615
|
+
* StackBlitz | stackblitz.com/edit/{id} | …?embed=1
|
|
1616
|
+
* | stackblitz.com/github/{u}/{r} | …?embed=1
|
|
1617
|
+
* CodeSandbox | codesandbox.io/s/{id} | codesandbox.io/embed/{id}
|
|
1618
|
+
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1619
|
+
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1620
|
+
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1621
|
+
*
|
|
1622
|
+
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1623
|
+
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
|
1624
|
+
* editor layer).
|
|
1625
|
+
*/
|
|
1626
|
+
declare function toCodeWidgetEmbedUrl(url: string): string;
|
|
1583
1627
|
|
|
1584
1628
|
/**
|
|
1585
1629
|
* GitHub-compatible slugify for heading anchor links.
|
|
@@ -1944,4 +1988,4 @@ declare function isTableNewlineOp(op: Op | undefined): boolean;
|
|
|
1944
1988
|
*/
|
|
1945
1989
|
declare function extractTableRegion(ops: readonly Op[], hintOpIdx: number): TableRegion | null;
|
|
1946
1990
|
|
|
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 };
|
|
1991
|
+
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 allow="${CODE_WIDGET_IFRAME_ALLOW}"${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,125 @@ 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
|
+
var CODE_WIDGET_IFRAME_ALLOW = "accelerometer; camera; encrypted-media; geolocation; gyroscope; microphone; midi; payment; usb; vr; xr-spatial-tracking; cross-origin-isolated";
|
|
2038
|
+
function toCodeWidgetEmbedUrl(url) {
|
|
2039
|
+
const u = typeof url === "string" ? url.trim() : "";
|
|
2040
|
+
if (!u) return "";
|
|
2041
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*stackblitz\.com\//i.test(u)) {
|
|
2042
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "1");
|
|
2043
|
+
}
|
|
2044
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codesandbox\.io\//i.test(u)) {
|
|
2045
|
+
if (/codesandbox\.io\/embed\//i.test(u)) return u;
|
|
2046
|
+
return u.replace(/codesandbox\.io\/s\//i, "codesandbox.io/embed/");
|
|
2047
|
+
}
|
|
2048
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*replit\.com\//i.test(u)) {
|
|
2049
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "true");
|
|
2050
|
+
}
|
|
2051
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codepen\.io\//i.test(u)) {
|
|
2052
|
+
if (/codepen\.io\/[^/]+\/embed\//i.test(u)) return u;
|
|
2053
|
+
return u.replace(/(codepen\.io\/[^/]+)\/pen\//i, "$1/embed/");
|
|
2054
|
+
}
|
|
2055
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*jsfiddle\.net\//i.test(u)) {
|
|
2056
|
+
const { base, query, hash } = splitUrl(u);
|
|
2057
|
+
if (/\/embedded(?:\/|$)/i.test(base)) return u;
|
|
2058
|
+
const trimmed = base.replace(/\/+$/, "");
|
|
2059
|
+
return `${trimmed}/embedded/${query}${hash}`;
|
|
2060
|
+
}
|
|
2061
|
+
return u;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
// src/schema/formats/embed/codeWidget.ts
|
|
2065
|
+
var codeWidgetFormat = {
|
|
2066
|
+
name: "codeWidget",
|
|
2067
|
+
scope: "embed",
|
|
2068
|
+
normalize(value) {
|
|
2069
|
+
return typeof value === "string" ? value.trim() : value;
|
|
2070
|
+
},
|
|
2071
|
+
validate(value) {
|
|
2072
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
const trimmed = value.trim();
|
|
2076
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
|
|
2077
|
+
return true;
|
|
2078
|
+
}
|
|
2079
|
+
if (trimmed.startsWith("//")) {
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
try {
|
|
2083
|
+
const url = new URL(trimmed);
|
|
2084
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2085
|
+
} catch {
|
|
2086
|
+
return false;
|
|
2087
|
+
}
|
|
2088
|
+
},
|
|
2089
|
+
render(value, attributes) {
|
|
2090
|
+
const src = typeof value === "string" ? value : "";
|
|
2091
|
+
const floatVal = attributes?.float;
|
|
2092
|
+
const widthVal = attributes?.width;
|
|
2093
|
+
const heightVal = attributes?.height;
|
|
2094
|
+
const float = floatVal != null && typeof floatVal === "string" && floatVal !== "none" ? ` data-float="${escapeHtml(floatVal)}"` : "";
|
|
2095
|
+
const styles = [];
|
|
2096
|
+
if (widthVal != null && (typeof widthVal === "string" || typeof widthVal === "number")) {
|
|
2097
|
+
const w = String(widthVal);
|
|
2098
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
2099
|
+
}
|
|
2100
|
+
if (heightVal != null && (typeof heightVal === "string" || typeof heightVal === "number")) {
|
|
2101
|
+
const h = String(heightVal);
|
|
2102
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
2103
|
+
}
|
|
2104
|
+
const style = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
2105
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
2106
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen allow="${CODE_WIDGET_IFRAME_ALLOW}"${float}${style}></iframe>`;
|
|
2107
|
+
},
|
|
2108
|
+
match(element) {
|
|
2109
|
+
if (element.tagName.toLowerCase() !== "iframe") return null;
|
|
2110
|
+
if (element.getAttribute("data-code-widget") === null) return null;
|
|
2111
|
+
const src = element.getAttribute("src");
|
|
2112
|
+
if (!src) return null;
|
|
2113
|
+
const attrs = {};
|
|
2114
|
+
const float = element.getAttribute("data-float");
|
|
2115
|
+
const styleAttr = element.getAttribute("style") || "";
|
|
2116
|
+
if (float) attrs.float = float;
|
|
2117
|
+
const widthMatch = styleAttr.match(/(?:^|;\s*)width:\s*([^;]+)/);
|
|
2118
|
+
if (widthMatch?.[1]) attrs.width = widthMatch[1].trim().replace(/px$/, "");
|
|
2119
|
+
const heightMatch = styleAttr.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
2120
|
+
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
2121
|
+
if (Object.keys(attrs).length > 0) {
|
|
2122
|
+
return { value: src, attributes: attrs };
|
|
2123
|
+
}
|
|
2124
|
+
return { value: src };
|
|
2125
|
+
},
|
|
2126
|
+
toMarkdown(value) {
|
|
2127
|
+
const src = typeof value === "string" ? value : "";
|
|
2128
|
+
return ``;
|
|
2129
|
+
}
|
|
2130
|
+
};
|
|
1993
2131
|
|
|
1994
2132
|
// src/schema/formats/embed/divider.ts
|
|
1995
2133
|
var dividerFormat = {
|
|
@@ -2234,6 +2372,7 @@ var videoFormat = {
|
|
|
2234
2372
|
return `<video src="${escapeHtml(src)}" controls${float}${style}></video>`;
|
|
2235
2373
|
},
|
|
2236
2374
|
match(element) {
|
|
2375
|
+
if (element.getAttribute("data-code-widget") !== null) return null;
|
|
2237
2376
|
const tagName = element.tagName.toLowerCase();
|
|
2238
2377
|
if (tagName !== "video" && tagName !== "iframe") return null;
|
|
2239
2378
|
const src = element.getAttribute("src");
|
|
@@ -2286,6 +2425,7 @@ var defaultBlockFormats = [
|
|
|
2286
2425
|
var defaultEmbedFormats = [
|
|
2287
2426
|
imageFormat,
|
|
2288
2427
|
videoFormat,
|
|
2428
|
+
codeWidgetFormat,
|
|
2289
2429
|
formulaFormat,
|
|
2290
2430
|
dividerFormat,
|
|
2291
2431
|
softBreakFormat,
|
|
@@ -3628,6 +3768,10 @@ function htmlToDelta(html, options = {}) {
|
|
|
3628
3768
|
const heightMatch = style.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
3629
3769
|
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
3630
3770
|
const embedAttrs = Object.keys(attrs).length > 0 ? attrs : void 0;
|
|
3771
|
+
if (element.getAttribute("data-code-widget") !== null) {
|
|
3772
|
+
context.pushEmbed({ codeWidget: src }, embedAttrs);
|
|
3773
|
+
return;
|
|
3774
|
+
}
|
|
3631
3775
|
context.pushEmbed({ video: fromVideoEmbedUrl(src) }, embedAttrs);
|
|
3632
3776
|
}
|
|
3633
3777
|
function processFootnotesSection(section) {
|
|
@@ -4485,6 +4629,28 @@ function renderEmbed2(embed, attributes, customRenderers, useLatexDelimiters = f
|
|
|
4485
4629
|
}
|
|
4486
4630
|
return ``;
|
|
4487
4631
|
}
|
|
4632
|
+
if (embedType === "codeWidget") {
|
|
4633
|
+
const src = typeof embedValue === "string" ? embedValue : "";
|
|
4634
|
+
const hasFloat = attributes?.float != null && typeof attributes.float === "string" && attributes.float !== "none";
|
|
4635
|
+
const hasWidth = attributes?.width != null;
|
|
4636
|
+
const hasHeight = attributes?.height != null;
|
|
4637
|
+
if (hasFloat || hasWidth || hasHeight) {
|
|
4638
|
+
const floatAttr = hasFloat ? ` data-float="${escapeHtml(String(attributes.float))}"` : "";
|
|
4639
|
+
const styles = [];
|
|
4640
|
+
if (hasWidth) {
|
|
4641
|
+
const w = typeof attributes.width === "string" || typeof attributes.width === "number" ? String(attributes.width) : "";
|
|
4642
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
4643
|
+
}
|
|
4644
|
+
if (hasHeight) {
|
|
4645
|
+
const h = typeof attributes.height === "string" || typeof attributes.height === "number" ? String(attributes.height) : "";
|
|
4646
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
4647
|
+
}
|
|
4648
|
+
const styleAttr = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
4649
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
4650
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${floatAttr}${styleAttr}></iframe>`;
|
|
4651
|
+
}
|
|
4652
|
+
return ``;
|
|
4653
|
+
}
|
|
4488
4654
|
if (embedType === "formula") {
|
|
4489
4655
|
const latex = typeof embedValue === "string" ? embedValue : "";
|
|
4490
4656
|
return useLatexDelimiters ? `\\(${latex}\\)` : `$${latex}$`;
|
|
@@ -4951,6 +5117,10 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
4951
5117
|
context.pushEmbed({ video: url });
|
|
4952
5118
|
return;
|
|
4953
5119
|
}
|
|
5120
|
+
if (alt.toLowerCase() === "widget") {
|
|
5121
|
+
context.pushEmbed({ codeWidget: url });
|
|
5122
|
+
return;
|
|
5123
|
+
}
|
|
4954
5124
|
const attrs = {};
|
|
4955
5125
|
if (node.alt) attrs.alt = node.alt;
|
|
4956
5126
|
if (url.toLowerCase().endsWith(".drawio")) {
|
|
@@ -5317,6 +5487,7 @@ export {
|
|
|
5317
5487
|
cloneDelta,
|
|
5318
5488
|
codeBlockFormat,
|
|
5319
5489
|
codeFormat,
|
|
5490
|
+
codeWidgetFormat,
|
|
5320
5491
|
colorFormat,
|
|
5321
5492
|
columnsBlockHandler,
|
|
5322
5493
|
createDefaultBlockHandlers,
|
|
@@ -5380,6 +5551,7 @@ export {
|
|
|
5380
5551
|
tableColFormat,
|
|
5381
5552
|
tableHeaderFormat,
|
|
5382
5553
|
tableRowFormat,
|
|
5554
|
+
toCodeWidgetEmbedUrl,
|
|
5383
5555
|
toHexColor,
|
|
5384
5556
|
underlineFormat,
|
|
5385
5557
|
unescapeHtml,
|