@scrider/formatter 1.10.8 → 1.10.10

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
@@ -405,6 +405,9 @@ var LIST_WRAPPER_TAGS = {
405
405
  checked: "ul",
406
406
  unchecked: "ul"
407
407
  };
408
+ function listWrapperFamily(listType) {
409
+ return LIST_WRAPPER_TAGS[listType] || "ul";
410
+ }
408
411
  var EMBED_RENDERERS = {
409
412
  image: (value, attrs) => {
410
413
  const src = typeof value === "string" ? value : "";
@@ -3405,7 +3408,25 @@ function deltaToHtml(delta, options = {}) {
3405
3408
  i += tableLines.length - 1;
3406
3409
  continue;
3407
3410
  }
3408
- const { tag, isList, listType, indent, isCodeBlock } = getBlockInfo(line.attributes);
3411
+ const { tag, isList, listType, indent, isCodeBlock, isBlockquote } = getBlockInfo(
3412
+ line.attributes
3413
+ );
3414
+ if (isBlockquote) {
3415
+ html += closeAllLists(listStack, pretty);
3416
+ listStack = [];
3417
+ counters = [];
3418
+ const quoteLines = collectBlockquoteLines(lines, i);
3419
+ html += renderBlockquote(
3420
+ quoteLines,
3421
+ embedRenderers,
3422
+ pretty,
3423
+ blockHandlers,
3424
+ options,
3425
+ resolvedDocumentPresentation
3426
+ );
3427
+ i += quoteLines.length - 1;
3428
+ continue;
3429
+ }
3409
3430
  if (isCodeBlock) {
3410
3431
  html += closeAllLists(listStack, pretty);
3411
3432
  listStack = [];
@@ -3434,13 +3455,7 @@ function deltaToHtml(delta, options = {}) {
3434
3455
  continue;
3435
3456
  }
3436
3457
  if (isList) {
3437
- html += handleListOpen(
3438
- listStack,
3439
- listType,
3440
- indent,
3441
- pretty,
3442
- resolvedDocumentPresentation
3443
- );
3458
+ html += handleListOpen(listStack, listType, indent, pretty, resolvedDocumentPresentation);
3444
3459
  if (hierarchicalNumbers && listType === "ordered") {
3445
3460
  if (counters.length > indent + 1) {
3446
3461
  counters = counters.slice(0, indent + 1);
@@ -3673,24 +3688,90 @@ function renderTableRow(cells, maxCol, cellTag, embedRenderers, pretty, depth, b
3673
3688
  }
3674
3689
  function getBlockInfo(attributes) {
3675
3690
  if (!attributes) {
3676
- return { tag: "p", isList: false, isCodeBlock: false, listType: void 0, indent: 0 };
3691
+ return {
3692
+ tag: "p",
3693
+ isList: false,
3694
+ isCodeBlock: false,
3695
+ isBlockquote: false,
3696
+ listType: void 0,
3697
+ indent: 0
3698
+ };
3677
3699
  }
3678
3700
  const indent = typeof attributes.indent === "number" ? attributes.indent : 0;
3679
3701
  if (attributes["code-block"]) {
3680
- return { tag: "pre", isList: false, isCodeBlock: true, listType: void 0, indent };
3702
+ return {
3703
+ tag: "pre",
3704
+ isList: false,
3705
+ isCodeBlock: true,
3706
+ isBlockquote: false,
3707
+ listType: void 0,
3708
+ indent
3709
+ };
3681
3710
  }
3682
3711
  if (attributes.list) {
3683
3712
  const listVal = attributes.list;
3684
3713
  const listType = typeof listVal === "string" ? listVal : "bullet";
3685
- return { tag: "li", isList: true, isCodeBlock: false, listType, indent };
3714
+ return { tag: "li", isList: true, isCodeBlock: false, isBlockquote: false, listType, indent };
3715
+ }
3716
+ if (attributes.blockquote) {
3717
+ return {
3718
+ tag: "blockquote",
3719
+ isList: false,
3720
+ isCodeBlock: false,
3721
+ isBlockquote: true,
3722
+ listType: void 0,
3723
+ indent
3724
+ };
3686
3725
  }
3687
3726
  for (const [format, tagOrFn] of Object.entries(BLOCK_FORMAT_TAGS)) {
3688
3727
  if (format in attributes && format !== "list" && format !== "code-block") {
3689
3728
  const tag = typeof tagOrFn === "function" ? tagOrFn(attributes[format]) : tagOrFn;
3690
- return { tag, isList: false, isCodeBlock: false, listType: void 0, indent };
3729
+ return {
3730
+ tag,
3731
+ isList: false,
3732
+ isCodeBlock: false,
3733
+ isBlockquote: false,
3734
+ listType: void 0,
3735
+ indent
3736
+ };
3691
3737
  }
3692
3738
  }
3693
- return { tag: "p", isList: false, isCodeBlock: false, listType: void 0, indent };
3739
+ return {
3740
+ tag: "p",
3741
+ isList: false,
3742
+ isCodeBlock: false,
3743
+ isBlockquote: false,
3744
+ listType: void 0,
3745
+ indent
3746
+ };
3747
+ }
3748
+ function collectBlockquoteLines(lines, startIndex) {
3749
+ const quoteLines = [];
3750
+ for (let i = startIndex; i < lines.length; i++) {
3751
+ const line = lines[i];
3752
+ if (!line || !line.attributes?.blockquote) break;
3753
+ quoteLines.push(line);
3754
+ }
3755
+ return quoteLines;
3756
+ }
3757
+ function renderBlockquote(quoteLines, embedRenderers, pretty, blockHandlers, options, resolvedDocumentPresentation) {
3758
+ const firstAttrs = quoteLines[0]?.attributes;
3759
+ const wrapperIndent = firstAttrs && typeof firstAttrs.indent === "number" && firstAttrs.indent > 0 ? ` style="margin-left: ${firstAttrs.indent * 2}em"` : "";
3760
+ const nl = pretty ? "\n" : "";
3761
+ const innerIndent = pretty ? " " : "";
3762
+ let html = `<blockquote${wrapperIndent}>${nl}`;
3763
+ for (const line of quoteLines) {
3764
+ const content = renderLineContent(line.ops, embedRenderers, blockHandlers, options);
3765
+ html += `${innerIndent}${renderBlockquoteParagraph(content, line.attributes, resolvedDocumentPresentation)}${nl}`;
3766
+ }
3767
+ html += `</blockquote>`;
3768
+ return pretty ? html + "\n" : html;
3769
+ }
3770
+ function renderBlockquoteParagraph(content, attributes, resolvedDocumentPresentation) {
3771
+ const styleSource = attributes ? { ...attributes, indent: void 0 } : void 0;
3772
+ const styleAttr = getBlockStyleAttribute("blockquote", styleSource, resolvedDocumentPresentation);
3773
+ const innerContent = content || "<br>";
3774
+ return `<p${styleAttr}>${innerContent}</p>`;
3694
3775
  }
3695
3776
  function collectCodeBlockLines(lines, startIndex) {
3696
3777
  const codeLines = [];
@@ -3752,7 +3833,7 @@ function handleListOpen(stack, listType, indent, pretty, resolvedDocumentPresent
3752
3833
  }
3753
3834
  }
3754
3835
  const top = stack[stack.length - 1];
3755
- if (top && top.indent === indent && top.type !== listType) {
3836
+ if (top && top.indent === indent && listWrapperFamily(top.type) !== listWrapperFamily(listType)) {
3756
3837
  const closed = stack.pop();
3757
3838
  if (closed) {
3758
3839
  const closeTag = LIST_WRAPPER_TAGS[closed.type] || "ul";
@@ -3941,6 +4022,22 @@ function renderEmbed(value, attributes, renderers, blockHandlers, options) {
3941
4022
 
3942
4023
  // src/conversion/html/html-to-delta.ts
3943
4024
  import { Delta as Delta8 } from "@scrider/delta";
4025
+ var BLOCKQUOTE_INNER_BLOCK_TAGS = /* @__PURE__ */ new Set([
4026
+ "p",
4027
+ "div",
4028
+ "h1",
4029
+ "h2",
4030
+ "h3",
4031
+ "h4",
4032
+ "h5",
4033
+ "h6",
4034
+ "ul",
4035
+ "ol",
4036
+ "li",
4037
+ "pre",
4038
+ "blockquote",
4039
+ "table"
4040
+ ]);
3944
4041
  function isCssWideKeyword(value) {
3945
4042
  return /^(inherit|initial|unset|revert|revert-layer)$/i.test(value.trim());
3946
4043
  }
@@ -4193,9 +4290,21 @@ function htmlToDelta(html, options = {}) {
4193
4290
  }
4194
4291
  }
4195
4292
  processChildren(element);
4196
- context.pushNewline();
4293
+ if (!(format.format === "blockquote" && hasBlockChildElement(element))) {
4294
+ context.pushNewline();
4295
+ }
4197
4296
  currentBlockAttributes = prevBlockAttrs;
4198
4297
  }
4298
+ function hasBlockChildElement(element) {
4299
+ const children2 = element.childNodes;
4300
+ for (let i = 0; i < children2.length; i++) {
4301
+ const child = children2[i];
4302
+ if (!child || !isElement(child)) continue;
4303
+ const tag = child.tagName.toLowerCase();
4304
+ if (BLOCKQUOTE_INNER_BLOCK_TAGS.has(tag)) return true;
4305
+ }
4306
+ return false;
4307
+ }
4199
4308
  function processCodeBlockElement(element) {
4200
4309
  const prevBlockAttrs = { ...currentBlockAttributes };
4201
4310
  let language;