@scrider/formatter 1.5.0 → 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 +173 -0
- 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 +171 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,7 @@ __export(index_exports, {
|
|
|
60
60
|
cloneDelta: () => cloneDelta,
|
|
61
61
|
codeBlockFormat: () => codeBlockFormat,
|
|
62
62
|
codeFormat: () => codeFormat,
|
|
63
|
+
codeWidgetFormat: () => codeWidgetFormat,
|
|
63
64
|
colorFormat: () => colorFormat,
|
|
64
65
|
columnsBlockHandler: () => columnsBlockHandler,
|
|
65
66
|
createDefaultBlockHandlers: () => createDefaultBlockHandlers,
|
|
@@ -123,6 +124,7 @@ __export(index_exports, {
|
|
|
123
124
|
tableColFormat: () => tableColFormat,
|
|
124
125
|
tableHeaderFormat: () => tableHeaderFormat,
|
|
125
126
|
tableRowFormat: () => tableRowFormat,
|
|
127
|
+
toCodeWidgetEmbedUrl: () => toCodeWidgetEmbedUrl,
|
|
126
128
|
toHexColor: () => toHexColor,
|
|
127
129
|
underlineFormat: () => underlineFormat,
|
|
128
130
|
unescapeHtml: () => unescapeHtml,
|
|
@@ -2021,6 +2023,25 @@ var EMBED_RENDERERS = {
|
|
|
2021
2023
|
}
|
|
2022
2024
|
return `<video src="${escapeHtml(src)}" controls${float}${style}></video>`;
|
|
2023
2025
|
},
|
|
2026
|
+
codeWidget: (value, attrs) => {
|
|
2027
|
+
const src = typeof value === "string" ? value : "";
|
|
2028
|
+
const floatVal = attrs?.float;
|
|
2029
|
+
const widthVal = attrs?.width;
|
|
2030
|
+
const heightVal = attrs?.height;
|
|
2031
|
+
const float = floatVal != null && typeof floatVal === "string" && floatVal !== "none" ? ` data-float="${escapeHtml(floatVal)}"` : "";
|
|
2032
|
+
const styles = [];
|
|
2033
|
+
if (widthVal != null && (typeof widthVal === "string" || typeof widthVal === "number")) {
|
|
2034
|
+
const w = String(widthVal);
|
|
2035
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
2036
|
+
}
|
|
2037
|
+
if (heightVal != null && (typeof heightVal === "string" || typeof heightVal === "number")) {
|
|
2038
|
+
const h = String(heightVal);
|
|
2039
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
2040
|
+
}
|
|
2041
|
+
const style = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
2042
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
2043
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${float}${style}></iframe>`;
|
|
2044
|
+
},
|
|
2024
2045
|
formula: (value) => {
|
|
2025
2046
|
const latex = typeof value === "string" ? value : "";
|
|
2026
2047
|
return `<span class="formula" data-formula="${escapeHtml(latex)}">${escapeHtml(latex)}</span>`;
|
|
@@ -2114,6 +2135,124 @@ function fromVideoEmbedUrl(embedUrl) {
|
|
|
2114
2135
|
}
|
|
2115
2136
|
return embedUrl;
|
|
2116
2137
|
}
|
|
2138
|
+
function splitUrl(url) {
|
|
2139
|
+
let rest = url;
|
|
2140
|
+
let hash = "";
|
|
2141
|
+
const hashIdx = rest.indexOf("#");
|
|
2142
|
+
if (hashIdx >= 0) {
|
|
2143
|
+
hash = rest.slice(hashIdx);
|
|
2144
|
+
rest = rest.slice(0, hashIdx);
|
|
2145
|
+
}
|
|
2146
|
+
let query = "";
|
|
2147
|
+
const qIdx = rest.indexOf("?");
|
|
2148
|
+
if (qIdx >= 0) {
|
|
2149
|
+
query = rest.slice(qIdx);
|
|
2150
|
+
rest = rest.slice(0, qIdx);
|
|
2151
|
+
}
|
|
2152
|
+
return { base: rest, query, hash };
|
|
2153
|
+
}
|
|
2154
|
+
function hasQueryParam(url, key) {
|
|
2155
|
+
const { query } = splitUrl(url);
|
|
2156
|
+
return new RegExp(`[?&]${key}=`, "i").test(query);
|
|
2157
|
+
}
|
|
2158
|
+
function appendQueryParam(url, key, value) {
|
|
2159
|
+
const { base, query, hash } = splitUrl(url);
|
|
2160
|
+
const next = query ? `${query}&${key}=${value}` : `?${key}=${value}`;
|
|
2161
|
+
return `${base}${next}${hash}`;
|
|
2162
|
+
}
|
|
2163
|
+
function toCodeWidgetEmbedUrl(url) {
|
|
2164
|
+
const u = typeof url === "string" ? url.trim() : "";
|
|
2165
|
+
if (!u) return "";
|
|
2166
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*stackblitz\.com\//i.test(u)) {
|
|
2167
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "1");
|
|
2168
|
+
}
|
|
2169
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codesandbox\.io\//i.test(u)) {
|
|
2170
|
+
if (/codesandbox\.io\/embed\//i.test(u)) return u;
|
|
2171
|
+
return u.replace(/codesandbox\.io\/s\//i, "codesandbox.io/embed/");
|
|
2172
|
+
}
|
|
2173
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*replit\.com\//i.test(u)) {
|
|
2174
|
+
return hasQueryParam(u, "embed") ? u : appendQueryParam(u, "embed", "true");
|
|
2175
|
+
}
|
|
2176
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*codepen\.io\//i.test(u)) {
|
|
2177
|
+
if (/codepen\.io\/[^/]+\/embed\//i.test(u)) return u;
|
|
2178
|
+
return u.replace(/(codepen\.io\/[^/]+)\/pen\//i, "$1/embed/");
|
|
2179
|
+
}
|
|
2180
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*jsfiddle\.net\//i.test(u)) {
|
|
2181
|
+
const { base, query, hash } = splitUrl(u);
|
|
2182
|
+
if (/\/embedded(?:\/|$)/i.test(base)) return u;
|
|
2183
|
+
const trimmed = base.replace(/\/+$/, "");
|
|
2184
|
+
return `${trimmed}/embedded/${query}${hash}`;
|
|
2185
|
+
}
|
|
2186
|
+
return u;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
// src/schema/formats/embed/codeWidget.ts
|
|
2190
|
+
var codeWidgetFormat = {
|
|
2191
|
+
name: "codeWidget",
|
|
2192
|
+
scope: "embed",
|
|
2193
|
+
normalize(value) {
|
|
2194
|
+
return typeof value === "string" ? value.trim() : value;
|
|
2195
|
+
},
|
|
2196
|
+
validate(value) {
|
|
2197
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2198
|
+
return false;
|
|
2199
|
+
}
|
|
2200
|
+
const trimmed = value.trim();
|
|
2201
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../")) {
|
|
2202
|
+
return true;
|
|
2203
|
+
}
|
|
2204
|
+
if (trimmed.startsWith("//")) {
|
|
2205
|
+
return true;
|
|
2206
|
+
}
|
|
2207
|
+
try {
|
|
2208
|
+
const url = new URL(trimmed);
|
|
2209
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2210
|
+
} catch {
|
|
2211
|
+
return false;
|
|
2212
|
+
}
|
|
2213
|
+
},
|
|
2214
|
+
render(value, attributes) {
|
|
2215
|
+
const src = typeof value === "string" ? value : "";
|
|
2216
|
+
const floatVal = attributes?.float;
|
|
2217
|
+
const widthVal = attributes?.width;
|
|
2218
|
+
const heightVal = attributes?.height;
|
|
2219
|
+
const float = floatVal != null && typeof floatVal === "string" && floatVal !== "none" ? ` data-float="${escapeHtml(floatVal)}"` : "";
|
|
2220
|
+
const styles = [];
|
|
2221
|
+
if (widthVal != null && (typeof widthVal === "string" || typeof widthVal === "number")) {
|
|
2222
|
+
const w = String(widthVal);
|
|
2223
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
2224
|
+
}
|
|
2225
|
+
if (heightVal != null && (typeof heightVal === "string" || typeof heightVal === "number")) {
|
|
2226
|
+
const h = String(heightVal);
|
|
2227
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
2228
|
+
}
|
|
2229
|
+
const style = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
2230
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
2231
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${float}${style}></iframe>`;
|
|
2232
|
+
},
|
|
2233
|
+
match(element) {
|
|
2234
|
+
if (element.tagName.toLowerCase() !== "iframe") return null;
|
|
2235
|
+
if (element.getAttribute("data-code-widget") === null) return null;
|
|
2236
|
+
const src = element.getAttribute("src");
|
|
2237
|
+
if (!src) return null;
|
|
2238
|
+
const attrs = {};
|
|
2239
|
+
const float = element.getAttribute("data-float");
|
|
2240
|
+
const styleAttr = element.getAttribute("style") || "";
|
|
2241
|
+
if (float) attrs.float = float;
|
|
2242
|
+
const widthMatch = styleAttr.match(/(?:^|;\s*)width:\s*([^;]+)/);
|
|
2243
|
+
if (widthMatch?.[1]) attrs.width = widthMatch[1].trim().replace(/px$/, "");
|
|
2244
|
+
const heightMatch = styleAttr.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
2245
|
+
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
2246
|
+
if (Object.keys(attrs).length > 0) {
|
|
2247
|
+
return { value: src, attributes: attrs };
|
|
2248
|
+
}
|
|
2249
|
+
return { value: src };
|
|
2250
|
+
},
|
|
2251
|
+
toMarkdown(value) {
|
|
2252
|
+
const src = typeof value === "string" ? value : "";
|
|
2253
|
+
return ``;
|
|
2254
|
+
}
|
|
2255
|
+
};
|
|
2117
2256
|
|
|
2118
2257
|
// src/schema/formats/embed/divider.ts
|
|
2119
2258
|
var dividerFormat = {
|
|
@@ -2358,6 +2497,7 @@ var videoFormat = {
|
|
|
2358
2497
|
return `<video src="${escapeHtml(src)}" controls${float}${style}></video>`;
|
|
2359
2498
|
},
|
|
2360
2499
|
match(element) {
|
|
2500
|
+
if (element.getAttribute("data-code-widget") !== null) return null;
|
|
2361
2501
|
const tagName = element.tagName.toLowerCase();
|
|
2362
2502
|
if (tagName !== "video" && tagName !== "iframe") return null;
|
|
2363
2503
|
const src = element.getAttribute("src");
|
|
@@ -2410,6 +2550,7 @@ var defaultBlockFormats = [
|
|
|
2410
2550
|
var defaultEmbedFormats = [
|
|
2411
2551
|
imageFormat,
|
|
2412
2552
|
videoFormat,
|
|
2553
|
+
codeWidgetFormat,
|
|
2413
2554
|
formulaFormat,
|
|
2414
2555
|
dividerFormat,
|
|
2415
2556
|
softBreakFormat,
|
|
@@ -3752,6 +3893,10 @@ function htmlToDelta(html, options = {}) {
|
|
|
3752
3893
|
const heightMatch = style.match(/(?:^|;\s*)height:\s*([^;]+)/);
|
|
3753
3894
|
if (heightMatch?.[1]) attrs.height = heightMatch[1].trim().replace(/px$/, "");
|
|
3754
3895
|
const embedAttrs = Object.keys(attrs).length > 0 ? attrs : void 0;
|
|
3896
|
+
if (element.getAttribute("data-code-widget") !== null) {
|
|
3897
|
+
context.pushEmbed({ codeWidget: src }, embedAttrs);
|
|
3898
|
+
return;
|
|
3899
|
+
}
|
|
3755
3900
|
context.pushEmbed({ video: fromVideoEmbedUrl(src) }, embedAttrs);
|
|
3756
3901
|
}
|
|
3757
3902
|
function processFootnotesSection(section) {
|
|
@@ -4609,6 +4754,28 @@ function renderEmbed2(embed, attributes, customRenderers, useLatexDelimiters = f
|
|
|
4609
4754
|
}
|
|
4610
4755
|
return ``;
|
|
4611
4756
|
}
|
|
4757
|
+
if (embedType === "codeWidget") {
|
|
4758
|
+
const src = typeof embedValue === "string" ? embedValue : "";
|
|
4759
|
+
const hasFloat = attributes?.float != null && typeof attributes.float === "string" && attributes.float !== "none";
|
|
4760
|
+
const hasWidth = attributes?.width != null;
|
|
4761
|
+
const hasHeight = attributes?.height != null;
|
|
4762
|
+
if (hasFloat || hasWidth || hasHeight) {
|
|
4763
|
+
const floatAttr = hasFloat ? ` data-float="${escapeHtml(String(attributes.float))}"` : "";
|
|
4764
|
+
const styles = [];
|
|
4765
|
+
if (hasWidth) {
|
|
4766
|
+
const w = typeof attributes.width === "string" || typeof attributes.width === "number" ? String(attributes.width) : "";
|
|
4767
|
+
if (w && w !== "auto") styles.push(`width: ${/^\d+$/.test(w) ? w + "px" : w}`);
|
|
4768
|
+
}
|
|
4769
|
+
if (hasHeight) {
|
|
4770
|
+
const h = typeof attributes.height === "string" || typeof attributes.height === "number" ? String(attributes.height) : "";
|
|
4771
|
+
if (h && h !== "auto") styles.push(`height: ${/^\d+$/.test(h) ? h + "px" : h}`);
|
|
4772
|
+
}
|
|
4773
|
+
const styleAttr = styles.length > 0 ? ` style="${styles.join("; ")}"` : "";
|
|
4774
|
+
const embedSrc = toCodeWidgetEmbedUrl(src);
|
|
4775
|
+
return `<iframe data-code-widget src="${escapeHtml(embedSrc)}" frameborder="0" allowfullscreen${floatAttr}${styleAttr}></iframe>`;
|
|
4776
|
+
}
|
|
4777
|
+
return ``;
|
|
4778
|
+
}
|
|
4612
4779
|
if (embedType === "formula") {
|
|
4613
4780
|
const latex = typeof embedValue === "string" ? embedValue : "";
|
|
4614
4781
|
return useLatexDelimiters ? `\\(${latex}\\)` : `$${latex}$`;
|
|
@@ -5075,6 +5242,10 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
5075
5242
|
context.pushEmbed({ video: url });
|
|
5076
5243
|
return;
|
|
5077
5244
|
}
|
|
5245
|
+
if (alt.toLowerCase() === "widget") {
|
|
5246
|
+
context.pushEmbed({ codeWidget: url });
|
|
5247
|
+
return;
|
|
5248
|
+
}
|
|
5078
5249
|
const attrs = {};
|
|
5079
5250
|
if (node.alt) attrs.alt = node.alt;
|
|
5080
5251
|
if (url.toLowerCase().endsWith(".drawio")) {
|
|
@@ -5442,6 +5613,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5442
5613
|
cloneDelta,
|
|
5443
5614
|
codeBlockFormat,
|
|
5444
5615
|
codeFormat,
|
|
5616
|
+
codeWidgetFormat,
|
|
5445
5617
|
colorFormat,
|
|
5446
5618
|
columnsBlockHandler,
|
|
5447
5619
|
createDefaultBlockHandlers,
|
|
@@ -5505,6 +5677,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5505
5677
|
tableColFormat,
|
|
5506
5678
|
tableHeaderFormat,
|
|
5507
5679
|
tableRowFormat,
|
|
5680
|
+
toCodeWidgetEmbedUrl,
|
|
5508
5681
|
toHexColor,
|
|
5509
5682
|
underlineFormat,
|
|
5510
5683
|
unescapeHtml,
|