@scrider/formatter 1.10.7 → 1.10.9

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.d.cts CHANGED
@@ -1077,6 +1077,9 @@ declare const alignFormat: Format<AlignType>;
1077
1077
  * Blockquote format
1078
1078
  *
1079
1079
  * Delta: { insert: "\n", attributes: { blockquote: true } }
1080
+ *
1081
+ * HTML render groups consecutive quote lines into one `<blockquote>` wrapping
1082
+ * inner `<p>`s. Delta stays per-line; grouping is render-only.
1080
1083
  */
1081
1084
  declare const blockquoteFormat: Format<boolean>;
1082
1085
 
package/dist/index.d.ts CHANGED
@@ -1077,6 +1077,9 @@ declare const alignFormat: Format<AlignType>;
1077
1077
  * Blockquote format
1078
1078
  *
1079
1079
  * Delta: { insert: "\n", attributes: { blockquote: true } }
1080
+ *
1081
+ * HTML render groups consecutive quote lines into one `<blockquote>` wrapping
1082
+ * inner `<p>`s. Delta stays per-line; grouping is render-only.
1080
1083
  */
1081
1084
  declare const blockquoteFormat: Format<boolean>;
1082
1085
 
package/dist/index.js CHANGED
@@ -3405,7 +3405,25 @@ function deltaToHtml(delta, options = {}) {
3405
3405
  i += tableLines.length - 1;
3406
3406
  continue;
3407
3407
  }
3408
- const { tag, isList, listType, indent, isCodeBlock } = getBlockInfo(line.attributes);
3408
+ const { tag, isList, listType, indent, isCodeBlock, isBlockquote } = getBlockInfo(
3409
+ line.attributes
3410
+ );
3411
+ if (isBlockquote) {
3412
+ html += closeAllLists(listStack, pretty);
3413
+ listStack = [];
3414
+ counters = [];
3415
+ const quoteLines = collectBlockquoteLines(lines, i);
3416
+ html += renderBlockquote(
3417
+ quoteLines,
3418
+ embedRenderers,
3419
+ pretty,
3420
+ blockHandlers,
3421
+ options,
3422
+ resolvedDocumentPresentation
3423
+ );
3424
+ i += quoteLines.length - 1;
3425
+ continue;
3426
+ }
3409
3427
  if (isCodeBlock) {
3410
3428
  html += closeAllLists(listStack, pretty);
3411
3429
  listStack = [];
@@ -3434,13 +3452,7 @@ function deltaToHtml(delta, options = {}) {
3434
3452
  continue;
3435
3453
  }
3436
3454
  if (isList) {
3437
- html += handleListOpen(
3438
- listStack,
3439
- listType,
3440
- indent,
3441
- pretty,
3442
- resolvedDocumentPresentation
3443
- );
3455
+ html += handleListOpen(listStack, listType, indent, pretty, resolvedDocumentPresentation);
3444
3456
  if (hierarchicalNumbers && listType === "ordered") {
3445
3457
  if (counters.length > indent + 1) {
3446
3458
  counters = counters.slice(0, indent + 1);
@@ -3673,24 +3685,90 @@ function renderTableRow(cells, maxCol, cellTag, embedRenderers, pretty, depth, b
3673
3685
  }
3674
3686
  function getBlockInfo(attributes) {
3675
3687
  if (!attributes) {
3676
- return { tag: "p", isList: false, isCodeBlock: false, listType: void 0, indent: 0 };
3688
+ return {
3689
+ tag: "p",
3690
+ isList: false,
3691
+ isCodeBlock: false,
3692
+ isBlockquote: false,
3693
+ listType: void 0,
3694
+ indent: 0
3695
+ };
3677
3696
  }
3678
3697
  const indent = typeof attributes.indent === "number" ? attributes.indent : 0;
3679
3698
  if (attributes["code-block"]) {
3680
- return { tag: "pre", isList: false, isCodeBlock: true, listType: void 0, indent };
3699
+ return {
3700
+ tag: "pre",
3701
+ isList: false,
3702
+ isCodeBlock: true,
3703
+ isBlockquote: false,
3704
+ listType: void 0,
3705
+ indent
3706
+ };
3681
3707
  }
3682
3708
  if (attributes.list) {
3683
3709
  const listVal = attributes.list;
3684
3710
  const listType = typeof listVal === "string" ? listVal : "bullet";
3685
- return { tag: "li", isList: true, isCodeBlock: false, listType, indent };
3711
+ return { tag: "li", isList: true, isCodeBlock: false, isBlockquote: false, listType, indent };
3712
+ }
3713
+ if (attributes.blockquote) {
3714
+ return {
3715
+ tag: "blockquote",
3716
+ isList: false,
3717
+ isCodeBlock: false,
3718
+ isBlockquote: true,
3719
+ listType: void 0,
3720
+ indent
3721
+ };
3686
3722
  }
3687
3723
  for (const [format, tagOrFn] of Object.entries(BLOCK_FORMAT_TAGS)) {
3688
3724
  if (format in attributes && format !== "list" && format !== "code-block") {
3689
3725
  const tag = typeof tagOrFn === "function" ? tagOrFn(attributes[format]) : tagOrFn;
3690
- return { tag, isList: false, isCodeBlock: false, listType: void 0, indent };
3726
+ return {
3727
+ tag,
3728
+ isList: false,
3729
+ isCodeBlock: false,
3730
+ isBlockquote: false,
3731
+ listType: void 0,
3732
+ indent
3733
+ };
3691
3734
  }
3692
3735
  }
3693
- return { tag: "p", isList: false, isCodeBlock: false, listType: void 0, indent };
3736
+ return {
3737
+ tag: "p",
3738
+ isList: false,
3739
+ isCodeBlock: false,
3740
+ isBlockquote: false,
3741
+ listType: void 0,
3742
+ indent
3743
+ };
3744
+ }
3745
+ function collectBlockquoteLines(lines, startIndex) {
3746
+ const quoteLines = [];
3747
+ for (let i = startIndex; i < lines.length; i++) {
3748
+ const line = lines[i];
3749
+ if (!line || !line.attributes?.blockquote) break;
3750
+ quoteLines.push(line);
3751
+ }
3752
+ return quoteLines;
3753
+ }
3754
+ function renderBlockquote(quoteLines, embedRenderers, pretty, blockHandlers, options, resolvedDocumentPresentation) {
3755
+ const firstAttrs = quoteLines[0]?.attributes;
3756
+ const wrapperIndent = firstAttrs && typeof firstAttrs.indent === "number" && firstAttrs.indent > 0 ? ` style="margin-left: ${firstAttrs.indent * 2}em"` : "";
3757
+ const nl = pretty ? "\n" : "";
3758
+ const innerIndent = pretty ? " " : "";
3759
+ let html = `<blockquote${wrapperIndent}>${nl}`;
3760
+ for (const line of quoteLines) {
3761
+ const content = renderLineContent(line.ops, embedRenderers, blockHandlers, options);
3762
+ html += `${innerIndent}${renderBlockquoteParagraph(content, line.attributes, resolvedDocumentPresentation)}${nl}`;
3763
+ }
3764
+ html += `</blockquote>`;
3765
+ return pretty ? html + "\n" : html;
3766
+ }
3767
+ function renderBlockquoteParagraph(content, attributes, resolvedDocumentPresentation) {
3768
+ const styleSource = attributes ? { ...attributes, indent: void 0 } : void 0;
3769
+ const styleAttr = getBlockStyleAttribute("blockquote", styleSource, resolvedDocumentPresentation);
3770
+ const innerContent = content || "<br>";
3771
+ return `<p${styleAttr}>${innerContent}</p>`;
3694
3772
  }
3695
3773
  function collectCodeBlockLines(lines, startIndex) {
3696
3774
  const codeLines = [];
@@ -3941,6 +4019,22 @@ function renderEmbed(value, attributes, renderers, blockHandlers, options) {
3941
4019
 
3942
4020
  // src/conversion/html/html-to-delta.ts
3943
4021
  import { Delta as Delta8 } from "@scrider/delta";
4022
+ var BLOCKQUOTE_INNER_BLOCK_TAGS = /* @__PURE__ */ new Set([
4023
+ "p",
4024
+ "div",
4025
+ "h1",
4026
+ "h2",
4027
+ "h3",
4028
+ "h4",
4029
+ "h5",
4030
+ "h6",
4031
+ "ul",
4032
+ "ol",
4033
+ "li",
4034
+ "pre",
4035
+ "blockquote",
4036
+ "table"
4037
+ ]);
3944
4038
  function isCssWideKeyword(value) {
3945
4039
  return /^(inherit|initial|unset|revert|revert-layer)$/i.test(value.trim());
3946
4040
  }
@@ -4040,6 +4134,12 @@ function htmlToDelta(html, options = {}) {
4040
4134
  pendingText = "";
4041
4135
  }
4042
4136
  }
4137
+ function beginBlockEmbedLine() {
4138
+ flushText();
4139
+ if (!atLineStart) {
4140
+ context.pushNewline();
4141
+ }
4142
+ }
4043
4143
  function processNode(node) {
4044
4144
  if (node.nodeType === NODE_TYPE.TEXT_NODE) {
4045
4145
  const text = node.textContent ?? "";
@@ -4187,9 +4287,21 @@ function htmlToDelta(html, options = {}) {
4187
4287
  }
4188
4288
  }
4189
4289
  processChildren(element);
4190
- context.pushNewline();
4290
+ if (!(format.format === "blockquote" && hasBlockChildElement(element))) {
4291
+ context.pushNewline();
4292
+ }
4191
4293
  currentBlockAttributes = prevBlockAttrs;
4192
4294
  }
4295
+ function hasBlockChildElement(element) {
4296
+ const children2 = element.childNodes;
4297
+ for (let i = 0; i < children2.length; i++) {
4298
+ const child = children2[i];
4299
+ if (!child || !isElement(child)) continue;
4300
+ const tag = child.tagName.toLowerCase();
4301
+ if (BLOCKQUOTE_INNER_BLOCK_TAGS.has(tag)) return true;
4302
+ }
4303
+ return false;
4304
+ }
4193
4305
  function processCodeBlockElement(element) {
4194
4306
  const prevBlockAttrs = { ...currentBlockAttributes };
4195
4307
  let language;
@@ -4406,7 +4518,7 @@ function htmlToDelta(html, options = {}) {
4406
4518
  };
4407
4519
  const data = footnotesHandler.fromHtml(section, blockContext);
4408
4520
  if (data) {
4409
- flushText();
4521
+ beginBlockEmbedLine();
4410
4522
  delta.insert({ block: data });
4411
4523
  delta.insert("\n");
4412
4524
  atLineStart = true;
@@ -4428,7 +4540,7 @@ function htmlToDelta(html, options = {}) {
4428
4540
  };
4429
4541
  const data = alertHandler.fromHtml(element, blockContext);
4430
4542
  if (data) {
4431
- flushText();
4543
+ beginBlockEmbedLine();
4432
4544
  delta.insert({ block: data });
4433
4545
  delta.insert("\n");
4434
4546
  atLineStart = true;
@@ -4450,7 +4562,7 @@ function htmlToDelta(html, options = {}) {
4450
4562
  };
4451
4563
  const data = columnsHandler.fromHtml(element, blockContext);
4452
4564
  if (data) {
4453
- flushText();
4565
+ beginBlockEmbedLine();
4454
4566
  delta.insert({ block: data });
4455
4567
  delta.insert("\n");
4456
4568
  atLineStart = true;
@@ -4472,7 +4584,7 @@ function htmlToDelta(html, options = {}) {
4472
4584
  };
4473
4585
  const data = boxHandler.fromHtml(element, blockContext);
4474
4586
  if (data) {
4475
- flushText();
4587
+ beginBlockEmbedLine();
4476
4588
  const opAttrs = {};
4477
4589
  const dataFloat = element.getAttribute("data-float");
4478
4590
  if (dataFloat) opAttrs.float = dataFloat;
@@ -4521,7 +4633,7 @@ function htmlToDelta(html, options = {}) {
4521
4633
  let data = tableHandler.fromHtml(table, makeTableBlockParseContext());
4522
4634
  if (!data) return false;
4523
4635
  if (host) data = enrichTableBlockFromHost(data, host);
4524
- flushText();
4636
+ beginBlockEmbedLine();
4525
4637
  delta.insert({ block: data });
4526
4638
  delta.insert("\n");
4527
4639
  atLineStart = true;