@reiwuzen/blocky 1.3.4 → 1.4.2

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 CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  applyMarkdownTransform: () => applyMarkdownTransform,
24
+ areBlocksSame: () => areBlocksSame,
24
25
  canRedo: () => canRedo,
25
26
  canUndo: () => canUndo,
26
27
  changeBlockType: () => changeBlockType,
@@ -36,6 +37,7 @@ __export(index_exports, {
36
37
  duplicateBlock: () => duplicateBlock,
37
38
  duplicateBlockAfter: () => duplicateBlockAfter,
38
39
  formatNodes: () => formatNodes,
40
+ formatParagraphBlock: () => stripPrefix,
39
41
  generateId: () => generateId,
40
42
  indentBlock: () => indentBlock,
41
43
  insertAt: () => insertAt,
@@ -619,18 +621,15 @@ function buildMetaForTarget(targetType) {
619
621
  case "number":
620
622
  case "todo":
621
623
  return { depth: 0 };
622
- case "heading1":
623
- case "heading2":
624
- case "heading3":
625
- case "paragraph":
626
- case "code":
627
- case "equation":
624
+ default:
628
625
  return {};
629
626
  }
630
627
  }
628
+ function isList(type) {
629
+ return type === "bullet" || type === "todo" || type === "number";
630
+ }
631
631
  function deriveMeta(block, targetType) {
632
- if (isList(block.type) && isList(targetType))
633
- return block.meta;
632
+ if (isList(block.type) && isList(targetType)) return block.meta;
634
633
  return buildMetaForTarget(targetType);
635
634
  }
636
635
  function toggleTodo(block) {
@@ -645,9 +644,6 @@ var MAX_DEPTH = 6;
645
644
  function isIndentable(block) {
646
645
  return block.type === "bullet" || block.type === "number" || block.type === "todo";
647
646
  }
648
- function isList(type) {
649
- return type === "bullet" || type === "todo" || type === "number";
650
- }
651
647
  function indentBlock(block) {
652
648
  if (!isIndentable(block))
653
649
  return import_result4.Result.Err(
@@ -671,6 +667,31 @@ function outdentBlock(block) {
671
667
  meta: { ...block.meta, depth: block.meta.depth - 1 }
672
668
  });
673
669
  }
670
+ function areBlocksSame(blocks, withBlocks) {
671
+ if (blocks.length !== withBlocks.length) return false;
672
+ return blocks.every((a, i) => {
673
+ const b = withBlocks[i];
674
+ if (a.type !== b.type) return false;
675
+ if (JSON.stringify(a.meta) !== JSON.stringify(b.meta)) return false;
676
+ if (a.content.length !== b.content.length) return false;
677
+ return a.content.every((an, j) => {
678
+ const bn = b.content[j];
679
+ if (an.type !== bn.type) return false;
680
+ switch (an.type) {
681
+ case "code":
682
+ return an.text === bn.text;
683
+ case "equation":
684
+ return an.latex === bn.latex;
685
+ case "text": {
686
+ const bt = bn;
687
+ return an.text === bt.text && an.bold === bt.bold && an.italic === bt.italic && an.underline === bt.underline && an.strikethrough === bt.strikethrough && an.highlighted === bt.highlighted && an.color === bt.color && an.link === bt.link;
688
+ }
689
+ default:
690
+ return false;
691
+ }
692
+ });
693
+ });
694
+ }
674
695
 
675
696
  // src/engine/serializer.ts
676
697
  var import_result5 = require("@reiwuzen/result");
@@ -769,6 +790,7 @@ function nodesToMarkdown(nodes) {
769
790
  return nodes.map((n) => {
770
791
  if (n.type === "code") return `\`${n.text}\``;
771
792
  if (n.type === "equation") return `$${n.latex}$`;
793
+ if (n.type === "ref") return `[${n.label}](${n.href})`;
772
794
  let text = n.text;
773
795
  if (n.bold) text = `**${text}**`;
774
796
  if (n.italic) text = `*${text}*`;
@@ -857,6 +879,7 @@ var currentBlocks = (history) => history.present.blocks;
857
879
  // Annotate the CommonJS export names for ESM import in node:
858
880
  0 && (module.exports = {
859
881
  applyMarkdownTransform,
882
+ areBlocksSame,
860
883
  canRedo,
861
884
  canUndo,
862
885
  changeBlockType,
@@ -872,6 +895,7 @@ var currentBlocks = (history) => history.present.blocks;
872
895
  duplicateBlock,
873
896
  duplicateBlockAfter,
874
897
  formatNodes,
898
+ formatParagraphBlock,
875
899
  generateId,
876
900
  indentBlock,
877
901
  insertAt,
package/dist/index.d.cts CHANGED
@@ -5,12 +5,16 @@ type Node = {
5
5
  type: "text";
6
6
  text: string;
7
7
  highlighted?: "yellow" | "green";
8
- color?: "red" | 'blue' | 'green';
8
+ color?: "red" | "blue" | "green";
9
9
  bold?: true;
10
10
  italic?: true;
11
11
  underline?: true;
12
12
  strikethrough?: true;
13
13
  link?: string;
14
+ } | {
15
+ type: "ref";
16
+ href: string;
17
+ label: string;
14
18
  } | {
15
19
  type: "code";
16
20
  text: string;
@@ -111,47 +115,99 @@ declare const removeLink: (nodes: Node[], sel: NodeSelection) => Result<Node[],
111
115
 
112
116
  type TransformResult = {
113
117
  block: AnyBlock;
118
+ /** true if the block type was actually changed, false if no trigger matched */
114
119
  converted: boolean;
115
120
  };
121
+ declare function stripPrefix(block: Block<"paragraph">, prefix: string): Block<"paragraph">["content"];
116
122
  /**
117
- * Call this when a space is typed.
123
+ * Attempt to convert a paragraph block into another type based on a
124
+ * Markdown-style prefix typed by the user.
125
+ *
126
+ * Call this when a **space** is typed inside a paragraph block.
127
+ *
128
+ * Supported triggers (must appear at position 0, immediately before the space):
129
+ *
130
+ * | Typed | Converts to |
131
+ * |----------|-------------|
132
+ * | `-` | bullet |
133
+ * | `1.` | number |
134
+ * | `[]` | todo |
135
+ * | `#` | heading1 |
136
+ * | `##` | heading2 |
137
+ * | `###` | heading3 |
118
138
  *
119
- * Guards (returns converted=false if any fail):
120
- * 1. block.type must be "paragraph"
121
- * 2. cursorOffset must be trigger.length + 1
122
- * ensures the space was typed right after the trigger at position 0
123
- * blocks mid-text spaces like "hello - " from converting
124
- * 3. text must start with a known trigger prefix
139
+ * Guards returns `converted: false` without mutating if any fail:
140
+ * 1. `block.type` must be `"paragraph"`
141
+ * 2. The text must start with a known trigger prefix
142
+ * 3. `cursorOffset` must be `trigger.length + 1` ensures the space
143
+ * was typed right after the trigger (blocks mid-text triggers like
144
+ * `"hello - "` from accidentally converting)
145
+ *
146
+ * On success the returned block has the trigger prefix stripped from its
147
+ * content and a freshly built `meta` for the target type.
125
148
  */
126
149
  declare function applyMarkdownTransform(block: AnyBlock, cursorOffset: number): Result<TransformResult>;
127
150
  /**
128
- * Convert a block to a new type while preserving content as much as possible.
151
+ * Convert a block to a new type, preserving content and meta where possible.
152
+ *
153
+ * Content conversion rules:
129
154
  *
130
- * rich rich keep content as-is, update type + meta
131
- * rich → code strip all formatting, concat all text → [CodeNode]
132
- * rich equation strip all formatting, concat all text → [EquationNode]
133
- * code rich single TextNode with code.text
134
- * equation rich single TextNode with equation.latex
135
- * code equation [EquationNode] with code.text as latex
136
- * equation code [CodeNode] with equation.latex as text
155
+ * | From | To | Content result |
156
+ * |-------------|-------------|----------------------------------------|
157
+ * | rich | rich | kept as-is |
158
+ * | rich | code | all text concatenated `[CodeNode]` |
159
+ * | rich | equation | all text concatenated `[EquationNode]`|
160
+ * | code | rich | `code.text` single `TextNode` |
161
+ * | equation | rich | `equation.latex` single `TextNode` |
162
+ * | code | equation | `code.text` as `latex` |
163
+ * | equation | code | `equation.latex` as `text` |
164
+ *
165
+ * Meta conversion rules:
166
+ * - list → list : `meta` (including `depth`) is preserved
167
+ * - anything else: fresh default `meta` is built for the target type
137
168
  */
138
169
  declare function changeBlockType<T extends BlockType>(block: AnyBlock, targetType: T): Result<Block<T>>;
139
170
  /**
140
171
  * Toggle the checked state of a todo block.
141
- * checked: undefined → checked: true → checked: undefined (cycle)
172
+ *
173
+ * Cycle: `undefined → true → undefined`
174
+ *
175
+ * Returns `Err` if the block is not of type `"todo"`.
142
176
  */
143
177
  declare function toggleTodo(block: AnyBlock): Result<Block<"todo">>;
144
178
  type IndentableBlock = Block<"bullet"> | Block<"number"> | Block<"todo">;
145
179
  /**
146
- * Increase the depth of a bullet, number, or todo block by 1.
147
- * Max depth is 6. Returns Err if block type is not indentable.
180
+ * Increase the indentation depth of a list block (`bullet`, `number`, `todo`) by 1.
181
+ *
182
+ * - Maximum depth is `6`.
183
+ * - Returns `Err` if the block type is not indentable or is already at max depth.
148
184
  */
149
185
  declare function indentBlock(block: AnyBlock): Result<IndentableBlock>;
150
186
  /**
151
- * Decrease the depth of a bullet, number, or todo block by 1.
152
- * Min depth is 0. Returns Err if block type is not indentable or already at 0.
187
+ * Decrease the indentation depth of a list block (`bullet`, `number`, `todo`) by 1.
188
+ *
189
+ * - Minimum depth is `0`.
190
+ * - Returns `Err` if the block type is not indentable or is already at depth 0.
153
191
  */
154
192
  declare function outdentBlock(block: AnyBlock): Result<IndentableBlock>;
193
+ /**
194
+ * Deep-equality check between two block arrays.
195
+ *
196
+ * Two arrays are considered the same when:
197
+ * - They have the same length
198
+ * - Every block at the same index has the same `id`, `type`, `meta`, and `content`
199
+ *
200
+ * Content nodes are compared field-by-field. Unknown extra fields on nodes are
201
+ * ignored so the check stays stable across schema additions.
202
+ *
203
+ * Useful for preventing redundant saves or snapshot writes:
204
+ * ```ts
205
+ * if (!areBlocksSame(current, saved)) {
206
+ * await createSnapshot(current);
207
+ * }
208
+ * ```
209
+ */
210
+ declare function areBlocksSame(blocks: AnyBlock[], withBlocks: AnyBlock[]): boolean;
155
211
 
156
212
  /**
157
213
  * Serialize an array of blocks to a JSON string.
@@ -267,4 +323,4 @@ declare function duplicateBlockAfter(blocks: AnyBlock[], id: string, newId?: str
267
323
  */
268
324
  declare function moveBlock(blocks: AnyBlock[], id: string, direction: "up" | "down"): Result<AnyBlock[], string>;
269
325
 
270
- export { type AnyBlock, type Block, type BlockContent, type BlockMeta, type BlockType, type History, type HistoryEntry, type Node, type NodeSelection, applyMarkdownTransform, canRedo, canUndo, changeBlockType, createBlock, createBlockAfter, createHistory, currentBlocks, deleteBlock, deleteLastChar, deleteRange, deserialize, deserializeNodes, duplicateBlock, duplicateBlockAfter, formatNodes, generateId, indentBlock, insertAt, insertBlockAfter, mergeAdjacentNodes, mergeBlocks, moveBlock, outdentBlock, push, redo, removeLink, replaceRange, serialize, serializeNodes, setLink, splitBlock, toMarkdown, toPlainText, toggleBold, toggleColor, toggleHighlight, toggleItalic, toggleStrikethrough, toggleTodo, toggleUnderline, undo };
326
+ export { type AnyBlock, type Block, type BlockContent, type BlockMeta, type BlockType, type History, type HistoryEntry, type Node, type NodeSelection, applyMarkdownTransform, areBlocksSame, canRedo, canUndo, changeBlockType, createBlock, createBlockAfter, createHistory, currentBlocks, deleteBlock, deleteLastChar, deleteRange, deserialize, deserializeNodes, duplicateBlock, duplicateBlockAfter, formatNodes, stripPrefix as formatParagraphBlock, generateId, indentBlock, insertAt, insertBlockAfter, mergeAdjacentNodes, mergeBlocks, moveBlock, outdentBlock, push, redo, removeLink, replaceRange, serialize, serializeNodes, setLink, splitBlock, toMarkdown, toPlainText, toggleBold, toggleColor, toggleHighlight, toggleItalic, toggleStrikethrough, toggleTodo, toggleUnderline, undo };
package/dist/index.d.ts CHANGED
@@ -5,12 +5,16 @@ type Node = {
5
5
  type: "text";
6
6
  text: string;
7
7
  highlighted?: "yellow" | "green";
8
- color?: "red" | 'blue' | 'green';
8
+ color?: "red" | "blue" | "green";
9
9
  bold?: true;
10
10
  italic?: true;
11
11
  underline?: true;
12
12
  strikethrough?: true;
13
13
  link?: string;
14
+ } | {
15
+ type: "ref";
16
+ href: string;
17
+ label: string;
14
18
  } | {
15
19
  type: "code";
16
20
  text: string;
@@ -111,47 +115,99 @@ declare const removeLink: (nodes: Node[], sel: NodeSelection) => Result<Node[],
111
115
 
112
116
  type TransformResult = {
113
117
  block: AnyBlock;
118
+ /** true if the block type was actually changed, false if no trigger matched */
114
119
  converted: boolean;
115
120
  };
121
+ declare function stripPrefix(block: Block<"paragraph">, prefix: string): Block<"paragraph">["content"];
116
122
  /**
117
- * Call this when a space is typed.
123
+ * Attempt to convert a paragraph block into another type based on a
124
+ * Markdown-style prefix typed by the user.
125
+ *
126
+ * Call this when a **space** is typed inside a paragraph block.
127
+ *
128
+ * Supported triggers (must appear at position 0, immediately before the space):
129
+ *
130
+ * | Typed | Converts to |
131
+ * |----------|-------------|
132
+ * | `-` | bullet |
133
+ * | `1.` | number |
134
+ * | `[]` | todo |
135
+ * | `#` | heading1 |
136
+ * | `##` | heading2 |
137
+ * | `###` | heading3 |
118
138
  *
119
- * Guards (returns converted=false if any fail):
120
- * 1. block.type must be "paragraph"
121
- * 2. cursorOffset must be trigger.length + 1
122
- * ensures the space was typed right after the trigger at position 0
123
- * blocks mid-text spaces like "hello - " from converting
124
- * 3. text must start with a known trigger prefix
139
+ * Guards returns `converted: false` without mutating if any fail:
140
+ * 1. `block.type` must be `"paragraph"`
141
+ * 2. The text must start with a known trigger prefix
142
+ * 3. `cursorOffset` must be `trigger.length + 1` ensures the space
143
+ * was typed right after the trigger (blocks mid-text triggers like
144
+ * `"hello - "` from accidentally converting)
145
+ *
146
+ * On success the returned block has the trigger prefix stripped from its
147
+ * content and a freshly built `meta` for the target type.
125
148
  */
126
149
  declare function applyMarkdownTransform(block: AnyBlock, cursorOffset: number): Result<TransformResult>;
127
150
  /**
128
- * Convert a block to a new type while preserving content as much as possible.
151
+ * Convert a block to a new type, preserving content and meta where possible.
152
+ *
153
+ * Content conversion rules:
129
154
  *
130
- * rich rich keep content as-is, update type + meta
131
- * rich → code strip all formatting, concat all text → [CodeNode]
132
- * rich equation strip all formatting, concat all text → [EquationNode]
133
- * code rich single TextNode with code.text
134
- * equation rich single TextNode with equation.latex
135
- * code equation [EquationNode] with code.text as latex
136
- * equation code [CodeNode] with equation.latex as text
155
+ * | From | To | Content result |
156
+ * |-------------|-------------|----------------------------------------|
157
+ * | rich | rich | kept as-is |
158
+ * | rich | code | all text concatenated `[CodeNode]` |
159
+ * | rich | equation | all text concatenated `[EquationNode]`|
160
+ * | code | rich | `code.text` single `TextNode` |
161
+ * | equation | rich | `equation.latex` single `TextNode` |
162
+ * | code | equation | `code.text` as `latex` |
163
+ * | equation | code | `equation.latex` as `text` |
164
+ *
165
+ * Meta conversion rules:
166
+ * - list → list : `meta` (including `depth`) is preserved
167
+ * - anything else: fresh default `meta` is built for the target type
137
168
  */
138
169
  declare function changeBlockType<T extends BlockType>(block: AnyBlock, targetType: T): Result<Block<T>>;
139
170
  /**
140
171
  * Toggle the checked state of a todo block.
141
- * checked: undefined → checked: true → checked: undefined (cycle)
172
+ *
173
+ * Cycle: `undefined → true → undefined`
174
+ *
175
+ * Returns `Err` if the block is not of type `"todo"`.
142
176
  */
143
177
  declare function toggleTodo(block: AnyBlock): Result<Block<"todo">>;
144
178
  type IndentableBlock = Block<"bullet"> | Block<"number"> | Block<"todo">;
145
179
  /**
146
- * Increase the depth of a bullet, number, or todo block by 1.
147
- * Max depth is 6. Returns Err if block type is not indentable.
180
+ * Increase the indentation depth of a list block (`bullet`, `number`, `todo`) by 1.
181
+ *
182
+ * - Maximum depth is `6`.
183
+ * - Returns `Err` if the block type is not indentable or is already at max depth.
148
184
  */
149
185
  declare function indentBlock(block: AnyBlock): Result<IndentableBlock>;
150
186
  /**
151
- * Decrease the depth of a bullet, number, or todo block by 1.
152
- * Min depth is 0. Returns Err if block type is not indentable or already at 0.
187
+ * Decrease the indentation depth of a list block (`bullet`, `number`, `todo`) by 1.
188
+ *
189
+ * - Minimum depth is `0`.
190
+ * - Returns `Err` if the block type is not indentable or is already at depth 0.
153
191
  */
154
192
  declare function outdentBlock(block: AnyBlock): Result<IndentableBlock>;
193
+ /**
194
+ * Deep-equality check between two block arrays.
195
+ *
196
+ * Two arrays are considered the same when:
197
+ * - They have the same length
198
+ * - Every block at the same index has the same `id`, `type`, `meta`, and `content`
199
+ *
200
+ * Content nodes are compared field-by-field. Unknown extra fields on nodes are
201
+ * ignored so the check stays stable across schema additions.
202
+ *
203
+ * Useful for preventing redundant saves or snapshot writes:
204
+ * ```ts
205
+ * if (!areBlocksSame(current, saved)) {
206
+ * await createSnapshot(current);
207
+ * }
208
+ * ```
209
+ */
210
+ declare function areBlocksSame(blocks: AnyBlock[], withBlocks: AnyBlock[]): boolean;
155
211
 
156
212
  /**
157
213
  * Serialize an array of blocks to a JSON string.
@@ -267,4 +323,4 @@ declare function duplicateBlockAfter(blocks: AnyBlock[], id: string, newId?: str
267
323
  */
268
324
  declare function moveBlock(blocks: AnyBlock[], id: string, direction: "up" | "down"): Result<AnyBlock[], string>;
269
325
 
270
- export { type AnyBlock, type Block, type BlockContent, type BlockMeta, type BlockType, type History, type HistoryEntry, type Node, type NodeSelection, applyMarkdownTransform, canRedo, canUndo, changeBlockType, createBlock, createBlockAfter, createHistory, currentBlocks, deleteBlock, deleteLastChar, deleteRange, deserialize, deserializeNodes, duplicateBlock, duplicateBlockAfter, formatNodes, generateId, indentBlock, insertAt, insertBlockAfter, mergeAdjacentNodes, mergeBlocks, moveBlock, outdentBlock, push, redo, removeLink, replaceRange, serialize, serializeNodes, setLink, splitBlock, toMarkdown, toPlainText, toggleBold, toggleColor, toggleHighlight, toggleItalic, toggleStrikethrough, toggleTodo, toggleUnderline, undo };
326
+ export { type AnyBlock, type Block, type BlockContent, type BlockMeta, type BlockType, type History, type HistoryEntry, type Node, type NodeSelection, applyMarkdownTransform, areBlocksSame, canRedo, canUndo, changeBlockType, createBlock, createBlockAfter, createHistory, currentBlocks, deleteBlock, deleteLastChar, deleteRange, deserialize, deserializeNodes, duplicateBlock, duplicateBlockAfter, formatNodes, stripPrefix as formatParagraphBlock, generateId, indentBlock, insertAt, insertBlockAfter, mergeAdjacentNodes, mergeBlocks, moveBlock, outdentBlock, push, redo, removeLink, replaceRange, serialize, serializeNodes, setLink, splitBlock, toMarkdown, toPlainText, toggleBold, toggleColor, toggleHighlight, toggleItalic, toggleStrikethrough, toggleTodo, toggleUnderline, undo };
package/dist/index.js CHANGED
@@ -552,18 +552,15 @@ function buildMetaForTarget(targetType) {
552
552
  case "number":
553
553
  case "todo":
554
554
  return { depth: 0 };
555
- case "heading1":
556
- case "heading2":
557
- case "heading3":
558
- case "paragraph":
559
- case "code":
560
- case "equation":
555
+ default:
561
556
  return {};
562
557
  }
563
558
  }
559
+ function isList(type) {
560
+ return type === "bullet" || type === "todo" || type === "number";
561
+ }
564
562
  function deriveMeta(block, targetType) {
565
- if (isList(block.type) && isList(targetType))
566
- return block.meta;
563
+ if (isList(block.type) && isList(targetType)) return block.meta;
567
564
  return buildMetaForTarget(targetType);
568
565
  }
569
566
  function toggleTodo(block) {
@@ -578,9 +575,6 @@ var MAX_DEPTH = 6;
578
575
  function isIndentable(block) {
579
576
  return block.type === "bullet" || block.type === "number" || block.type === "todo";
580
577
  }
581
- function isList(type) {
582
- return type === "bullet" || type === "todo" || type === "number";
583
- }
584
578
  function indentBlock(block) {
585
579
  if (!isIndentable(block))
586
580
  return Result4.Err(
@@ -604,6 +598,31 @@ function outdentBlock(block) {
604
598
  meta: { ...block.meta, depth: block.meta.depth - 1 }
605
599
  });
606
600
  }
601
+ function areBlocksSame(blocks, withBlocks) {
602
+ if (blocks.length !== withBlocks.length) return false;
603
+ return blocks.every((a, i) => {
604
+ const b = withBlocks[i];
605
+ if (a.type !== b.type) return false;
606
+ if (JSON.stringify(a.meta) !== JSON.stringify(b.meta)) return false;
607
+ if (a.content.length !== b.content.length) return false;
608
+ return a.content.every((an, j) => {
609
+ const bn = b.content[j];
610
+ if (an.type !== bn.type) return false;
611
+ switch (an.type) {
612
+ case "code":
613
+ return an.text === bn.text;
614
+ case "equation":
615
+ return an.latex === bn.latex;
616
+ case "text": {
617
+ const bt = bn;
618
+ return an.text === bt.text && an.bold === bt.bold && an.italic === bt.italic && an.underline === bt.underline && an.strikethrough === bt.strikethrough && an.highlighted === bt.highlighted && an.color === bt.color && an.link === bt.link;
619
+ }
620
+ default:
621
+ return false;
622
+ }
623
+ });
624
+ });
625
+ }
607
626
 
608
627
  // src/engine/serializer.ts
609
628
  import { Result as Result5 } from "@reiwuzen/result";
@@ -702,6 +721,7 @@ function nodesToMarkdown(nodes) {
702
721
  return nodes.map((n) => {
703
722
  if (n.type === "code") return `\`${n.text}\``;
704
723
  if (n.type === "equation") return `$${n.latex}$`;
724
+ if (n.type === "ref") return `[${n.label}](${n.href})`;
705
725
  let text = n.text;
706
726
  if (n.bold) text = `**${text}**`;
707
727
  if (n.italic) text = `*${text}*`;
@@ -789,6 +809,7 @@ var canRedo = (history) => history.future.length > 0;
789
809
  var currentBlocks = (history) => history.present.blocks;
790
810
  export {
791
811
  applyMarkdownTransform,
812
+ areBlocksSame,
792
813
  canRedo,
793
814
  canUndo,
794
815
  changeBlockType,
@@ -804,6 +825,7 @@ export {
804
825
  duplicateBlock,
805
826
  duplicateBlockAfter,
806
827
  formatNodes,
828
+ stripPrefix as formatParagraphBlock,
807
829
  generateId,
808
830
  indentBlock,
809
831
  insertAt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reiwuzen/blocky",
3
- "version": "1.3.4",
3
+ "version": "1.4.2",
4
4
  "description": "Pure TypeScript block editor engine. Headless, framework-agnostic — content mutation, formatting, transforms, serialization, and history.",
5
5
  "author": "Rei WuZen",
6
6
  "license": "ISC",