@tiptap/extension-list 3.26.0 → 3.27.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.
@@ -20,23 +20,229 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/ordered-list/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ORDERED_LIST_MARKER_PATTERN: () => ORDERED_LIST_MARKER_PATTERN,
23
24
  OrderedList: () => OrderedList,
24
- orderedListInputRegex: () => orderedListInputRegex
25
+ areOrderedListMarkersSequential: () => areOrderedListMarkersSequential,
26
+ buildOrderedListAttrsFromMarker: () => buildOrderedListAttrsFromMarker,
27
+ detectMarkerType: () => detectMarkerType,
28
+ getListMarker: () => getListMarker,
29
+ markerToStart: () => markerToStart,
30
+ orderedListInputRegex: () => orderedListInputRegex,
31
+ parseListMarker: () => parseListMarker,
32
+ parsePlainTextOrderedListPaste: () => parsePlainTextOrderedListPaste,
33
+ toRoman: () => toRoman,
34
+ toRomanUpper: () => toRomanUpper
25
35
  });
26
36
  module.exports = __toCommonJS(index_exports);
27
37
 
28
38
  // src/ordered-list/ordered-list.ts
39
+ var import_state = require("@tiptap/pm/state");
29
40
  var import_core = require("@tiptap/core");
30
41
 
42
+ // src/ordered-list/roman.ts
43
+ var ROMAN_NUMERALS = [
44
+ [1e3, "m"],
45
+ [900, "cm"],
46
+ [500, "d"],
47
+ [400, "cd"],
48
+ [100, "c"],
49
+ [90, "xc"],
50
+ [50, "l"],
51
+ [40, "xl"],
52
+ [10, "x"],
53
+ [9, "ix"],
54
+ [5, "v"],
55
+ [4, "iv"],
56
+ [1, "i"]
57
+ ];
58
+ var ALPHA_NUMERALS = "abcdefghijklmnopqrstuvwxyz";
59
+ var ORDERED_LIST_ALPHA_MARKER_PATTERN = "[a-zA-Z]{1,2}";
60
+ var ORDERED_LIST_MARKER_PATTERN = String.raw`\d+|[ivxlcdmIVXLCDM]+|${ORDERED_LIST_ALPHA_MARKER_PATTERN}`;
61
+ function toRoman(num) {
62
+ let remaining = num;
63
+ let result = "";
64
+ for (const [value, numeral] of ROMAN_NUMERALS) {
65
+ while (remaining >= value) {
66
+ result += numeral;
67
+ remaining -= value;
68
+ }
69
+ }
70
+ return result;
71
+ }
72
+ function toRomanUpper(num) {
73
+ return toRoman(num).toUpperCase();
74
+ }
75
+ function fromRoman(roman) {
76
+ const lower = roman.toLowerCase();
77
+ let index = 0;
78
+ let result = 0;
79
+ while (index < lower.length) {
80
+ let matched = false;
81
+ for (const [value, numeral] of ROMAN_NUMERALS) {
82
+ if (lower.startsWith(numeral, index)) {
83
+ result += value;
84
+ index += numeral.length;
85
+ matched = true;
86
+ break;
87
+ }
88
+ }
89
+ if (!matched) {
90
+ return 0;
91
+ }
92
+ }
93
+ return result;
94
+ }
95
+ function isValidRoman(marker) {
96
+ if (!/^[ivxlcdmIVXLCDM]+$/.test(marker)) {
97
+ return false;
98
+ }
99
+ const value = fromRoman(marker);
100
+ if (value <= 0) {
101
+ return false;
102
+ }
103
+ const expected = marker === marker.toLowerCase() ? toRoman(value) : toRomanUpper(value);
104
+ return expected === marker;
105
+ }
106
+ function fromAlpha(marker) {
107
+ const lower = marker.toLowerCase();
108
+ if (lower.length === 1) {
109
+ return lower.charCodeAt(0) - "a".charCodeAt(0) + 1;
110
+ }
111
+ if (lower.length === 2) {
112
+ const first = lower.charCodeAt(0) - "a".charCodeAt(0);
113
+ const second = lower.charCodeAt(1) - "a".charCodeAt(0);
114
+ return (first + 1) * 26 + second + 1;
115
+ }
116
+ return 0;
117
+ }
118
+ function toRomanAlpha(num) {
119
+ if (num <= 26) {
120
+ return ALPHA_NUMERALS[num - 1];
121
+ }
122
+ const first = Math.floor((num - 1) / 26) - 1;
123
+ const second = (num - 1) % 26;
124
+ if (first < 0) {
125
+ return ALPHA_NUMERALS[second];
126
+ }
127
+ return ALPHA_NUMERALS[first] + ALPHA_NUMERALS[second];
128
+ }
129
+ function detectMarkerType(marker) {
130
+ if (!marker || /^\d+$/.test(marker)) {
131
+ return void 0;
132
+ }
133
+ if (isValidRoman(marker)) {
134
+ return marker === marker.toLowerCase() ? "i" : "I";
135
+ }
136
+ if (/^[a-z]{1,2}$/.test(marker)) {
137
+ return "a";
138
+ }
139
+ if (/^[A-Z]{1,2}$/.test(marker)) {
140
+ return "A";
141
+ }
142
+ return void 0;
143
+ }
144
+ function markerToStart(marker) {
145
+ if (/^\d+$/.test(marker)) {
146
+ return parseInt(marker, 10);
147
+ }
148
+ const type = detectMarkerType(marker);
149
+ if (type === "i" || type === "I") {
150
+ return fromRoman(marker);
151
+ }
152
+ if (type === "a" || type === "A") {
153
+ const start = fromAlpha(marker);
154
+ return start > 0 ? start : 1;
155
+ }
156
+ const parsed = parseInt(marker, 10);
157
+ return Number.isNaN(parsed) ? 1 : parsed;
158
+ }
159
+ function startToMarker(type, start) {
160
+ if (type === "numeric") {
161
+ return String(start);
162
+ }
163
+ switch (type) {
164
+ case "a":
165
+ return toRomanAlpha(start);
166
+ case "A":
167
+ return toRomanAlpha(start).toUpperCase();
168
+ case "i":
169
+ return toRoman(start);
170
+ case "I":
171
+ return toRomanUpper(start);
172
+ default:
173
+ return String(start);
174
+ }
175
+ }
176
+ function areOrderedListMarkersSequential(markers) {
177
+ var _a;
178
+ if (markers.length === 0) {
179
+ return false;
180
+ }
181
+ const firstType = (_a = detectMarkerType(markers[0])) != null ? _a : "numeric";
182
+ const firstStart = markerToStart(markers[0]);
183
+ if (firstStart < 1) {
184
+ return false;
185
+ }
186
+ for (let i = 0; i < markers.length; i++) {
187
+ const expected = startToMarker(firstType, firstStart + i);
188
+ if (markers[i] !== expected) {
189
+ return false;
190
+ }
191
+ }
192
+ return true;
193
+ }
194
+ function parseListMarker(marker) {
195
+ return {
196
+ type: detectMarkerType(marker),
197
+ start: markerToStart(marker)
198
+ };
199
+ }
200
+ function buildOrderedListAttrsFromMarker(marker) {
201
+ const { type, start } = parseListMarker(marker);
202
+ const attrs = {};
203
+ if (type) {
204
+ attrs.type = type;
205
+ }
206
+ if (start !== 1) {
207
+ attrs.start = start;
208
+ }
209
+ return attrs;
210
+ }
211
+ function getListMarker(type, index, separator = ". ") {
212
+ const position = index + 1;
213
+ if (!type || type === "1") {
214
+ return `${position}${separator}`;
215
+ }
216
+ switch (type) {
217
+ case "a":
218
+ return `${toRomanAlpha(position)}${separator}`;
219
+ case "A":
220
+ return `${toRomanAlpha(position).toUpperCase()}${separator}`;
221
+ case "i":
222
+ return `${toRoman(position)}${separator}`;
223
+ case "I":
224
+ return `${toRomanUpper(position)}${separator}`;
225
+ default:
226
+ return `${position}${separator}`;
227
+ }
228
+ }
229
+
31
230
  // src/ordered-list/utils.ts
32
- var ORDERED_LIST_ITEM_REGEX = /^(\s*)(\d+)\.\s+(.*)$/;
231
+ var ORDERED_LIST_ITEM_REGEX = new RegExp(
232
+ `^(\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+(.*)$`
233
+ );
234
+ var ORDERED_LIST_LINE_START_REGEX = new RegExp(
235
+ `^(\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+`
236
+ );
33
237
  var INDENTED_LINE_REGEX = /^\s/;
238
+ function isOrderedListMarkerLine(line) {
239
+ return ORDERED_LIST_ITEM_REGEX.test(line.trimStart());
240
+ }
34
241
  function isBlockContentLine(line) {
35
242
  const trimmedLine = line.trimStart();
36
243
  return (
37
244
  // oxlint-disable-next-line prefer-string-starts-ends-with
38
- /^[-+*]\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
39
- /^\d+\.\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
245
+ /^[-+*]\s+/.test(trimmedLine) || isOrderedListMarkerLine(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
40
246
  /^>\s?/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
41
247
  /^```/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
42
248
  /^~~~/.test(trimmedLine)
@@ -78,8 +284,11 @@ function collectOrderedListItems(lines) {
78
284
  if (!match) {
79
285
  break;
80
286
  }
81
- const [, indent, number, content] = match;
287
+ const [, indent, marker, _separator, content] = match;
82
288
  const indentLevel = indent.length;
289
+ const number = parseInt(marker, 10);
290
+ const markerType = isNaN(number) ? detectMarkerType(marker) : void 0;
291
+ const itemNumber = isNaN(number) ? markerToStart(marker) : number;
83
292
  const itemContentLines = [content];
84
293
  let nextLineIndex = currentLineIndex + 1;
85
294
  const itemLines = [line];
@@ -110,7 +319,8 @@ function collectOrderedListItems(lines) {
110
319
  }
111
320
  listItems.push({
112
321
  indent: indentLevel,
113
- number: parseInt(number, 10),
322
+ number: itemNumber,
323
+ type: markerType,
114
324
  content: itemContentLines.join("\n").trim(),
115
325
  contentLines: itemContentLines,
116
326
  raw: itemLines.join("\n")
@@ -120,6 +330,44 @@ function collectOrderedListItems(lines) {
120
330
  }
121
331
  return [listItems, consumed];
122
332
  }
333
+ var PLAIN_TEXT_ORDERED_LIST_LINE_REGEX = new RegExp(
334
+ `^(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+(.+)$`
335
+ );
336
+ function parsePlainTextOrderedListPaste(text) {
337
+ const lines = text.split("\n").filter((l) => l.trim().length > 0);
338
+ if (lines.length === 0) {
339
+ return null;
340
+ }
341
+ const parsedItems = [];
342
+ for (const line of lines) {
343
+ const match = line.trim().match(PLAIN_TEXT_ORDERED_LIST_LINE_REGEX);
344
+ if (!match) {
345
+ return null;
346
+ }
347
+ parsedItems.push({
348
+ marker: match[1],
349
+ content: match[3]
350
+ });
351
+ }
352
+ const markers = parsedItems.map((item) => item.marker);
353
+ if (!areOrderedListMarkersSequential(markers)) {
354
+ return null;
355
+ }
356
+ const attrs = buildOrderedListAttrsFromMarker(parsedItems[0].marker);
357
+ return {
358
+ type: "orderedList",
359
+ attrs,
360
+ content: parsedItems.map((item) => ({
361
+ type: "listItem",
362
+ content: [
363
+ {
364
+ type: "paragraph",
365
+ content: [{ type: "text", text: item.content }]
366
+ }
367
+ ]
368
+ }))
369
+ };
370
+ }
123
371
  function buildNestedStructure(items, baseIndent, lexer) {
124
372
  const result = [];
125
373
  let currentIndex = 0;
@@ -154,6 +402,7 @@ function buildNestedStructure(items, baseIndent, lexer) {
154
402
  type: "list",
155
403
  ordered: true,
156
404
  start: nestedItems[0].number,
405
+ typeMarker: nestedItems[0].type,
157
406
  items: nestedListItems,
158
407
  raw: nestedItems.map((nestedItem) => nestedItem.raw).join("\n")
159
408
  });
@@ -205,6 +454,27 @@ function parseListItems(items, helpers) {
205
454
  var ListItemName = "listItem";
206
455
  var TextStyleName = "textStyle";
207
456
  var orderedListInputRegex = /^(\d+)\.\s$/;
457
+ function cssListStyleTypeToHtmlType(style) {
458
+ const match = style.match(/list-style-type\s*:\s*([^;]+)/i);
459
+ if (!match) {
460
+ return null;
461
+ }
462
+ const cssValue = match[1].trim().toLowerCase();
463
+ switch (cssValue) {
464
+ case "upper-roman":
465
+ return "I";
466
+ case "lower-roman":
467
+ return "i";
468
+ case "upper-alpha":
469
+ case "upper-latin":
470
+ return "A";
471
+ case "lower-alpha":
472
+ case "lower-latin":
473
+ return "a";
474
+ default:
475
+ return null;
476
+ }
477
+ }
208
478
  var OrderedList = import_core.Node.create({
209
479
  name: "orderedList",
210
480
  addOptions() {
@@ -229,7 +499,30 @@ var OrderedList = import_core.Node.create({
229
499
  },
230
500
  type: {
231
501
  default: null,
232
- parseHTML: (element) => element.getAttribute("type")
502
+ parseHTML: (element) => {
503
+ const htmlType = element.getAttribute("type");
504
+ if (htmlType) {
505
+ return htmlType;
506
+ }
507
+ const style = element.getAttribute("style");
508
+ if (style) {
509
+ const mappedFromOl = cssListStyleTypeToHtmlType(style);
510
+ if (mappedFromOl) {
511
+ return mappedFromOl;
512
+ }
513
+ }
514
+ const firstLi = element.querySelector("li");
515
+ if (firstLi) {
516
+ const liStyle = firstLi.getAttribute("style");
517
+ if (liStyle) {
518
+ const mappedFromLi = cssListStyleTypeToHtmlType(liStyle);
519
+ if (mappedFromLi) {
520
+ return mappedFromLi;
521
+ }
522
+ }
523
+ }
524
+ return null;
525
+ }
233
526
  }
234
527
  };
235
528
  },
@@ -241,8 +534,15 @@ var OrderedList = import_core.Node.create({
241
534
  ];
242
535
  },
243
536
  renderHTML({ HTMLAttributes }) {
244
- const { start, ...attributesWithoutStart } = HTMLAttributes;
245
- return start === 1 ? ["ol", (0, import_core.mergeAttributes)(this.options.HTMLAttributes, attributesWithoutStart), 0] : ["ol", (0, import_core.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
537
+ const { start, type, ...attributesWithoutType } = HTMLAttributes;
538
+ const attrs = (0, import_core.mergeAttributes)(this.options.HTMLAttributes, attributesWithoutType);
539
+ if (start !== 1) {
540
+ attrs.start = start;
541
+ }
542
+ if (type && type !== "1") {
543
+ attrs.type = type;
544
+ }
545
+ return ["ol", attrs, 0];
246
546
  },
247
547
  markdownTokenName: "list",
248
548
  parseMarkdown: (token, helpers) => {
@@ -250,11 +550,19 @@ var OrderedList = import_core.Node.create({
250
550
  return [];
251
551
  }
252
552
  const startValue = token.start || 1;
553
+ const typeValue = token.typeMarker;
253
554
  const content = token.items ? parseListItems(token.items, helpers) : [];
555
+ const attrs = {};
254
556
  if (startValue !== 1) {
557
+ attrs.start = startValue;
558
+ }
559
+ if (typeValue) {
560
+ attrs.type = typeValue;
561
+ }
562
+ if (Object.keys(attrs).length > 0) {
255
563
  return {
256
564
  type: "orderedList",
257
- attrs: { start: startValue },
565
+ attrs,
258
566
  content
259
567
  };
260
568
  }
@@ -273,12 +581,12 @@ var OrderedList = import_core.Node.create({
273
581
  name: "orderedList",
274
582
  level: "block",
275
583
  start: (src) => {
276
- const match = src.match(/^(\s*)(\d+)\.\s+/);
584
+ const match = src.match(ORDERED_LIST_LINE_START_REGEX);
277
585
  const index = match == null ? void 0 : match.index;
278
586
  return index !== void 0 ? index : -1;
279
587
  },
280
588
  tokenize: (src, _tokens, lexer) => {
281
- var _a;
589
+ var _a, _b;
282
590
  const lines = src.split("\n");
283
591
  const [listItems, consumed] = collectOrderedListItems(lines);
284
592
  if (listItems.length === 0) {
@@ -289,10 +597,12 @@ var OrderedList = import_core.Node.create({
289
597
  return void 0;
290
598
  }
291
599
  const startValue = ((_a = listItems[0]) == null ? void 0 : _a.number) || 1;
600
+ const typeMarker = (_b = listItems[0]) == null ? void 0 : _b.type;
292
601
  return {
293
602
  type: "list",
294
603
  ordered: true,
295
604
  start: startValue,
605
+ typeMarker,
296
606
  items,
297
607
  raw: lines.slice(0, consumed).join("\n")
298
608
  };
@@ -316,12 +626,47 @@ var OrderedList = import_core.Node.create({
316
626
  "Mod-Shift-7": () => this.editor.commands.toggleOrderedList()
317
627
  };
318
628
  },
629
+ addProseMirrorPlugins() {
630
+ return [
631
+ new import_state.Plugin({
632
+ props: {
633
+ handlePaste: (view, event) => {
634
+ var _a, _b;
635
+ const html = (_a = event.clipboardData) == null ? void 0 : _a.getData("text/html");
636
+ if (html == null ? void 0 : html.trim()) {
637
+ return false;
638
+ }
639
+ const text = (_b = event.clipboardData) == null ? void 0 : _b.getData("text/plain");
640
+ if (!text) {
641
+ return false;
642
+ }
643
+ const orderedListContent = parsePlainTextOrderedListPaste(text);
644
+ if (!orderedListContent) {
645
+ return false;
646
+ }
647
+ try {
648
+ const orderedListNode = view.state.schema.nodeFromJSON(orderedListContent);
649
+ const tr = view.state.tr.replaceSelectionWith(orderedListNode);
650
+ view.dispatch(tr);
651
+ return true;
652
+ } catch {
653
+ return false;
654
+ }
655
+ }
656
+ }
657
+ })
658
+ ];
659
+ },
319
660
  addInputRules() {
661
+ const joinPredicate = (match, node) => {
662
+ const hasDefaultType = !node.attrs.type || node.attrs.type === "1";
663
+ return hasDefaultType && node.childCount + node.attrs.start === +match[1];
664
+ };
320
665
  let inputRule = (0, import_core.wrappingInputRule)({
321
666
  find: orderedListInputRegex,
322
667
  type: this.type,
323
668
  getAttributes: (match) => ({ start: +match[1] }),
324
- joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1]
669
+ joinPredicate
325
670
  });
326
671
  if (this.options.keepMarks || this.options.keepAttributes) {
327
672
  inputRule = (0, import_core.wrappingInputRule)({
@@ -330,7 +675,7 @@ var OrderedList = import_core.Node.create({
330
675
  keepMarks: this.options.keepMarks,
331
676
  keepAttributes: this.options.keepAttributes,
332
677
  getAttributes: (match) => ({ start: +match[1], ...this.editor.getAttributes(TextStyleName) }),
333
- joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
678
+ joinPredicate,
334
679
  editor: this.editor
335
680
  });
336
681
  }
@@ -339,7 +684,17 @@ var OrderedList = import_core.Node.create({
339
684
  });
340
685
  // Annotate the CommonJS export names for ESM import in node:
341
686
  0 && (module.exports = {
687
+ ORDERED_LIST_MARKER_PATTERN,
342
688
  OrderedList,
343
- orderedListInputRegex
689
+ areOrderedListMarkersSequential,
690
+ buildOrderedListAttrsFromMarker,
691
+ detectMarkerType,
692
+ getListMarker,
693
+ markerToStart,
694
+ orderedListInputRegex,
695
+ parseListMarker,
696
+ parsePlainTextOrderedListPaste,
697
+ toRoman,
698
+ toRomanUpper
344
699
  });
345
700
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ordered-list/index.ts","../../src/ordered-list/ordered-list.ts","../../src/ordered-list/utils.ts"],"sourcesContent":["export * from './ordered-list.js'\n","import { mergeAttributes, Node, wrappingInputRule } from '@tiptap/core'\n\nimport { buildNestedStructure, collectOrderedListItems, parseListItems } from './utils.js'\n\nconst ListItemName = 'listItem'\nconst TextStyleName = 'textStyle'\n\nexport interface OrderedListOptions {\n /**\n * The node type name for list items.\n * @default 'listItem'\n * @example 'myListItem'\n */\n itemTypeName: string\n\n /**\n * The HTML attributes for an ordered list node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>\n\n /**\n * Keep the marks when splitting a list item.\n * @default false\n * @example true\n */\n keepMarks: boolean\n\n /**\n * Keep the attributes when splitting a list item.\n * @default false\n * @example true\n */\n keepAttributes: boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n orderedList: {\n /**\n * Toggle an ordered list\n * @example editor.commands.toggleOrderedList()\n */\n toggleOrderedList: () => ReturnType\n }\n }\n}\n\n/**\n * Matches an ordered list to a 1. on input (or any number followed by a dot).\n */\nexport const orderedListInputRegex = /^(\\d+)\\.\\s$/\n\n/**\n * This extension allows you to create ordered lists.\n * This requires the ListItem extension\n * @see https://www.tiptap.dev/api/nodes/ordered-list\n * @see https://www.tiptap.dev/api/nodes/list-item\n */\nexport const OrderedList = Node.create<OrderedListOptions>({\n name: 'orderedList',\n\n addOptions() {\n return {\n itemTypeName: 'listItem',\n HTMLAttributes: {},\n keepMarks: false,\n keepAttributes: false,\n }\n },\n\n group: 'block list',\n\n content() {\n return `${this.options.itemTypeName}+`\n },\n\n addAttributes() {\n return {\n start: {\n default: 1,\n parseHTML: element => {\n return element.hasAttribute('start')\n ? parseInt(element.getAttribute('start') || '', 10)\n : 1\n },\n },\n type: {\n default: null,\n parseHTML: element => element.getAttribute('type'),\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'ol',\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n const { start, ...attributesWithoutStart } = HTMLAttributes\n\n return start === 1\n ? ['ol', mergeAttributes(this.options.HTMLAttributes, attributesWithoutStart), 0]\n : ['ol', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]\n },\n\n markdownTokenName: 'list',\n\n parseMarkdown: (token, helpers) => {\n if (token.type !== 'list' || !token.ordered) {\n return []\n }\n\n const startValue = token.start || 1\n const content = token.items ? parseListItems(token.items, helpers) : []\n\n if (startValue !== 1) {\n return {\n type: 'orderedList',\n attrs: { start: startValue },\n content,\n }\n }\n\n return {\n type: 'orderedList',\n content,\n }\n },\n\n renderMarkdown: (node, h) => {\n if (!node.content) {\n return ''\n }\n\n return h.renderChildren(node.content, '\\n')\n },\n\n markdownTokenizer: {\n name: 'orderedList',\n level: 'block',\n start: (src: string) => {\n const match = src.match(/^(\\s*)(\\d+)\\.\\s+/)\n const index = match?.index\n return index !== undefined ? index : -1\n },\n tokenize: (src: string, _tokens, lexer) => {\n const lines = src.split('\\n')\n const [listItems, consumed] = collectOrderedListItems(lines)\n\n if (listItems.length === 0) {\n return undefined\n }\n\n const items = buildNestedStructure(listItems, 0, lexer)\n\n if (items.length === 0) {\n return undefined\n }\n\n const startValue = listItems[0]?.number || 1\n\n return {\n type: 'list',\n ordered: true,\n start: startValue,\n items,\n raw: lines.slice(0, consumed).join('\\n'),\n } as unknown as object\n },\n },\n\n markdownOptions: {\n indentsContent: true,\n },\n\n addCommands() {\n return {\n toggleOrderedList:\n () =>\n ({ commands, chain }) => {\n if (this.options.keepAttributes) {\n return chain()\n .toggleList(this.name, this.options.itemTypeName, this.options.keepMarks)\n .updateAttributes(ListItemName, this.editor.getAttributes(TextStyleName))\n .run()\n }\n return commands.toggleList(this.name, this.options.itemTypeName, this.options.keepMarks)\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Shift-7': () => this.editor.commands.toggleOrderedList(),\n }\n },\n\n addInputRules() {\n let inputRule = wrappingInputRule({\n find: orderedListInputRegex,\n type: this.type,\n getAttributes: match => ({ start: +match[1] }),\n joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],\n })\n\n if (this.options.keepMarks || this.options.keepAttributes) {\n inputRule = wrappingInputRule({\n find: orderedListInputRegex,\n type: this.type,\n keepMarks: this.options.keepMarks,\n keepAttributes: this.options.keepAttributes,\n getAttributes: match => ({ start: +match[1], ...this.editor.getAttributes(TextStyleName) }),\n joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],\n editor: this.editor,\n })\n }\n return [inputRule]\n },\n})\n","import type {\n JSONContent,\n MarkdownLexerConfiguration,\n MarkdownParseHelpers,\n MarkdownToken,\n} from '@tiptap/core'\n\n/**\n * Matches an ordered list item line with optional leading whitespace.\n * Captures: (1) indentation spaces, (2) item number, (3) content after marker\n * Example matches: \"1. Item\", \" 2. Nested item\", \" 3. Deeply nested\"\n */\nconst ORDERED_LIST_ITEM_REGEX = /^(\\s*)(\\d+)\\.\\s+(.*)$/\n\n/**\n * Matches any line that starts with whitespace (indented content).\n * Used to identify continuation content that belongs to a list item.\n */\nconst INDENTED_LINE_REGEX = /^\\s/\n\n/**\n * Represents a parsed ordered list item with indentation information\n */\nexport interface OrderedListItem {\n indent: number\n number: number\n content: string\n contentLines: string[]\n raw: string\n}\n\nfunction isBlockContentLine(line: string): boolean {\n const trimmedLine = line.trimStart()\n\n return (\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^[-+*]\\s+/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^\\d+\\.\\s+/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^>\\s?/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^```/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^~~~/.test(trimmedLine)\n )\n}\n\nfunction splitItemContent(contentLines: string[]): {\n paragraphLines: string[]\n blockLines: string[]\n} {\n const paragraphLines: string[] = []\n const blockLines: string[] = []\n let reachedBlockBoundary = false\n\n contentLines.forEach(line => {\n if (reachedBlockBoundary) {\n blockLines.push(line)\n return\n }\n\n if (line.trim() === '') {\n reachedBlockBoundary = true\n blockLines.push(line)\n return\n }\n\n if (paragraphLines.length > 0 && isBlockContentLine(line)) {\n reachedBlockBoundary = true\n blockLines.push(line)\n return\n }\n\n paragraphLines.push(line)\n })\n\n return {\n paragraphLines,\n blockLines,\n }\n}\n\n/**\n * Collects all ordered list items from lines, parsing them into a flat array\n * with indentation information. Stops collecting continuation content when\n * encountering nested list items, allowing them to be processed separately.\n *\n * @param lines - Array of source lines to parse\n * @returns Tuple of [listItems array, number of lines consumed]\n */\nexport function collectOrderedListItems(lines: string[]): [OrderedListItem[], number] {\n const listItems: OrderedListItem[] = []\n let currentLineIndex = 0\n let consumed = 0\n\n while (currentLineIndex < lines.length) {\n const line = lines[currentLineIndex]\n const match = line.match(ORDERED_LIST_ITEM_REGEX)\n\n if (!match) {\n break\n }\n\n const [, indent, number, content] = match\n const indentLevel = indent.length\n const itemContentLines = [content]\n let nextLineIndex = currentLineIndex + 1\n const itemLines = [line]\n let sawBlankLine = false\n\n // Collect continuation lines for this item (but NOT nested list items)\n while (nextLineIndex < lines.length) {\n const nextLine = lines[nextLineIndex]\n const nextMatch = nextLine.match(ORDERED_LIST_ITEM_REGEX)\n\n // If it's another list item (nested or not), stop collecting\n if (nextMatch) {\n break\n }\n\n // Check for continuation content (non-list content)\n if (nextLine.trim() === '') {\n // Empty line\n itemLines.push(nextLine)\n itemContentLines.push('')\n sawBlankLine = true\n nextLineIndex += 1\n } else if (nextLine.match(INDENTED_LINE_REGEX)) {\n // Indented content - part of this item (but not a list item)\n itemLines.push(nextLine)\n itemContentLines.push(nextLine.slice(indentLevel + 2))\n nextLineIndex += 1\n } else {\n if (sawBlankLine) {\n break\n }\n\n itemLines.push(nextLine)\n itemContentLines.push(nextLine)\n nextLineIndex += 1\n }\n }\n\n listItems.push({\n indent: indentLevel,\n number: parseInt(number, 10),\n content: itemContentLines.join('\\n').trim(),\n contentLines: itemContentLines,\n raw: itemLines.join('\\n'),\n })\n\n consumed = nextLineIndex\n currentLineIndex = nextLineIndex\n }\n\n return [listItems, consumed]\n}\n\n/**\n * Recursively builds a nested structure from a flat array of list items\n * based on their indentation levels. Creates proper markdown tokens with\n * nested lists where appropriate.\n *\n * @param items - Flat array of list items with indentation info\n * @param baseIndent - The indentation level to process at this recursion level\n * @param lexer - Markdown lexer for parsing inline and block content\n * @returns Array of list_item tokens with proper nesting\n */\nexport function buildNestedStructure(\n items: OrderedListItem[],\n baseIndent: number,\n lexer: MarkdownLexerConfiguration,\n): unknown[] {\n const result: unknown[] = []\n let currentIndex = 0\n\n while (currentIndex < items.length) {\n const item = items[currentIndex]\n\n if (item.indent === baseIndent) {\n // This item belongs at the current level\n const { paragraphLines, blockLines } = splitItemContent(item.contentLines)\n const mainText = paragraphLines.join('\\n').trim()\n\n const tokens = []\n\n // Always wrap the main text in a paragraph token\n if (mainText) {\n tokens.push({\n type: 'paragraph',\n raw: mainText,\n tokens: lexer.inlineTokens(mainText),\n })\n }\n\n const additionalContent = blockLines.join('\\n').trim()\n if (additionalContent) {\n const blockTokens = lexer.blockTokens(additionalContent)\n tokens.push(...blockTokens)\n }\n\n // Look ahead to find nested items at deeper indent levels\n let lookAheadIndex = currentIndex + 1\n const nestedItems = []\n\n while (lookAheadIndex < items.length && items[lookAheadIndex].indent > baseIndent) {\n nestedItems.push(items[lookAheadIndex])\n lookAheadIndex += 1\n }\n\n // If we have nested items, recursively build their structure\n if (nestedItems.length > 0) {\n // Find the next indent level (immediate children)\n const nextIndent = Math.min(...nestedItems.map(nestedItem => nestedItem.indent))\n\n // Build the nested list recursively with all nested items\n // The recursive call will handle further nesting\n const nestedListItems = buildNestedStructure(nestedItems, nextIndent, lexer)\n\n // Create a nested list token\n tokens.push({\n type: 'list',\n ordered: true,\n start: nestedItems[0].number,\n items: nestedListItems,\n raw: nestedItems.map(nestedItem => nestedItem.raw).join('\\n'),\n })\n }\n\n result.push({\n type: 'list_item',\n raw: item.raw,\n tokens,\n })\n\n // Skip the nested items we just processed\n currentIndex = lookAheadIndex\n } else {\n // This item has deeper indent than we're currently processing\n // It should be handled by a recursive call\n currentIndex += 1\n }\n }\n\n return result\n}\n\n/**\n * Parses markdown list item tokens into Tiptap JSONContent structure,\n * ensuring text content is properly wrapped in paragraph nodes.\n *\n * @param items - Array of markdown tokens representing list items\n * @param helpers - Markdown parse helpers for recursive parsing\n * @returns Array of listItem JSONContent nodes\n */\nexport function parseListItems(\n items: MarkdownToken[],\n helpers: MarkdownParseHelpers,\n): JSONContent[] {\n return items.map(item => {\n if (item.type !== 'list_item') {\n return helpers.parseChildren([item])[0]\n }\n\n // Parse the tokens within the list item\n const content: JSONContent[] = []\n\n if (item.tokens && item.tokens.length > 0) {\n item.tokens.forEach(itemToken => {\n // If it's already a proper block node (paragraph, list, etc.), parse it directly\n if (\n itemToken.type === 'paragraph' ||\n itemToken.type === 'list' ||\n itemToken.type === 'blockquote' ||\n itemToken.type === 'code'\n ) {\n content.push(...helpers.parseChildren([itemToken]))\n } else if (itemToken.type === 'text' && itemToken.tokens) {\n // If it's inline text tokens, wrap them in a paragraph\n const inlineContent = helpers.parseChildren([itemToken])\n content.push({\n type: 'paragraph',\n content: inlineContent,\n })\n } else {\n // For any other content, try to parse it\n const parsed = helpers.parseChildren([itemToken])\n if (parsed.length > 0) {\n content.push(...parsed)\n }\n }\n })\n }\n\n return {\n type: 'listItem',\n content,\n }\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/ordered-list/index.ts","../../src/ordered-list/ordered-list.ts","../../src/ordered-list/roman.ts","../../src/ordered-list/utils.ts"],"sourcesContent":["export * from './ordered-list.js'\nexport {\n areOrderedListMarkersSequential,\n buildOrderedListAttrsFromMarker,\n detectMarkerType,\n getListMarker,\n markerToStart,\n ORDERED_LIST_MARKER_PATTERN,\n parseListMarker,\n toRoman,\n toRomanUpper,\n} from './roman.js'\nexport { parsePlainTextOrderedListPaste } from './utils.js'\n","import type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { Plugin } from '@tiptap/pm/state'\n\nimport { mergeAttributes, Node, wrappingInputRule } from '@tiptap/core'\n\nimport {\n buildNestedStructure,\n collectOrderedListItems,\n ORDERED_LIST_LINE_START_REGEX,\n parseListItems,\n parsePlainTextOrderedListPaste,\n} from './utils.js'\n\nconst ListItemName = 'listItem'\nconst TextStyleName = 'textStyle'\n\nexport interface OrderedListOptions {\n /**\n * The node type name for list items.\n * @default 'listItem'\n * @example 'myListItem'\n */\n itemTypeName: string\n\n /**\n * The HTML attributes for an ordered list node.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>\n\n /**\n * Keep the marks when splitting a list item.\n * @default false\n * @example true\n */\n keepMarks: boolean\n\n /**\n * Keep the attributes when splitting a list item.\n * @default false\n * @example true\n */\n keepAttributes: boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n orderedList: {\n /**\n * Toggle an ordered list\n * @example editor.commands.toggleOrderedList()\n */\n toggleOrderedList: () => ReturnType\n }\n }\n}\n\n/**\n * Matches an ordered list to a 1. on input (or any number followed by a dot).\n */\nexport const orderedListInputRegex = /^(\\d+)\\.\\s$/\n\n/**\n * Maps CSS list-style-type values to HTML type attribute values.\n * Google Docs and Word often use CSS instead of the HTML type attribute.\n */\nfunction cssListStyleTypeToHtmlType(style: string): string | null {\n const match = style.match(/list-style-type\\s*:\\s*([^;]+)/i)\n if (!match) {\n return null\n }\n\n const cssValue = match[1].trim().toLowerCase()\n\n switch (cssValue) {\n case 'upper-roman':\n return 'I'\n case 'lower-roman':\n return 'i'\n case 'upper-alpha':\n case 'upper-latin':\n return 'A'\n case 'lower-alpha':\n case 'lower-latin':\n return 'a'\n default:\n return null\n }\n}\n\n/**\n * This extension allows you to create ordered lists.\n * This requires the ListItem extension\n * @see https://www.tiptap.dev/api/nodes/ordered-list\n * @see https://www.tiptap.dev/api/nodes/list-item\n */\nexport const OrderedList = Node.create<OrderedListOptions>({\n name: 'orderedList',\n\n addOptions() {\n return {\n itemTypeName: 'listItem',\n HTMLAttributes: {},\n keepMarks: false,\n keepAttributes: false,\n }\n },\n\n group: 'block list',\n\n content() {\n return `${this.options.itemTypeName}+`\n },\n\n addAttributes() {\n return {\n start: {\n default: 1,\n parseHTML: element => {\n return element.hasAttribute('start')\n ? parseInt(element.getAttribute('start') || '', 10)\n : 1\n },\n },\n type: {\n default: null,\n parseHTML: element => {\n // 1. Check the HTML type attribute on <ol>\n const htmlType = element.getAttribute('type')\n if (htmlType) {\n return htmlType\n }\n\n // 2. Check CSS list-style-type on the <ol> element's style attribute\n const style = element.getAttribute('style')\n if (style) {\n const mappedFromOl = cssListStyleTypeToHtmlType(style)\n if (mappedFromOl) {\n return mappedFromOl\n }\n }\n\n // 3. Check the first <li> child for list-style-type (Google Docs pattern)\n const firstLi = element.querySelector('li')\n if (firstLi) {\n const liStyle = firstLi.getAttribute('style')\n if (liStyle) {\n const mappedFromLi = cssListStyleTypeToHtmlType(liStyle)\n if (mappedFromLi) {\n return mappedFromLi\n }\n }\n }\n\n return null\n },\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'ol',\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n const { start, type, ...attributesWithoutType } = HTMLAttributes\n\n const attrs = mergeAttributes(this.options.HTMLAttributes, attributesWithoutType)\n\n if (start !== 1) {\n attrs.start = start\n }\n\n if (type && type !== '1') {\n attrs.type = type\n }\n\n return ['ol', attrs, 0]\n },\n\n markdownTokenName: 'list',\n\n parseMarkdown: (token, helpers) => {\n if (token.type !== 'list' || !token.ordered) {\n return []\n }\n\n const startValue = token.start || 1\n const typeValue = token.typeMarker as string | undefined\n const content = token.items ? parseListItems(token.items, helpers) : []\n\n // Build attrs only when they differ from defaults\n const attrs: Record<string, unknown> = {}\n\n if (startValue !== 1) {\n attrs.start = startValue\n }\n\n if (typeValue) {\n attrs.type = typeValue\n }\n\n if (Object.keys(attrs).length > 0) {\n return {\n type: 'orderedList',\n attrs,\n content,\n }\n }\n\n return {\n type: 'orderedList',\n content,\n }\n },\n\n renderMarkdown: (node, h) => {\n if (!node.content) {\n return ''\n }\n\n return h.renderChildren(node.content, '\\n')\n },\n\n markdownTokenizer: {\n name: 'orderedList',\n level: 'block',\n start: (src: string) => {\n const match = src.match(ORDERED_LIST_LINE_START_REGEX)\n const index = match?.index\n return index !== undefined ? index : -1\n },\n tokenize: (src: string, _tokens, lexer) => {\n const lines = src.split('\\n')\n const [listItems, consumed] = collectOrderedListItems(lines)\n\n if (listItems.length === 0) {\n return undefined\n }\n\n const items = buildNestedStructure(listItems, 0, lexer)\n\n if (items.length === 0) {\n return undefined\n }\n\n const startValue = listItems[0]?.number || 1\n const typeMarker = listItems[0]?.type\n\n return {\n type: 'list',\n ordered: true,\n start: startValue,\n typeMarker,\n items,\n raw: lines.slice(0, consumed).join('\\n'),\n } as unknown as object\n },\n },\n\n markdownOptions: {\n indentsContent: true,\n },\n\n addCommands() {\n return {\n toggleOrderedList:\n () =>\n ({ commands, chain }) => {\n if (this.options.keepAttributes) {\n return chain()\n .toggleList(this.name, this.options.itemTypeName, this.options.keepMarks)\n .updateAttributes(ListItemName, this.editor.getAttributes(TextStyleName))\n .run()\n }\n return commands.toggleList(this.name, this.options.itemTypeName, this.options.keepMarks)\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Shift-7': () => this.editor.commands.toggleOrderedList(),\n }\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handlePaste: (view, event) => {\n const html = event.clipboardData?.getData('text/html')\n\n if (html?.trim()) {\n return false\n }\n\n const text = event.clipboardData?.getData('text/plain')\n\n if (!text) {\n return false\n }\n\n const orderedListContent = parsePlainTextOrderedListPaste(text)\n\n if (!orderedListContent) {\n return false\n }\n\n try {\n const orderedListNode = view.state.schema.nodeFromJSON(orderedListContent)\n const tr = view.state.tr.replaceSelectionWith(orderedListNode)\n\n view.dispatch(tr)\n\n return true\n } catch {\n return false\n }\n },\n },\n }),\n ]\n },\n\n addInputRules() {\n const joinPredicate = (match: RegExpMatchArray, node: ProseMirrorNode) => {\n // Only join if the existing list has a default type\n // (not a typed list like \"a\" or \"i\" which should stay separate)\n const hasDefaultType = !node.attrs.type || node.attrs.type === '1'\n\n return hasDefaultType && node.childCount + node.attrs.start === +match[1]\n }\n\n let inputRule = wrappingInputRule({\n find: orderedListInputRegex,\n type: this.type,\n getAttributes: match => ({ start: +match[1] }),\n joinPredicate,\n })\n\n if (this.options.keepMarks || this.options.keepAttributes) {\n inputRule = wrappingInputRule({\n find: orderedListInputRegex,\n type: this.type,\n keepMarks: this.options.keepMarks,\n keepAttributes: this.options.keepAttributes,\n getAttributes: match => ({ start: +match[1], ...this.editor.getAttributes(TextStyleName) }),\n joinPredicate,\n editor: this.editor,\n })\n }\n return [inputRule]\n },\n})\n","const ROMAN_NUMERALS: [number, string][] = [\n [1000, 'm'],\n [900, 'cm'],\n [500, 'd'],\n [400, 'cd'],\n [100, 'c'],\n [90, 'xc'],\n [50, 'l'],\n [40, 'xl'],\n [10, 'x'],\n [9, 'ix'],\n [5, 'v'],\n [4, 'iv'],\n [1, 'i'],\n]\n\nconst ALPHA_NUMERALS = 'abcdefghijklmnopqrstuvwxyz'\n\n/** Alpha list markers support at most 2 letters (a–z, aa–zz), matching {@link fromAlpha}. */\nexport const ORDERED_LIST_ALPHA_MARKER_PATTERN = '[a-zA-Z]{1,2}'\n\n/**\n * Marker segment for ordered list lines: numeric, roman, or 1–2 letter alpha.\n * Roman is matched before alpha so \"iii\" is roman; invalid romans like \"aa\" fall through to alpha.\n */\nexport const ORDERED_LIST_MARKER_PATTERN = String.raw`\\d+|[ivxlcdmIVXLCDM]+|${ORDERED_LIST_ALPHA_MARKER_PATTERN}`\n\n/**\n * Convert a number to lowercase roman numerals.\n * @example toRoman(1) // 'i'\n * @example toRoman(4) // 'iv'\n */\nexport function toRoman(num: number): string {\n let remaining = num\n let result = ''\n\n for (const [value, numeral] of ROMAN_NUMERALS) {\n while (remaining >= value) {\n result += numeral\n remaining -= value\n }\n }\n\n return result\n}\n\n/**\n * Convert a number to uppercase roman numerals.\n * @example toRomanUpper(1) // 'I'\n * @example toRomanUpper(4) // 'IV'\n */\nexport function toRomanUpper(num: number): string {\n return toRoman(num).toUpperCase()\n}\n\nfunction fromRoman(roman: string): number {\n const lower = roman.toLowerCase()\n let index = 0\n let result = 0\n\n while (index < lower.length) {\n let matched = false\n\n for (const [value, numeral] of ROMAN_NUMERALS) {\n if (lower.startsWith(numeral, index)) {\n result += value\n index += numeral.length\n matched = true\n break\n }\n }\n\n if (!matched) {\n return 0\n }\n }\n\n return result\n}\n\nfunction isValidRoman(marker: string): boolean {\n if (!/^[ivxlcdmIVXLCDM]+$/.test(marker)) {\n return false\n }\n\n const value = fromRoman(marker)\n\n if (value <= 0) {\n return false\n }\n\n const expected = marker === marker.toLowerCase() ? toRoman(value) : toRomanUpper(value)\n\n return expected === marker\n}\n\nfunction fromAlpha(marker: string): number {\n const lower = marker.toLowerCase()\n\n if (lower.length === 1) {\n return lower.charCodeAt(0) - 'a'.charCodeAt(0) + 1\n }\n\n if (lower.length === 2) {\n const first = lower.charCodeAt(0) - 'a'.charCodeAt(0)\n const second = lower.charCodeAt(1) - 'a'.charCodeAt(0)\n\n return (first + 1) * 26 + second + 1\n }\n\n return 0\n}\n\nfunction toRomanAlpha(num: number): string {\n if (num <= 26) {\n return ALPHA_NUMERALS[num - 1]\n }\n\n const first = Math.floor((num - 1) / 26) - 1\n const second = (num - 1) % 26\n\n if (first < 0) {\n return ALPHA_NUMERALS[second]\n }\n\n return ALPHA_NUMERALS[first] + ALPHA_NUMERALS[second]\n}\n\n/**\n * Extract the list marker type from a marker string.\n * Supports \"1\", \"a\", \"A\", \"i\", \"I\" marker styles.\n *\n * @param marker The text content of the list marker (e.g. \"a\", \"1\", \"iii\", \"b\")\n * @returns The normalized type string, or undefined for default numeric type\n */\nexport function detectMarkerType(marker: string): string | undefined {\n if (!marker || /^\\d+$/.test(marker)) {\n return undefined\n }\n\n if (isValidRoman(marker)) {\n return marker === marker.toLowerCase() ? 'i' : 'I'\n }\n\n if (/^[a-z]{1,2}$/.test(marker)) {\n return 'a'\n }\n\n if (/^[A-Z]{1,2}$/.test(marker)) {\n return 'A'\n }\n\n return undefined\n}\n\n/**\n * Convert a list marker string to its numeric start position.\n *\n * @param marker The text content of the list marker (e.g. \"3\", \"b\", \"II\")\n * @returns The 1-based start value for the ordered list\n */\nexport function markerToStart(marker: string): number {\n if (/^\\d+$/.test(marker)) {\n return parseInt(marker, 10)\n }\n\n const type = detectMarkerType(marker)\n\n if (type === 'i' || type === 'I') {\n return fromRoman(marker)\n }\n\n if (type === 'a' || type === 'A') {\n const start = fromAlpha(marker)\n\n return start > 0 ? start : 1\n }\n\n const parsed = parseInt(marker, 10)\n\n return Number.isNaN(parsed) ? 1 : parsed\n}\n\nfunction startToMarker(type: string, start: number): string {\n if (type === 'numeric') {\n return String(start)\n }\n\n switch (type) {\n case 'a':\n return toRomanAlpha(start)\n case 'A':\n return toRomanAlpha(start).toUpperCase()\n case 'i':\n return toRoman(start)\n case 'I':\n return toRomanUpper(start)\n default:\n return String(start)\n }\n}\n\n/**\n * Returns true when all markers share the same style and increment by 1.\n * Style is inferred from the first marker so ambiguous letters (e.g. \"c\", \"i\")\n * are not re-classified differently on later lines.\n */\nexport function areOrderedListMarkersSequential(markers: string[]): boolean {\n if (markers.length === 0) {\n return false\n }\n\n const firstType = detectMarkerType(markers[0]) ?? 'numeric'\n const firstStart = markerToStart(markers[0])\n\n if (firstStart < 1) {\n return false\n }\n\n for (let i = 0; i < markers.length; i++) {\n const expected = startToMarker(firstType, firstStart + i)\n\n if (markers[i] !== expected) {\n return false\n }\n }\n\n return true\n}\n\nexport interface ParsedListMarker {\n type?: string\n start: number\n}\n\n/**\n * Parse a list marker into HTML ordered-list attrs (type + start).\n */\nexport function parseListMarker(marker: string): ParsedListMarker {\n return {\n type: detectMarkerType(marker),\n start: markerToStart(marker),\n }\n}\n\n/**\n * Build orderedList node attrs from the first list item marker.\n */\nexport function buildOrderedListAttrsFromMarker(marker: string): Record<string, string | number> {\n const { type, start } = parseListMarker(marker)\n const attrs: Record<string, string | number> = {}\n\n if (type) {\n attrs.type = type\n }\n\n if (start !== 1) {\n attrs.start = start\n }\n\n return attrs\n}\n\n/**\n * Returns the list marker prefix for a given item at a given index.\n *\n * @param type The list type attribute (e.g. \"a\", \"A\", \"i\", \"I\", null/undefined for default)\n * @param index The zero-based index of the list item\n * @param separator The separator to use (default: \". \")\n * @returns The marker string (e.g. \"a. \", \"I. \", \"1. \")\n */\nexport function getListMarker(\n type: string | null | undefined,\n index: number,\n separator = '. ',\n): string {\n const position = index + 1\n\n if (!type || type === '1') {\n return `${position}${separator}`\n }\n\n switch (type) {\n case 'a':\n return `${toRomanAlpha(position)}${separator}`\n case 'A':\n return `${toRomanAlpha(position).toUpperCase()}${separator}`\n case 'i':\n return `${toRoman(position)}${separator}`\n case 'I':\n return `${toRomanUpper(position)}${separator}`\n default:\n return `${position}${separator}`\n }\n}\n","import type {\n JSONContent,\n MarkdownLexerConfiguration,\n MarkdownParseHelpers,\n MarkdownToken,\n} from '@tiptap/core'\n\nimport {\n areOrderedListMarkersSequential,\n buildOrderedListAttrsFromMarker,\n detectMarkerType,\n markerToStart,\n ORDERED_LIST_MARKER_PATTERN,\n} from './roman.js'\n\nexport { ORDERED_LIST_MARKER_PATTERN }\n\n/**\n * Matches an ordered list item line with optional leading whitespace.\n * Captures: (1) indentation spaces, (2) item marker (number, letter, or roman numeral),\n * (3) separator (. or )), (4) content after marker\n *\n * Examples: \"1. Item\", \" a) Nested item\", \" I. Roman item\", \"iii. Another\", \"aa. Item 27\"\n */\nexport const ORDERED_LIST_ITEM_REGEX = new RegExp(\n `^(\\\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\\\s+(.*)$`,\n)\n\n/**\n * Matches the start of an ordered list line (used by markdown tokenizer).\n */\nexport const ORDERED_LIST_LINE_START_REGEX = new RegExp(\n `^(\\\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\\\s+`,\n)\n\n/**\n * Matches any line that starts with whitespace (indented content).\n * Used to identify continuation content that belongs to a list item.\n */\nconst INDENTED_LINE_REGEX = /^\\s/\n\n/**\n * Represents a parsed ordered list item with indentation information\n */\nexport interface OrderedListItem {\n indent: number\n number: number\n type?: string\n content: string\n contentLines: string[]\n raw: string\n}\n\nfunction isOrderedListMarkerLine(line: string): boolean {\n return ORDERED_LIST_ITEM_REGEX.test(line.trimStart())\n}\n\nfunction isBlockContentLine(line: string): boolean {\n const trimmedLine = line.trimStart()\n\n return (\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^[-+*]\\s+/.test(trimmedLine) ||\n isOrderedListMarkerLine(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^>\\s?/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^```/.test(trimmedLine) ||\n // oxlint-disable-next-line prefer-string-starts-ends-with\n /^~~~/.test(trimmedLine)\n )\n}\n\nfunction splitItemContent(contentLines: string[]): {\n paragraphLines: string[]\n blockLines: string[]\n} {\n const paragraphLines: string[] = []\n const blockLines: string[] = []\n let reachedBlockBoundary = false\n\n contentLines.forEach(line => {\n if (reachedBlockBoundary) {\n blockLines.push(line)\n return\n }\n\n if (line.trim() === '') {\n reachedBlockBoundary = true\n blockLines.push(line)\n return\n }\n\n if (paragraphLines.length > 0 && isBlockContentLine(line)) {\n reachedBlockBoundary = true\n blockLines.push(line)\n return\n }\n\n paragraphLines.push(line)\n })\n\n return {\n paragraphLines,\n blockLines,\n }\n}\n\n/**\n * Collects all ordered list items from lines, parsing them into a flat array\n * with indentation information. Stops collecting continuation content when\n * encountering nested list items, allowing them to be processed separately.\n *\n * @param lines - Array of source lines to parse\n * @returns Tuple of [listItems array, number of lines consumed]\n */\nexport function collectOrderedListItems(lines: string[]): [OrderedListItem[], number] {\n const listItems: OrderedListItem[] = []\n let currentLineIndex = 0\n let consumed = 0\n\n while (currentLineIndex < lines.length) {\n const line = lines[currentLineIndex]\n const match = line.match(ORDERED_LIST_ITEM_REGEX)\n\n if (!match) {\n break\n }\n\n const [, indent, marker, _separator, content] = match\n const indentLevel = indent.length\n const number = parseInt(marker, 10)\n\n const markerType = isNaN(number) ? detectMarkerType(marker) : undefined\n const itemNumber = isNaN(number) ? markerToStart(marker) : number\n\n const itemContentLines = [content]\n let nextLineIndex = currentLineIndex + 1\n const itemLines = [line]\n let sawBlankLine = false\n\n // Collect continuation lines for this item (but NOT nested list items)\n while (nextLineIndex < lines.length) {\n const nextLine = lines[nextLineIndex]\n const nextMatch = nextLine.match(ORDERED_LIST_ITEM_REGEX)\n\n // If it's another list item (nested or not), stop collecting\n if (nextMatch) {\n break\n }\n\n // Check for continuation content (non-list content)\n if (nextLine.trim() === '') {\n // Empty line\n itemLines.push(nextLine)\n itemContentLines.push('')\n sawBlankLine = true\n nextLineIndex += 1\n } else if (nextLine.match(INDENTED_LINE_REGEX)) {\n // Indented content - part of this item (but not a list item)\n itemLines.push(nextLine)\n itemContentLines.push(nextLine.slice(indentLevel + 2))\n nextLineIndex += 1\n } else {\n if (sawBlankLine) {\n break\n }\n\n itemLines.push(nextLine)\n itemContentLines.push(nextLine)\n nextLineIndex += 1\n }\n }\n\n listItems.push({\n indent: indentLevel,\n number: itemNumber,\n type: markerType,\n content: itemContentLines.join('\\n').trim(),\n contentLines: itemContentLines,\n raw: itemLines.join('\\n'),\n })\n\n consumed = nextLineIndex\n currentLineIndex = nextLineIndex\n }\n\n return [listItems, consumed]\n}\n\nconst PLAIN_TEXT_ORDERED_LIST_LINE_REGEX = new RegExp(\n `^(${ORDERED_LIST_MARKER_PATTERN})([.)])\\\\s+(.+)$`,\n)\n\n/**\n * Parse plain-text pasted ordered list lines into JSONContent, or null if not a typed list.\n */\nexport function parsePlainTextOrderedListPaste(text: string): JSONContent | null {\n const lines = text.split('\\n').filter(l => l.trim().length > 0)\n\n if (lines.length === 0) {\n return null\n }\n\n const parsedItems: Array<{ marker: string; content: string }> = []\n\n for (const line of lines) {\n const match = line.trim().match(PLAIN_TEXT_ORDERED_LIST_LINE_REGEX)\n\n if (!match) {\n return null\n }\n\n parsedItems.push({\n marker: match[1],\n content: match[3],\n })\n }\n\n const markers = parsedItems.map(item => item.marker)\n\n if (!areOrderedListMarkersSequential(markers)) {\n return null\n }\n\n const attrs = buildOrderedListAttrsFromMarker(parsedItems[0].marker)\n\n return {\n type: 'orderedList',\n attrs,\n content: parsedItems.map(item => ({\n type: 'listItem',\n content: [\n {\n type: 'paragraph',\n content: [{ type: 'text', text: item.content }],\n },\n ],\n })),\n }\n}\n\n/**\n * Recursively builds a nested structure from a flat array of list items\n * based on their indentation levels. Creates proper markdown tokens with\n * nested lists where appropriate.\n *\n * @param items - Flat array of list items with indentation info\n * @param baseIndent - The indentation level to process at this recursion level\n * @param lexer - Markdown lexer for parsing inline and block content\n * @returns Array of list_item tokens with proper nesting\n */\nexport function buildNestedStructure(\n items: OrderedListItem[],\n baseIndent: number,\n lexer: MarkdownLexerConfiguration,\n): unknown[] {\n const result: unknown[] = []\n let currentIndex = 0\n\n while (currentIndex < items.length) {\n const item = items[currentIndex]\n\n if (item.indent === baseIndent) {\n // This item belongs at the current level\n const { paragraphLines, blockLines } = splitItemContent(item.contentLines)\n const mainText = paragraphLines.join('\\n').trim()\n\n const tokens = []\n\n // Always wrap the main text in a paragraph token\n if (mainText) {\n tokens.push({\n type: 'paragraph',\n raw: mainText,\n tokens: lexer.inlineTokens(mainText),\n })\n }\n\n const additionalContent = blockLines.join('\\n').trim()\n if (additionalContent) {\n const blockTokens = lexer.blockTokens(additionalContent)\n tokens.push(...blockTokens)\n }\n\n // Look ahead to find nested items at deeper indent levels\n let lookAheadIndex = currentIndex + 1\n const nestedItems = []\n\n while (lookAheadIndex < items.length && items[lookAheadIndex].indent > baseIndent) {\n nestedItems.push(items[lookAheadIndex])\n lookAheadIndex += 1\n }\n\n // If we have nested items, recursively build their structure\n if (nestedItems.length > 0) {\n // Find the next indent level (immediate children)\n const nextIndent = Math.min(...nestedItems.map(nestedItem => nestedItem.indent))\n\n // Build the nested list recursively with all nested items\n // The recursive call will handle further nesting\n const nestedListItems = buildNestedStructure(nestedItems, nextIndent, lexer)\n\n // Create a nested list token\n tokens.push({\n type: 'list',\n ordered: true,\n start: nestedItems[0].number,\n typeMarker: nestedItems[0].type,\n items: nestedListItems,\n raw: nestedItems.map(nestedItem => nestedItem.raw).join('\\n'),\n })\n }\n\n result.push({\n type: 'list_item',\n raw: item.raw,\n tokens,\n })\n\n // Skip the nested items we just processed\n currentIndex = lookAheadIndex\n } else {\n // This item has deeper indent than we're currently processing\n // It should be handled by a recursive call\n currentIndex += 1\n }\n }\n\n return result\n}\n\n/**\n * Parses markdown list item tokens into Tiptap JSONContent structure,\n * ensuring text content is properly wrapped in paragraph nodes.\n *\n * @param items - Array of markdown tokens representing list items\n * @param helpers - Markdown parse helpers for recursive parsing\n * @returns Array of listItem JSONContent nodes\n */\nexport function parseListItems(\n items: MarkdownToken[],\n helpers: MarkdownParseHelpers,\n): JSONContent[] {\n return items.map(item => {\n if (item.type !== 'list_item') {\n return helpers.parseChildren([item])[0]\n }\n\n // Parse the tokens within the list item\n const content: JSONContent[] = []\n\n if (item.tokens && item.tokens.length > 0) {\n item.tokens.forEach(itemToken => {\n // If it's already a proper block node (paragraph, list, etc.), parse it directly\n if (\n itemToken.type === 'paragraph' ||\n itemToken.type === 'list' ||\n itemToken.type === 'blockquote' ||\n itemToken.type === 'code'\n ) {\n content.push(...helpers.parseChildren([itemToken]))\n } else if (itemToken.type === 'text' && itemToken.tokens) {\n // If it's inline text tokens, wrap them in a paragraph\n const inlineContent = helpers.parseChildren([itemToken])\n content.push({\n type: 'paragraph',\n content: inlineContent,\n })\n } else {\n // For any other content, try to parse it\n const parsed = helpers.parseChildren([itemToken])\n if (parsed.length > 0) {\n content.push(...parsed)\n }\n }\n })\n }\n\n return {\n type: 'listItem',\n content,\n }\n })\n}\n"],"mappings":"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","names":[]}