@tiptap/extension-list 3.26.1 → 3.27.1
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 +377 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -2
- package/dist/index.d.ts +67 -2
- package/dist/index.js +366 -17
- package/dist/index.js.map +1 -1
- package/dist/item/index.cjs +67 -2
- package/dist/item/index.cjs.map +1 -1
- package/dist/item/index.js +67 -2
- package/dist/item/index.js.map +1 -1
- package/dist/kit/index.cjs +355 -16
- package/dist/kit/index.cjs.map +1 -1
- package/dist/kit/index.js +355 -16
- package/dist/kit/index.js.map +1 -1
- package/dist/ordered-list/index.cjs +373 -16
- package/dist/ordered-list/index.cjs.map +1 -1
- package/dist/ordered-list/index.d.cts +67 -2
- package/dist/ordered-list/index.d.ts +67 -2
- package/dist/ordered-list/index.js +362 -15
- package/dist/ordered-list/index.js.map +1 -1
- package/package.json +8 -5
- package/src/item/list-item.ts +5 -1
- package/src/ordered-list/index.ts +12 -0
- package/src/ordered-list/ordered-list.ts +145 -10
- package/src/ordered-list/roman.ts +295 -0
- package/src/ordered-list/utils.ts +97 -9
|
@@ -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
|
-
|
|
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 =
|
|
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,
|
|
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];
|
|
@@ -96,8 +305,10 @@ function collectOrderedListItems(lines) {
|
|
|
96
305
|
sawBlankLine = true;
|
|
97
306
|
nextLineIndex += 1;
|
|
98
307
|
} else if (nextLine.match(INDENTED_LINE_REGEX)) {
|
|
308
|
+
const leadingWhitespace = nextLine.length - nextLine.trimStart().length;
|
|
309
|
+
const contentIndent = indentLevel + marker.length + 1;
|
|
99
310
|
itemLines.push(nextLine);
|
|
100
|
-
itemContentLines.push(nextLine.slice(
|
|
311
|
+
itemContentLines.push(nextLine.slice(Math.min(leadingWhitespace, contentIndent)));
|
|
101
312
|
nextLineIndex += 1;
|
|
102
313
|
} else {
|
|
103
314
|
if (sawBlankLine) {
|
|
@@ -110,7 +321,8 @@ function collectOrderedListItems(lines) {
|
|
|
110
321
|
}
|
|
111
322
|
listItems.push({
|
|
112
323
|
indent: indentLevel,
|
|
113
|
-
number:
|
|
324
|
+
number: itemNumber,
|
|
325
|
+
type: markerType,
|
|
114
326
|
content: itemContentLines.join("\n").trim(),
|
|
115
327
|
contentLines: itemContentLines,
|
|
116
328
|
raw: itemLines.join("\n")
|
|
@@ -120,6 +332,44 @@ function collectOrderedListItems(lines) {
|
|
|
120
332
|
}
|
|
121
333
|
return [listItems, consumed];
|
|
122
334
|
}
|
|
335
|
+
var PLAIN_TEXT_ORDERED_LIST_LINE_REGEX = new RegExp(
|
|
336
|
+
`^(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+(.+)$`
|
|
337
|
+
);
|
|
338
|
+
function parsePlainTextOrderedListPaste(text) {
|
|
339
|
+
const lines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
340
|
+
if (lines.length === 0) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
const parsedItems = [];
|
|
344
|
+
for (const line of lines) {
|
|
345
|
+
const match = line.trim().match(PLAIN_TEXT_ORDERED_LIST_LINE_REGEX);
|
|
346
|
+
if (!match) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
parsedItems.push({
|
|
350
|
+
marker: match[1],
|
|
351
|
+
content: match[3]
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
const markers = parsedItems.map((item) => item.marker);
|
|
355
|
+
if (!areOrderedListMarkersSequential(markers)) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const attrs = buildOrderedListAttrsFromMarker(parsedItems[0].marker);
|
|
359
|
+
return {
|
|
360
|
+
type: "orderedList",
|
|
361
|
+
attrs,
|
|
362
|
+
content: parsedItems.map((item) => ({
|
|
363
|
+
type: "listItem",
|
|
364
|
+
content: [
|
|
365
|
+
{
|
|
366
|
+
type: "paragraph",
|
|
367
|
+
content: [{ type: "text", text: item.content }]
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
}))
|
|
371
|
+
};
|
|
372
|
+
}
|
|
123
373
|
function buildNestedStructure(items, baseIndent, lexer) {
|
|
124
374
|
const result = [];
|
|
125
375
|
let currentIndex = 0;
|
|
@@ -154,6 +404,7 @@ function buildNestedStructure(items, baseIndent, lexer) {
|
|
|
154
404
|
type: "list",
|
|
155
405
|
ordered: true,
|
|
156
406
|
start: nestedItems[0].number,
|
|
407
|
+
typeMarker: nestedItems[0].type,
|
|
157
408
|
items: nestedListItems,
|
|
158
409
|
raw: nestedItems.map((nestedItem) => nestedItem.raw).join("\n")
|
|
159
410
|
});
|
|
@@ -205,6 +456,27 @@ function parseListItems(items, helpers) {
|
|
|
205
456
|
var ListItemName = "listItem";
|
|
206
457
|
var TextStyleName = "textStyle";
|
|
207
458
|
var orderedListInputRegex = /^(\d+)\.\s$/;
|
|
459
|
+
function cssListStyleTypeToHtmlType(style) {
|
|
460
|
+
const match = style.match(/list-style-type\s*:\s*([^;]+)/i);
|
|
461
|
+
if (!match) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
const cssValue = match[1].trim().toLowerCase();
|
|
465
|
+
switch (cssValue) {
|
|
466
|
+
case "upper-roman":
|
|
467
|
+
return "I";
|
|
468
|
+
case "lower-roman":
|
|
469
|
+
return "i";
|
|
470
|
+
case "upper-alpha":
|
|
471
|
+
case "upper-latin":
|
|
472
|
+
return "A";
|
|
473
|
+
case "lower-alpha":
|
|
474
|
+
case "lower-latin":
|
|
475
|
+
return "a";
|
|
476
|
+
default:
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
208
480
|
var OrderedList = import_core.Node.create({
|
|
209
481
|
name: "orderedList",
|
|
210
482
|
addOptions() {
|
|
@@ -229,7 +501,30 @@ var OrderedList = import_core.Node.create({
|
|
|
229
501
|
},
|
|
230
502
|
type: {
|
|
231
503
|
default: null,
|
|
232
|
-
parseHTML: (element) =>
|
|
504
|
+
parseHTML: (element) => {
|
|
505
|
+
const htmlType = element.getAttribute("type");
|
|
506
|
+
if (htmlType) {
|
|
507
|
+
return htmlType;
|
|
508
|
+
}
|
|
509
|
+
const style = element.getAttribute("style");
|
|
510
|
+
if (style) {
|
|
511
|
+
const mappedFromOl = cssListStyleTypeToHtmlType(style);
|
|
512
|
+
if (mappedFromOl) {
|
|
513
|
+
return mappedFromOl;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
const firstLi = element.querySelector("li");
|
|
517
|
+
if (firstLi) {
|
|
518
|
+
const liStyle = firstLi.getAttribute("style");
|
|
519
|
+
if (liStyle) {
|
|
520
|
+
const mappedFromLi = cssListStyleTypeToHtmlType(liStyle);
|
|
521
|
+
if (mappedFromLi) {
|
|
522
|
+
return mappedFromLi;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
233
528
|
}
|
|
234
529
|
};
|
|
235
530
|
},
|
|
@@ -241,8 +536,15 @@ var OrderedList = import_core.Node.create({
|
|
|
241
536
|
];
|
|
242
537
|
},
|
|
243
538
|
renderHTML({ HTMLAttributes }) {
|
|
244
|
-
const { start, ...
|
|
245
|
-
|
|
539
|
+
const { start, type, ...attributesWithoutType } = HTMLAttributes;
|
|
540
|
+
const attrs = (0, import_core.mergeAttributes)(this.options.HTMLAttributes, attributesWithoutType);
|
|
541
|
+
if (start !== 1) {
|
|
542
|
+
attrs.start = start;
|
|
543
|
+
}
|
|
544
|
+
if (type && type !== "1") {
|
|
545
|
+
attrs.type = type;
|
|
546
|
+
}
|
|
547
|
+
return ["ol", attrs, 0];
|
|
246
548
|
},
|
|
247
549
|
markdownTokenName: "list",
|
|
248
550
|
parseMarkdown: (token, helpers) => {
|
|
@@ -250,11 +552,19 @@ var OrderedList = import_core.Node.create({
|
|
|
250
552
|
return [];
|
|
251
553
|
}
|
|
252
554
|
const startValue = token.start || 1;
|
|
555
|
+
const typeValue = token.typeMarker;
|
|
253
556
|
const content = token.items ? parseListItems(token.items, helpers) : [];
|
|
557
|
+
const attrs = {};
|
|
254
558
|
if (startValue !== 1) {
|
|
559
|
+
attrs.start = startValue;
|
|
560
|
+
}
|
|
561
|
+
if (typeValue) {
|
|
562
|
+
attrs.type = typeValue;
|
|
563
|
+
}
|
|
564
|
+
if (Object.keys(attrs).length > 0) {
|
|
255
565
|
return {
|
|
256
566
|
type: "orderedList",
|
|
257
|
-
attrs
|
|
567
|
+
attrs,
|
|
258
568
|
content
|
|
259
569
|
};
|
|
260
570
|
}
|
|
@@ -273,12 +583,12 @@ var OrderedList = import_core.Node.create({
|
|
|
273
583
|
name: "orderedList",
|
|
274
584
|
level: "block",
|
|
275
585
|
start: (src) => {
|
|
276
|
-
const match = src.match(
|
|
586
|
+
const match = src.match(ORDERED_LIST_LINE_START_REGEX);
|
|
277
587
|
const index = match == null ? void 0 : match.index;
|
|
278
588
|
return index !== void 0 ? index : -1;
|
|
279
589
|
},
|
|
280
590
|
tokenize: (src, _tokens, lexer) => {
|
|
281
|
-
var _a;
|
|
591
|
+
var _a, _b;
|
|
282
592
|
const lines = src.split("\n");
|
|
283
593
|
const [listItems, consumed] = collectOrderedListItems(lines);
|
|
284
594
|
if (listItems.length === 0) {
|
|
@@ -289,10 +599,12 @@ var OrderedList = import_core.Node.create({
|
|
|
289
599
|
return void 0;
|
|
290
600
|
}
|
|
291
601
|
const startValue = ((_a = listItems[0]) == null ? void 0 : _a.number) || 1;
|
|
602
|
+
const typeMarker = (_b = listItems[0]) == null ? void 0 : _b.type;
|
|
292
603
|
return {
|
|
293
604
|
type: "list",
|
|
294
605
|
ordered: true,
|
|
295
606
|
start: startValue,
|
|
607
|
+
typeMarker,
|
|
296
608
|
items,
|
|
297
609
|
raw: lines.slice(0, consumed).join("\n")
|
|
298
610
|
};
|
|
@@ -316,12 +628,47 @@ var OrderedList = import_core.Node.create({
|
|
|
316
628
|
"Mod-Shift-7": () => this.editor.commands.toggleOrderedList()
|
|
317
629
|
};
|
|
318
630
|
},
|
|
631
|
+
addProseMirrorPlugins() {
|
|
632
|
+
return [
|
|
633
|
+
new import_state.Plugin({
|
|
634
|
+
props: {
|
|
635
|
+
handlePaste: (view, event) => {
|
|
636
|
+
var _a, _b;
|
|
637
|
+
const html = (_a = event.clipboardData) == null ? void 0 : _a.getData("text/html");
|
|
638
|
+
if (html == null ? void 0 : html.trim()) {
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
const text = (_b = event.clipboardData) == null ? void 0 : _b.getData("text/plain");
|
|
642
|
+
if (!text) {
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
const orderedListContent = parsePlainTextOrderedListPaste(text);
|
|
646
|
+
if (!orderedListContent) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
const orderedListNode = view.state.schema.nodeFromJSON(orderedListContent);
|
|
651
|
+
const tr = view.state.tr.replaceSelectionWith(orderedListNode);
|
|
652
|
+
view.dispatch(tr);
|
|
653
|
+
return true;
|
|
654
|
+
} catch {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
})
|
|
660
|
+
];
|
|
661
|
+
},
|
|
319
662
|
addInputRules() {
|
|
663
|
+
const joinPredicate = (match, node) => {
|
|
664
|
+
const hasDefaultType = !node.attrs.type || node.attrs.type === "1";
|
|
665
|
+
return hasDefaultType && node.childCount + node.attrs.start === +match[1];
|
|
666
|
+
};
|
|
320
667
|
let inputRule = (0, import_core.wrappingInputRule)({
|
|
321
668
|
find: orderedListInputRegex,
|
|
322
669
|
type: this.type,
|
|
323
670
|
getAttributes: (match) => ({ start: +match[1] }),
|
|
324
|
-
joinPredicate
|
|
671
|
+
joinPredicate
|
|
325
672
|
});
|
|
326
673
|
if (this.options.keepMarks || this.options.keepAttributes) {
|
|
327
674
|
inputRule = (0, import_core.wrappingInputRule)({
|
|
@@ -330,7 +677,7 @@ var OrderedList = import_core.Node.create({
|
|
|
330
677
|
keepMarks: this.options.keepMarks,
|
|
331
678
|
keepAttributes: this.options.keepAttributes,
|
|
332
679
|
getAttributes: (match) => ({ start: +match[1], ...this.editor.getAttributes(TextStyleName) }),
|
|
333
|
-
joinPredicate
|
|
680
|
+
joinPredicate,
|
|
334
681
|
editor: this.editor
|
|
335
682
|
});
|
|
336
683
|
}
|
|
@@ -339,7 +686,17 @@ var OrderedList = import_core.Node.create({
|
|
|
339
686
|
});
|
|
340
687
|
// Annotate the CommonJS export names for ESM import in node:
|
|
341
688
|
0 && (module.exports = {
|
|
689
|
+
ORDERED_LIST_MARKER_PATTERN,
|
|
342
690
|
OrderedList,
|
|
343
|
-
|
|
691
|
+
areOrderedListMarkersSequential,
|
|
692
|
+
buildOrderedListAttrsFromMarker,
|
|
693
|
+
detectMarkerType,
|
|
694
|
+
getListMarker,
|
|
695
|
+
markerToStart,
|
|
696
|
+
orderedListInputRegex,
|
|
697
|
+
parseListMarker,
|
|
698
|
+
parsePlainTextOrderedListPaste,
|
|
699
|
+
toRoman,
|
|
700
|
+
toRomanUpper
|
|
344
701
|
});
|
|
345
702
|
//# 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 // Strip the indentation only up to the whitespace that is actually present,\n // so an under-indented line (e.g. a single leading space) keeps its first character.\n const leadingWhitespace = nextLine.length - nextLine.trimStart().length\n const contentIndent = indentLevel + marker.length + 1\n itemLines.push(nextLine)\n itemContentLines.push(nextLine.slice(Math.min(leadingWhitespace, contentIndent)))\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":[]}
|