@scrider/formatter 1.7.1 → 1.8.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 +205 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +202 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1026,7 +1026,7 @@ declare const blockFormat: Format<Record<string, unknown>>;
|
|
|
1026
1026
|
* Delta: { insert: { codeWidget: "https://codesandbox.io/s/abc123" } }
|
|
1027
1027
|
*
|
|
1028
1028
|
* Value is a URL to an interactive code playground (StackBlitz, CodeSandbox,
|
|
1029
|
-
* Replit, CodePen, JSFiddle). Rendered as an <iframe> carrying a
|
|
1029
|
+
* Replit, CodePen, JSFiddle, Trinket, OneCompiler). Rendered as an <iframe> carrying a
|
|
1030
1030
|
* `data-code-widget` marker so it can be told apart from a plain video iframe
|
|
1031
1031
|
* during HTML → Delta (see videoFormat.match guard).
|
|
1032
1032
|
*
|
|
@@ -1656,6 +1656,8 @@ declare function unescapeHtml(text: string): string;
|
|
|
1656
1656
|
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1657
1657
|
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1658
1658
|
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1659
|
+
* Trinket | trinket.io/{lang}/{id} | trinket.io/embed/{lang}/{id}
|
|
1660
|
+
* OneCompiler | onecompiler.com/{lang}/{id} | onecompiler.com/embed/{lang}/{id}
|
|
1659
1661
|
*
|
|
1660
1662
|
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1661
1663
|
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
package/dist/index.d.ts
CHANGED
|
@@ -1026,7 +1026,7 @@ declare const blockFormat: Format<Record<string, unknown>>;
|
|
|
1026
1026
|
* Delta: { insert: { codeWidget: "https://codesandbox.io/s/abc123" } }
|
|
1027
1027
|
*
|
|
1028
1028
|
* Value is a URL to an interactive code playground (StackBlitz, CodeSandbox,
|
|
1029
|
-
* Replit, CodePen, JSFiddle). Rendered as an <iframe> carrying a
|
|
1029
|
+
* Replit, CodePen, JSFiddle, Trinket, OneCompiler). Rendered as an <iframe> carrying a
|
|
1030
1030
|
* `data-code-widget` marker so it can be told apart from a plain video iframe
|
|
1031
1031
|
* during HTML → Delta (see videoFormat.match guard).
|
|
1032
1032
|
*
|
|
@@ -1656,6 +1656,8 @@ declare function unescapeHtml(text: string): string;
|
|
|
1656
1656
|
* Replit | replit.com/@{u}/{repl} | …?embed=true
|
|
1657
1657
|
* CodePen | codepen.io/{u}/pen/{id} | codepen.io/{u}/embed/{id}
|
|
1658
1658
|
* JSFiddle | jsfiddle.net/{u}/{id}/ | jsfiddle.net/{u}/{id}/embedded/
|
|
1659
|
+
* Trinket | trinket.io/{lang}/{id} | trinket.io/embed/{lang}/{id}
|
|
1660
|
+
* OneCompiler | onecompiler.com/{lang}/{id} | onecompiler.com/embed/{lang}/{id}
|
|
1659
1661
|
*
|
|
1660
1662
|
* Unknown hosts are returned unchanged (the marker `data-code-widget` still
|
|
1661
1663
|
* makes them render as an iframe; auto-detection of bare URLs lives in the
|
package/dist/index.js
CHANGED
|
@@ -333,6 +333,20 @@ function cloneDelta(delta) {
|
|
|
333
333
|
return new Delta(deepClone(delta.ops));
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
// src/conversion/markdown/table-header-markdown.ts
|
|
337
|
+
function isHeaderDashPlaceholder(text) {
|
|
338
|
+
const t = text.trim();
|
|
339
|
+
return t === "-" && t.length === 1;
|
|
340
|
+
}
|
|
341
|
+
function normalizeHeaderCellForParse(text, isHeaderRow) {
|
|
342
|
+
if (isHeaderRow && isHeaderDashPlaceholder(text)) return "";
|
|
343
|
+
return text;
|
|
344
|
+
}
|
|
345
|
+
function serializeHeaderCell(text) {
|
|
346
|
+
if (text.trim() === "") return "-";
|
|
347
|
+
return text;
|
|
348
|
+
}
|
|
349
|
+
|
|
336
350
|
// src/conversion/adapters/types.ts
|
|
337
351
|
var NODE_TYPE = {
|
|
338
352
|
ELEMENT_NODE: 1,
|
|
@@ -454,19 +468,21 @@ function renderGfmTable(data, context) {
|
|
|
454
468
|
if (headerRows === 0) {
|
|
455
469
|
const emptyParts = [];
|
|
456
470
|
for (let c = 0; c < cols; c++) {
|
|
457
|
-
emptyParts.push("
|
|
471
|
+
emptyParts.push("");
|
|
458
472
|
}
|
|
459
473
|
lines.push("| " + emptyParts.join(" | ") + " |");
|
|
460
474
|
lines.push(renderGfmSeparator(cols, data.colAligns));
|
|
461
475
|
}
|
|
462
476
|
for (let r = 0; r < rows; r++) {
|
|
463
477
|
const parts = [];
|
|
478
|
+
const isHeaderRow = headerRows > 0 && r < headerRows;
|
|
464
479
|
for (let c = 0; c < cols; c++) {
|
|
465
480
|
const cell = data.cells[`${r}:${c}`];
|
|
466
481
|
let text = "";
|
|
467
482
|
if (cell && context.renderDelta) {
|
|
468
483
|
text = stripCellContent(context.renderDelta(cell.ops));
|
|
469
484
|
}
|
|
485
|
+
if (isHeaderRow) text = serializeHeaderCell(text);
|
|
470
486
|
parts.push(text.replace(/\|/g, "\\|"));
|
|
471
487
|
}
|
|
472
488
|
lines.push("| " + parts.join(" | ") + " |");
|
|
@@ -2069,6 +2085,14 @@ function toCodeWidgetEmbedUrl(url) {
|
|
|
2069
2085
|
const trimmed = base.replace(/\/+$/, "");
|
|
2070
2086
|
return `${trimmed}/embedded/${query}${hash}`;
|
|
2071
2087
|
}
|
|
2088
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*trinket\.io\//i.test(u)) {
|
|
2089
|
+
if (/trinket\.io\/embed\//i.test(u)) return u;
|
|
2090
|
+
return u.replace(/trinket\.io\//i, "trinket.io/embed/");
|
|
2091
|
+
}
|
|
2092
|
+
if (/(?:\/\/|^)(?:[\w-]+\.)*onecompiler\.com\//i.test(u)) {
|
|
2093
|
+
if (/onecompiler\.com\/embed\//i.test(u)) return u;
|
|
2094
|
+
return u.replace(/onecompiler\.com\//i, "onecompiler.com/embed/");
|
|
2095
|
+
}
|
|
2072
2096
|
return u;
|
|
2073
2097
|
}
|
|
2074
2098
|
|
|
@@ -4424,7 +4448,15 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
|
|
|
4424
4448
|
if (headerRows.length > 0) {
|
|
4425
4449
|
for (const [, row] of headerRows) {
|
|
4426
4450
|
mdLines.push(
|
|
4427
|
-
renderMdRow(
|
|
4451
|
+
renderMdRow(
|
|
4452
|
+
row.cells,
|
|
4453
|
+
maxCol,
|
|
4454
|
+
embedRenderers,
|
|
4455
|
+
useLatexDelimiters,
|
|
4456
|
+
registry,
|
|
4457
|
+
softBreakStyle,
|
|
4458
|
+
true
|
|
4459
|
+
)
|
|
4428
4460
|
);
|
|
4429
4461
|
}
|
|
4430
4462
|
mdLines.push(renderMdSeparator(maxCol, colAligns));
|
|
@@ -4434,22 +4466,38 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
|
|
|
4434
4466
|
emptyRow.set(col, { ops: [] });
|
|
4435
4467
|
}
|
|
4436
4468
|
mdLines.push(
|
|
4437
|
-
renderMdRow(
|
|
4469
|
+
renderMdRow(
|
|
4470
|
+
emptyRow,
|
|
4471
|
+
maxCol,
|
|
4472
|
+
embedRenderers,
|
|
4473
|
+
useLatexDelimiters,
|
|
4474
|
+
registry,
|
|
4475
|
+
softBreakStyle,
|
|
4476
|
+
false
|
|
4477
|
+
)
|
|
4438
4478
|
);
|
|
4439
4479
|
mdLines.push(renderMdSeparator(maxCol, colAligns));
|
|
4440
4480
|
}
|
|
4441
4481
|
for (const [, row] of bodyRows) {
|
|
4442
4482
|
mdLines.push(
|
|
4443
|
-
renderMdRow(
|
|
4483
|
+
renderMdRow(
|
|
4484
|
+
row.cells,
|
|
4485
|
+
maxCol,
|
|
4486
|
+
embedRenderers,
|
|
4487
|
+
useLatexDelimiters,
|
|
4488
|
+
registry,
|
|
4489
|
+
softBreakStyle,
|
|
4490
|
+
false
|
|
4491
|
+
)
|
|
4444
4492
|
);
|
|
4445
4493
|
}
|
|
4446
4494
|
return mdLines.join("\n");
|
|
4447
4495
|
}
|
|
4448
|
-
function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces") {
|
|
4496
|
+
function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces", isHeaderRow = false) {
|
|
4449
4497
|
const parts = [];
|
|
4450
4498
|
for (let col = 0; col <= maxCol; col++) {
|
|
4451
4499
|
const cell = cells.get(col);
|
|
4452
|
-
|
|
4500
|
+
let content = cell ? renderLineContent2(
|
|
4453
4501
|
cell.ops,
|
|
4454
4502
|
embedRenderers,
|
|
4455
4503
|
false,
|
|
@@ -4461,6 +4509,7 @@ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false,
|
|
|
4461
4509
|
true
|
|
4462
4510
|
// inTableCell — softBreak must use <br>, never " \n"
|
|
4463
4511
|
) : "";
|
|
4512
|
+
if (isHeaderRow) content = serializeHeaderCell(content);
|
|
4464
4513
|
parts.push(content.replace(/\|/g, "\\|"));
|
|
4465
4514
|
}
|
|
4466
4515
|
return "| " + parts.join(" | ") + " |";
|
|
@@ -4725,7 +4774,138 @@ function renderBlockFormat(content, attributes, orderedIndex, _strict) {
|
|
|
4725
4774
|
}
|
|
4726
4775
|
|
|
4727
4776
|
// src/conversion/markdown/markdown-to-delta.ts
|
|
4728
|
-
import { Delta as Delta10 } from "@scrider/delta";
|
|
4777
|
+
import { Delta as Delta10, isInsert as isInsert5 } from "@scrider/delta";
|
|
4778
|
+
|
|
4779
|
+
// src/conversion/markdown/table-header-normalize.ts
|
|
4780
|
+
import { isInsert as isInsert4 } from "@scrider/delta";
|
|
4781
|
+
function isTableCellTerminator(op) {
|
|
4782
|
+
return isInsert4(op) && typeof op.insert === "string" && op.insert === "\n" && op.attributes !== void 0 && typeof op.attributes["table-row"] === "number";
|
|
4783
|
+
}
|
|
4784
|
+
function normalizeSyntheticEmptyHeaderRow(ops) {
|
|
4785
|
+
const ends = [];
|
|
4786
|
+
let buf = "";
|
|
4787
|
+
const textOpIndicesByCell = [];
|
|
4788
|
+
let currentTextOps = [];
|
|
4789
|
+
for (let i = 0; i < ops.length; i++) {
|
|
4790
|
+
const op = ops[i];
|
|
4791
|
+
if (!isInsert4(op)) continue;
|
|
4792
|
+
if (typeof op.insert === "string" && op.insert !== "\n") {
|
|
4793
|
+
buf += op.insert;
|
|
4794
|
+
currentTextOps.push(i);
|
|
4795
|
+
continue;
|
|
4796
|
+
}
|
|
4797
|
+
if (isTableCellTerminator(op)) {
|
|
4798
|
+
const row = op.attributes["table-row"];
|
|
4799
|
+
const col = op.attributes["table-col"];
|
|
4800
|
+
ends.push({ row, col, newlineIdx: i, text: buf });
|
|
4801
|
+
textOpIndicesByCell.push([...currentTextOps]);
|
|
4802
|
+
buf = "";
|
|
4803
|
+
currentTextOps = [];
|
|
4804
|
+
}
|
|
4805
|
+
}
|
|
4806
|
+
const row0 = ends.filter((e) => e.row === 0);
|
|
4807
|
+
if (row0.length === 0) return [...ops];
|
|
4808
|
+
if (!row0.every((e) => e.text.trim() === "")) return [...ops];
|
|
4809
|
+
if (row0.some((e) => isHeaderDashPlaceholder(e.text))) return [...ops];
|
|
4810
|
+
const remove = /* @__PURE__ */ new Set();
|
|
4811
|
+
for (let j = 0; j < ends.length; j++) {
|
|
4812
|
+
const end = ends[j];
|
|
4813
|
+
if (end.row !== 0) continue;
|
|
4814
|
+
remove.add(end.newlineIdx);
|
|
4815
|
+
for (const ti of textOpIndicesByCell[j] ?? []) remove.add(ti);
|
|
4816
|
+
}
|
|
4817
|
+
const out = [];
|
|
4818
|
+
for (let i = 0; i < ops.length; i++) {
|
|
4819
|
+
if (remove.has(i)) continue;
|
|
4820
|
+
const op = ops[i];
|
|
4821
|
+
if (!isTableCellTerminator(op)) {
|
|
4822
|
+
out.push(op);
|
|
4823
|
+
continue;
|
|
4824
|
+
}
|
|
4825
|
+
const row = op.attributes["table-row"];
|
|
4826
|
+
if (row === 0) continue;
|
|
4827
|
+
const attrs = { ...op.attributes };
|
|
4828
|
+
delete attrs["table-header"];
|
|
4829
|
+
out.push({
|
|
4830
|
+
insert: "\n",
|
|
4831
|
+
attributes: { ...attrs, "table-row": row - 1 }
|
|
4832
|
+
});
|
|
4833
|
+
}
|
|
4834
|
+
return out;
|
|
4835
|
+
}
|
|
4836
|
+
function normalizeHeaderDashPlaceholders(ops) {
|
|
4837
|
+
const ends = [];
|
|
4838
|
+
let buf = "";
|
|
4839
|
+
let currentTextOps = [];
|
|
4840
|
+
for (let i = 0; i < ops.length; i++) {
|
|
4841
|
+
const op = ops[i];
|
|
4842
|
+
if (!isInsert4(op)) continue;
|
|
4843
|
+
if (typeof op.insert === "string" && op.insert !== "\n") {
|
|
4844
|
+
buf += op.insert;
|
|
4845
|
+
currentTextOps.push(i);
|
|
4846
|
+
continue;
|
|
4847
|
+
}
|
|
4848
|
+
if (isTableCellTerminator(op)) {
|
|
4849
|
+
const row = op.attributes["table-row"];
|
|
4850
|
+
const isHeader = row === 0 && op.attributes["table-header"] === true;
|
|
4851
|
+
ends.push({ isHeader, textOpIndices: [...currentTextOps], text: buf });
|
|
4852
|
+
buf = "";
|
|
4853
|
+
currentTextOps = [];
|
|
4854
|
+
}
|
|
4855
|
+
}
|
|
4856
|
+
const dashHeaderCells = ends.filter(
|
|
4857
|
+
(e) => e.isHeader && e.textOpIndices.length > 0 && isHeaderDashPlaceholder(e.text)
|
|
4858
|
+
);
|
|
4859
|
+
if (dashHeaderCells.length === 0) return [...ops];
|
|
4860
|
+
const replaceIndices = /* @__PURE__ */ new Set();
|
|
4861
|
+
for (const end of dashHeaderCells) {
|
|
4862
|
+
for (const ti of end.textOpIndices) replaceIndices.add(ti);
|
|
4863
|
+
}
|
|
4864
|
+
const out = [];
|
|
4865
|
+
for (let i = 0; i < ops.length; i++) {
|
|
4866
|
+
const op = ops[i];
|
|
4867
|
+
if (!replaceIndices.has(i)) {
|
|
4868
|
+
out.push(op);
|
|
4869
|
+
continue;
|
|
4870
|
+
}
|
|
4871
|
+
if (!isInsert4(op)) {
|
|
4872
|
+
out.push(op);
|
|
4873
|
+
continue;
|
|
4874
|
+
}
|
|
4875
|
+
if (typeof op.insert === "string" && op.insert !== "\n") {
|
|
4876
|
+
const normalized = normalizeHeaderCellForParse(op.insert, true);
|
|
4877
|
+
if (normalized.length === 0) continue;
|
|
4878
|
+
out.push(
|
|
4879
|
+
op.attributes ? { insert: normalized, attributes: op.attributes } : { insert: normalized }
|
|
4880
|
+
);
|
|
4881
|
+
} else {
|
|
4882
|
+
out.push(op);
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4885
|
+
return out;
|
|
4886
|
+
}
|
|
4887
|
+
function normalizeImportedTableOps(ops) {
|
|
4888
|
+
if (ops.length === 0) return [...ops];
|
|
4889
|
+
const ends = [];
|
|
4890
|
+
let buf = "";
|
|
4891
|
+
for (const op of ops) {
|
|
4892
|
+
if (!isInsert4(op)) continue;
|
|
4893
|
+
if (typeof op.insert === "string" && op.insert !== "\n") {
|
|
4894
|
+
buf += op.insert;
|
|
4895
|
+
continue;
|
|
4896
|
+
}
|
|
4897
|
+
if (isTableCellTerminator(op)) {
|
|
4898
|
+
ends.push({ row: op.attributes["table-row"], text: buf });
|
|
4899
|
+
buf = "";
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
const row0 = ends.filter((e) => e.row === 0);
|
|
4903
|
+
const headerless = row0.length > 0 && row0.every((e) => e.text.trim() === "") && !row0.some((e) => isHeaderDashPlaceholder(e.text));
|
|
4904
|
+
if (headerless) return normalizeSyntheticEmptyHeaderRow(ops);
|
|
4905
|
+
return normalizeHeaderDashPlaceholders(ops);
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4908
|
+
// src/conversion/markdown/markdown-to-delta.ts
|
|
4729
4909
|
var remarkParse = null;
|
|
4730
4910
|
var remarkGfm = null;
|
|
4731
4911
|
var remarkMath = null;
|
|
@@ -5214,6 +5394,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
5214
5394
|
}
|
|
5215
5395
|
function processTable(node) {
|
|
5216
5396
|
if (!node.children) return;
|
|
5397
|
+
const tableStart = delta.ops.length;
|
|
5217
5398
|
const aligns = node.align || [];
|
|
5218
5399
|
for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
|
|
5219
5400
|
const rowNode = node.children[rowIdx];
|
|
@@ -5242,6 +5423,15 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
5242
5423
|
context.pushNewline(cellBlockAttrs);
|
|
5243
5424
|
}
|
|
5244
5425
|
}
|
|
5426
|
+
const tableOps = delta.ops.splice(tableStart);
|
|
5427
|
+
for (const op of normalizeImportedTableOps(tableOps)) {
|
|
5428
|
+
if (!isInsert5(op)) continue;
|
|
5429
|
+
if (op.attributes && Object.keys(op.attributes).length > 0) {
|
|
5430
|
+
delta.insert(op.insert, op.attributes);
|
|
5431
|
+
} else {
|
|
5432
|
+
delta.insert(op.insert);
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5245
5435
|
}
|
|
5246
5436
|
function isBlockLevelHtml(html) {
|
|
5247
5437
|
return /^\s*<(div|table|section|article|aside|nav|header|footer|figure|pre|hr|ol|ul|dl|details|iframe|video)\b/i.test(
|
|
@@ -5423,9 +5613,9 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
|
|
|
5423
5613
|
}
|
|
5424
5614
|
|
|
5425
5615
|
// src/conversion/markdown/table-region.ts
|
|
5426
|
-
import { isInsert as
|
|
5616
|
+
import { isInsert as isInsert6, isTextInsert as isTextInsert3 } from "@scrider/delta";
|
|
5427
5617
|
function isTableNewlineOp(op) {
|
|
5428
|
-
if (!op || !
|
|
5618
|
+
if (!op || !isInsert6(op) || !isTextInsert3(op)) return false;
|
|
5429
5619
|
if (!op.insert.includes("\n")) return false;
|
|
5430
5620
|
return !!op.attributes && "table-row" in op.attributes;
|
|
5431
5621
|
}
|
|
@@ -5434,7 +5624,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5434
5624
|
let probeIdx = -1;
|
|
5435
5625
|
for (let i = hintOpIdx; i < ops.length; i++) {
|
|
5436
5626
|
const op = ops[i];
|
|
5437
|
-
if (!op || !
|
|
5627
|
+
if (!op || !isInsert6(op)) continue;
|
|
5438
5628
|
if (isTextInsert3(op) && op.insert.includes("\n")) {
|
|
5439
5629
|
probeIdx = i;
|
|
5440
5630
|
break;
|
|
@@ -5445,7 +5635,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5445
5635
|
let endOpIdx = probeIdx;
|
|
5446
5636
|
for (let i = probeIdx + 1; i < ops.length; i++) {
|
|
5447
5637
|
const op = ops[i];
|
|
5448
|
-
if (!op || !
|
|
5638
|
+
if (!op || !isInsert6(op)) break;
|
|
5449
5639
|
if (isTextInsert3(op) && op.insert.includes("\n")) {
|
|
5450
5640
|
if (isTableNewlineOp(op)) {
|
|
5451
5641
|
endOpIdx = i;
|
|
@@ -5457,7 +5647,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5457
5647
|
let startOpIdx = 0;
|
|
5458
5648
|
for (let i = probeIdx - 1; i >= 0; i--) {
|
|
5459
5649
|
const op = ops[i];
|
|
5460
|
-
if (!op || !
|
|
5650
|
+
if (!op || !isInsert6(op)) {
|
|
5461
5651
|
startOpIdx = i + 1;
|
|
5462
5652
|
break;
|
|
5463
5653
|
}
|