@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Node } from '@tiptap/core';
|
|
1
|
+
import { Node, JSONContent } from '@tiptap/core';
|
|
2
2
|
|
|
3
3
|
interface OrderedListOptions {
|
|
4
4
|
/**
|
|
@@ -49,4 +49,69 @@ declare const orderedListInputRegex: RegExp;
|
|
|
49
49
|
*/
|
|
50
50
|
declare const OrderedList: Node<OrderedListOptions, any>;
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Marker segment for ordered list lines: numeric, roman, or 1–2 letter alpha.
|
|
54
|
+
* Roman is matched before alpha so "iii" is roman; invalid romans like "aa" fall through to alpha.
|
|
55
|
+
*/
|
|
56
|
+
declare const ORDERED_LIST_MARKER_PATTERN: string;
|
|
57
|
+
/**
|
|
58
|
+
* Convert a number to lowercase roman numerals.
|
|
59
|
+
* @example toRoman(1) // 'i'
|
|
60
|
+
* @example toRoman(4) // 'iv'
|
|
61
|
+
*/
|
|
62
|
+
declare function toRoman(num: number): string;
|
|
63
|
+
/**
|
|
64
|
+
* Convert a number to uppercase roman numerals.
|
|
65
|
+
* @example toRomanUpper(1) // 'I'
|
|
66
|
+
* @example toRomanUpper(4) // 'IV'
|
|
67
|
+
*/
|
|
68
|
+
declare function toRomanUpper(num: number): string;
|
|
69
|
+
/**
|
|
70
|
+
* Extract the list marker type from a marker string.
|
|
71
|
+
* Supports "1", "a", "A", "i", "I" marker styles.
|
|
72
|
+
*
|
|
73
|
+
* @param marker The text content of the list marker (e.g. "a", "1", "iii", "b")
|
|
74
|
+
* @returns The normalized type string, or undefined for default numeric type
|
|
75
|
+
*/
|
|
76
|
+
declare function detectMarkerType(marker: string): string | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Convert a list marker string to its numeric start position.
|
|
79
|
+
*
|
|
80
|
+
* @param marker The text content of the list marker (e.g. "3", "b", "II")
|
|
81
|
+
* @returns The 1-based start value for the ordered list
|
|
82
|
+
*/
|
|
83
|
+
declare function markerToStart(marker: string): number;
|
|
84
|
+
/**
|
|
85
|
+
* Returns true when all markers share the same style and increment by 1.
|
|
86
|
+
* Style is inferred from the first marker so ambiguous letters (e.g. "c", "i")
|
|
87
|
+
* are not re-classified differently on later lines.
|
|
88
|
+
*/
|
|
89
|
+
declare function areOrderedListMarkersSequential(markers: string[]): boolean;
|
|
90
|
+
interface ParsedListMarker {
|
|
91
|
+
type?: string;
|
|
92
|
+
start: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Parse a list marker into HTML ordered-list attrs (type + start).
|
|
96
|
+
*/
|
|
97
|
+
declare function parseListMarker(marker: string): ParsedListMarker;
|
|
98
|
+
/**
|
|
99
|
+
* Build orderedList node attrs from the first list item marker.
|
|
100
|
+
*/
|
|
101
|
+
declare function buildOrderedListAttrsFromMarker(marker: string): Record<string, string | number>;
|
|
102
|
+
/**
|
|
103
|
+
* Returns the list marker prefix for a given item at a given index.
|
|
104
|
+
*
|
|
105
|
+
* @param type The list type attribute (e.g. "a", "A", "i", "I", null/undefined for default)
|
|
106
|
+
* @param index The zero-based index of the list item
|
|
107
|
+
* @param separator The separator to use (default: ". ")
|
|
108
|
+
* @returns The marker string (e.g. "a. ", "I. ", "1. ")
|
|
109
|
+
*/
|
|
110
|
+
declare function getListMarker(type: string | null | undefined, index: number, separator?: string): string;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Parse plain-text pasted ordered list lines into JSONContent, or null if not a typed list.
|
|
114
|
+
*/
|
|
115
|
+
declare function parsePlainTextOrderedListPaste(text: string): JSONContent | null;
|
|
116
|
+
|
|
117
|
+
export { ORDERED_LIST_MARKER_PATTERN, OrderedList, type OrderedListOptions, areOrderedListMarkersSequential, buildOrderedListAttrsFromMarker, detectMarkerType, getListMarker, markerToStart, orderedListInputRegex, parseListMarker, parsePlainTextOrderedListPaste, toRoman, toRomanUpper };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Node } from '@tiptap/core';
|
|
1
|
+
import { Node, JSONContent } from '@tiptap/core';
|
|
2
2
|
|
|
3
3
|
interface OrderedListOptions {
|
|
4
4
|
/**
|
|
@@ -49,4 +49,69 @@ declare const orderedListInputRegex: RegExp;
|
|
|
49
49
|
*/
|
|
50
50
|
declare const OrderedList: Node<OrderedListOptions, any>;
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Marker segment for ordered list lines: numeric, roman, or 1–2 letter alpha.
|
|
54
|
+
* Roman is matched before alpha so "iii" is roman; invalid romans like "aa" fall through to alpha.
|
|
55
|
+
*/
|
|
56
|
+
declare const ORDERED_LIST_MARKER_PATTERN: string;
|
|
57
|
+
/**
|
|
58
|
+
* Convert a number to lowercase roman numerals.
|
|
59
|
+
* @example toRoman(1) // 'i'
|
|
60
|
+
* @example toRoman(4) // 'iv'
|
|
61
|
+
*/
|
|
62
|
+
declare function toRoman(num: number): string;
|
|
63
|
+
/**
|
|
64
|
+
* Convert a number to uppercase roman numerals.
|
|
65
|
+
* @example toRomanUpper(1) // 'I'
|
|
66
|
+
* @example toRomanUpper(4) // 'IV'
|
|
67
|
+
*/
|
|
68
|
+
declare function toRomanUpper(num: number): string;
|
|
69
|
+
/**
|
|
70
|
+
* Extract the list marker type from a marker string.
|
|
71
|
+
* Supports "1", "a", "A", "i", "I" marker styles.
|
|
72
|
+
*
|
|
73
|
+
* @param marker The text content of the list marker (e.g. "a", "1", "iii", "b")
|
|
74
|
+
* @returns The normalized type string, or undefined for default numeric type
|
|
75
|
+
*/
|
|
76
|
+
declare function detectMarkerType(marker: string): string | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Convert a list marker string to its numeric start position.
|
|
79
|
+
*
|
|
80
|
+
* @param marker The text content of the list marker (e.g. "3", "b", "II")
|
|
81
|
+
* @returns The 1-based start value for the ordered list
|
|
82
|
+
*/
|
|
83
|
+
declare function markerToStart(marker: string): number;
|
|
84
|
+
/**
|
|
85
|
+
* Returns true when all markers share the same style and increment by 1.
|
|
86
|
+
* Style is inferred from the first marker so ambiguous letters (e.g. "c", "i")
|
|
87
|
+
* are not re-classified differently on later lines.
|
|
88
|
+
*/
|
|
89
|
+
declare function areOrderedListMarkersSequential(markers: string[]): boolean;
|
|
90
|
+
interface ParsedListMarker {
|
|
91
|
+
type?: string;
|
|
92
|
+
start: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Parse a list marker into HTML ordered-list attrs (type + start).
|
|
96
|
+
*/
|
|
97
|
+
declare function parseListMarker(marker: string): ParsedListMarker;
|
|
98
|
+
/**
|
|
99
|
+
* Build orderedList node attrs from the first list item marker.
|
|
100
|
+
*/
|
|
101
|
+
declare function buildOrderedListAttrsFromMarker(marker: string): Record<string, string | number>;
|
|
102
|
+
/**
|
|
103
|
+
* Returns the list marker prefix for a given item at a given index.
|
|
104
|
+
*
|
|
105
|
+
* @param type The list type attribute (e.g. "a", "A", "i", "I", null/undefined for default)
|
|
106
|
+
* @param index The zero-based index of the list item
|
|
107
|
+
* @param separator The separator to use (default: ". ")
|
|
108
|
+
* @returns The marker string (e.g. "a. ", "I. ", "1. ")
|
|
109
|
+
*/
|
|
110
|
+
declare function getListMarker(type: string | null | undefined, index: number, separator?: string): string;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Parse plain-text pasted ordered list lines into JSONContent, or null if not a typed list.
|
|
114
|
+
*/
|
|
115
|
+
declare function parsePlainTextOrderedListPaste(text: string): JSONContent | null;
|
|
116
|
+
|
|
117
|
+
export { ORDERED_LIST_MARKER_PATTERN, OrderedList, type OrderedListOptions, areOrderedListMarkersSequential, buildOrderedListAttrsFromMarker, detectMarkerType, getListMarker, markerToStart, orderedListInputRegex, parseListMarker, parsePlainTextOrderedListPaste, toRoman, toRomanUpper };
|
|
@@ -1,15 +1,211 @@
|
|
|
1
1
|
// src/ordered-list/ordered-list.ts
|
|
2
|
+
import { Plugin } from "@tiptap/pm/state";
|
|
2
3
|
import { mergeAttributes, Node, wrappingInputRule } from "@tiptap/core";
|
|
3
4
|
|
|
5
|
+
// src/ordered-list/roman.ts
|
|
6
|
+
var ROMAN_NUMERALS = [
|
|
7
|
+
[1e3, "m"],
|
|
8
|
+
[900, "cm"],
|
|
9
|
+
[500, "d"],
|
|
10
|
+
[400, "cd"],
|
|
11
|
+
[100, "c"],
|
|
12
|
+
[90, "xc"],
|
|
13
|
+
[50, "l"],
|
|
14
|
+
[40, "xl"],
|
|
15
|
+
[10, "x"],
|
|
16
|
+
[9, "ix"],
|
|
17
|
+
[5, "v"],
|
|
18
|
+
[4, "iv"],
|
|
19
|
+
[1, "i"]
|
|
20
|
+
];
|
|
21
|
+
var ALPHA_NUMERALS = "abcdefghijklmnopqrstuvwxyz";
|
|
22
|
+
var ORDERED_LIST_ALPHA_MARKER_PATTERN = "[a-zA-Z]{1,2}";
|
|
23
|
+
var ORDERED_LIST_MARKER_PATTERN = String.raw`\d+|[ivxlcdmIVXLCDM]+|${ORDERED_LIST_ALPHA_MARKER_PATTERN}`;
|
|
24
|
+
function toRoman(num) {
|
|
25
|
+
let remaining = num;
|
|
26
|
+
let result = "";
|
|
27
|
+
for (const [value, numeral] of ROMAN_NUMERALS) {
|
|
28
|
+
while (remaining >= value) {
|
|
29
|
+
result += numeral;
|
|
30
|
+
remaining -= value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
function toRomanUpper(num) {
|
|
36
|
+
return toRoman(num).toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
function fromRoman(roman) {
|
|
39
|
+
const lower = roman.toLowerCase();
|
|
40
|
+
let index = 0;
|
|
41
|
+
let result = 0;
|
|
42
|
+
while (index < lower.length) {
|
|
43
|
+
let matched = false;
|
|
44
|
+
for (const [value, numeral] of ROMAN_NUMERALS) {
|
|
45
|
+
if (lower.startsWith(numeral, index)) {
|
|
46
|
+
result += value;
|
|
47
|
+
index += numeral.length;
|
|
48
|
+
matched = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!matched) {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
function isValidRoman(marker) {
|
|
59
|
+
if (!/^[ivxlcdmIVXLCDM]+$/.test(marker)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const value = fromRoman(marker);
|
|
63
|
+
if (value <= 0) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const expected = marker === marker.toLowerCase() ? toRoman(value) : toRomanUpper(value);
|
|
67
|
+
return expected === marker;
|
|
68
|
+
}
|
|
69
|
+
function fromAlpha(marker) {
|
|
70
|
+
const lower = marker.toLowerCase();
|
|
71
|
+
if (lower.length === 1) {
|
|
72
|
+
return lower.charCodeAt(0) - "a".charCodeAt(0) + 1;
|
|
73
|
+
}
|
|
74
|
+
if (lower.length === 2) {
|
|
75
|
+
const first = lower.charCodeAt(0) - "a".charCodeAt(0);
|
|
76
|
+
const second = lower.charCodeAt(1) - "a".charCodeAt(0);
|
|
77
|
+
return (first + 1) * 26 + second + 1;
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
function toRomanAlpha(num) {
|
|
82
|
+
if (num <= 26) {
|
|
83
|
+
return ALPHA_NUMERALS[num - 1];
|
|
84
|
+
}
|
|
85
|
+
const first = Math.floor((num - 1) / 26) - 1;
|
|
86
|
+
const second = (num - 1) % 26;
|
|
87
|
+
if (first < 0) {
|
|
88
|
+
return ALPHA_NUMERALS[second];
|
|
89
|
+
}
|
|
90
|
+
return ALPHA_NUMERALS[first] + ALPHA_NUMERALS[second];
|
|
91
|
+
}
|
|
92
|
+
function detectMarkerType(marker) {
|
|
93
|
+
if (!marker || /^\d+$/.test(marker)) {
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
if (isValidRoman(marker)) {
|
|
97
|
+
return marker === marker.toLowerCase() ? "i" : "I";
|
|
98
|
+
}
|
|
99
|
+
if (/^[a-z]{1,2}$/.test(marker)) {
|
|
100
|
+
return "a";
|
|
101
|
+
}
|
|
102
|
+
if (/^[A-Z]{1,2}$/.test(marker)) {
|
|
103
|
+
return "A";
|
|
104
|
+
}
|
|
105
|
+
return void 0;
|
|
106
|
+
}
|
|
107
|
+
function markerToStart(marker) {
|
|
108
|
+
if (/^\d+$/.test(marker)) {
|
|
109
|
+
return parseInt(marker, 10);
|
|
110
|
+
}
|
|
111
|
+
const type = detectMarkerType(marker);
|
|
112
|
+
if (type === "i" || type === "I") {
|
|
113
|
+
return fromRoman(marker);
|
|
114
|
+
}
|
|
115
|
+
if (type === "a" || type === "A") {
|
|
116
|
+
const start = fromAlpha(marker);
|
|
117
|
+
return start > 0 ? start : 1;
|
|
118
|
+
}
|
|
119
|
+
const parsed = parseInt(marker, 10);
|
|
120
|
+
return Number.isNaN(parsed) ? 1 : parsed;
|
|
121
|
+
}
|
|
122
|
+
function startToMarker(type, start) {
|
|
123
|
+
if (type === "numeric") {
|
|
124
|
+
return String(start);
|
|
125
|
+
}
|
|
126
|
+
switch (type) {
|
|
127
|
+
case "a":
|
|
128
|
+
return toRomanAlpha(start);
|
|
129
|
+
case "A":
|
|
130
|
+
return toRomanAlpha(start).toUpperCase();
|
|
131
|
+
case "i":
|
|
132
|
+
return toRoman(start);
|
|
133
|
+
case "I":
|
|
134
|
+
return toRomanUpper(start);
|
|
135
|
+
default:
|
|
136
|
+
return String(start);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function areOrderedListMarkersSequential(markers) {
|
|
140
|
+
var _a;
|
|
141
|
+
if (markers.length === 0) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
const firstType = (_a = detectMarkerType(markers[0])) != null ? _a : "numeric";
|
|
145
|
+
const firstStart = markerToStart(markers[0]);
|
|
146
|
+
if (firstStart < 1) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
for (let i = 0; i < markers.length; i++) {
|
|
150
|
+
const expected = startToMarker(firstType, firstStart + i);
|
|
151
|
+
if (markers[i] !== expected) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
function parseListMarker(marker) {
|
|
158
|
+
return {
|
|
159
|
+
type: detectMarkerType(marker),
|
|
160
|
+
start: markerToStart(marker)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function buildOrderedListAttrsFromMarker(marker) {
|
|
164
|
+
const { type, start } = parseListMarker(marker);
|
|
165
|
+
const attrs = {};
|
|
166
|
+
if (type) {
|
|
167
|
+
attrs.type = type;
|
|
168
|
+
}
|
|
169
|
+
if (start !== 1) {
|
|
170
|
+
attrs.start = start;
|
|
171
|
+
}
|
|
172
|
+
return attrs;
|
|
173
|
+
}
|
|
174
|
+
function getListMarker(type, index, separator = ". ") {
|
|
175
|
+
const position = index + 1;
|
|
176
|
+
if (!type || type === "1") {
|
|
177
|
+
return `${position}${separator}`;
|
|
178
|
+
}
|
|
179
|
+
switch (type) {
|
|
180
|
+
case "a":
|
|
181
|
+
return `${toRomanAlpha(position)}${separator}`;
|
|
182
|
+
case "A":
|
|
183
|
+
return `${toRomanAlpha(position).toUpperCase()}${separator}`;
|
|
184
|
+
case "i":
|
|
185
|
+
return `${toRoman(position)}${separator}`;
|
|
186
|
+
case "I":
|
|
187
|
+
return `${toRomanUpper(position)}${separator}`;
|
|
188
|
+
default:
|
|
189
|
+
return `${position}${separator}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
4
193
|
// src/ordered-list/utils.ts
|
|
5
|
-
var ORDERED_LIST_ITEM_REGEX =
|
|
194
|
+
var ORDERED_LIST_ITEM_REGEX = new RegExp(
|
|
195
|
+
`^(\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+(.*)$`
|
|
196
|
+
);
|
|
197
|
+
var ORDERED_LIST_LINE_START_REGEX = new RegExp(
|
|
198
|
+
`^(\\s*)(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+`
|
|
199
|
+
);
|
|
6
200
|
var INDENTED_LINE_REGEX = /^\s/;
|
|
201
|
+
function isOrderedListMarkerLine(line) {
|
|
202
|
+
return ORDERED_LIST_ITEM_REGEX.test(line.trimStart());
|
|
203
|
+
}
|
|
7
204
|
function isBlockContentLine(line) {
|
|
8
205
|
const trimmedLine = line.trimStart();
|
|
9
206
|
return (
|
|
10
207
|
// oxlint-disable-next-line prefer-string-starts-ends-with
|
|
11
|
-
/^[-+*]\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
|
|
12
|
-
/^\d+\.\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
|
|
208
|
+
/^[-+*]\s+/.test(trimmedLine) || isOrderedListMarkerLine(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
|
|
13
209
|
/^>\s?/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
|
|
14
210
|
/^```/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
|
|
15
211
|
/^~~~/.test(trimmedLine)
|
|
@@ -51,8 +247,11 @@ function collectOrderedListItems(lines) {
|
|
|
51
247
|
if (!match) {
|
|
52
248
|
break;
|
|
53
249
|
}
|
|
54
|
-
const [, indent,
|
|
250
|
+
const [, indent, marker, _separator, content] = match;
|
|
55
251
|
const indentLevel = indent.length;
|
|
252
|
+
const number = parseInt(marker, 10);
|
|
253
|
+
const markerType = isNaN(number) ? detectMarkerType(marker) : void 0;
|
|
254
|
+
const itemNumber = isNaN(number) ? markerToStart(marker) : number;
|
|
56
255
|
const itemContentLines = [content];
|
|
57
256
|
let nextLineIndex = currentLineIndex + 1;
|
|
58
257
|
const itemLines = [line];
|
|
@@ -69,8 +268,10 @@ function collectOrderedListItems(lines) {
|
|
|
69
268
|
sawBlankLine = true;
|
|
70
269
|
nextLineIndex += 1;
|
|
71
270
|
} else if (nextLine.match(INDENTED_LINE_REGEX)) {
|
|
271
|
+
const leadingWhitespace = nextLine.length - nextLine.trimStart().length;
|
|
272
|
+
const contentIndent = indentLevel + marker.length + 1;
|
|
72
273
|
itemLines.push(nextLine);
|
|
73
|
-
itemContentLines.push(nextLine.slice(
|
|
274
|
+
itemContentLines.push(nextLine.slice(Math.min(leadingWhitespace, contentIndent)));
|
|
74
275
|
nextLineIndex += 1;
|
|
75
276
|
} else {
|
|
76
277
|
if (sawBlankLine) {
|
|
@@ -83,7 +284,8 @@ function collectOrderedListItems(lines) {
|
|
|
83
284
|
}
|
|
84
285
|
listItems.push({
|
|
85
286
|
indent: indentLevel,
|
|
86
|
-
number:
|
|
287
|
+
number: itemNumber,
|
|
288
|
+
type: markerType,
|
|
87
289
|
content: itemContentLines.join("\n").trim(),
|
|
88
290
|
contentLines: itemContentLines,
|
|
89
291
|
raw: itemLines.join("\n")
|
|
@@ -93,6 +295,44 @@ function collectOrderedListItems(lines) {
|
|
|
93
295
|
}
|
|
94
296
|
return [listItems, consumed];
|
|
95
297
|
}
|
|
298
|
+
var PLAIN_TEXT_ORDERED_LIST_LINE_REGEX = new RegExp(
|
|
299
|
+
`^(${ORDERED_LIST_MARKER_PATTERN})([.)])\\s+(.+)$`
|
|
300
|
+
);
|
|
301
|
+
function parsePlainTextOrderedListPaste(text) {
|
|
302
|
+
const lines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
303
|
+
if (lines.length === 0) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
const parsedItems = [];
|
|
307
|
+
for (const line of lines) {
|
|
308
|
+
const match = line.trim().match(PLAIN_TEXT_ORDERED_LIST_LINE_REGEX);
|
|
309
|
+
if (!match) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
parsedItems.push({
|
|
313
|
+
marker: match[1],
|
|
314
|
+
content: match[3]
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
const markers = parsedItems.map((item) => item.marker);
|
|
318
|
+
if (!areOrderedListMarkersSequential(markers)) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
const attrs = buildOrderedListAttrsFromMarker(parsedItems[0].marker);
|
|
322
|
+
return {
|
|
323
|
+
type: "orderedList",
|
|
324
|
+
attrs,
|
|
325
|
+
content: parsedItems.map((item) => ({
|
|
326
|
+
type: "listItem",
|
|
327
|
+
content: [
|
|
328
|
+
{
|
|
329
|
+
type: "paragraph",
|
|
330
|
+
content: [{ type: "text", text: item.content }]
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}))
|
|
334
|
+
};
|
|
335
|
+
}
|
|
96
336
|
function buildNestedStructure(items, baseIndent, lexer) {
|
|
97
337
|
const result = [];
|
|
98
338
|
let currentIndex = 0;
|
|
@@ -127,6 +367,7 @@ function buildNestedStructure(items, baseIndent, lexer) {
|
|
|
127
367
|
type: "list",
|
|
128
368
|
ordered: true,
|
|
129
369
|
start: nestedItems[0].number,
|
|
370
|
+
typeMarker: nestedItems[0].type,
|
|
130
371
|
items: nestedListItems,
|
|
131
372
|
raw: nestedItems.map((nestedItem) => nestedItem.raw).join("\n")
|
|
132
373
|
});
|
|
@@ -178,6 +419,27 @@ function parseListItems(items, helpers) {
|
|
|
178
419
|
var ListItemName = "listItem";
|
|
179
420
|
var TextStyleName = "textStyle";
|
|
180
421
|
var orderedListInputRegex = /^(\d+)\.\s$/;
|
|
422
|
+
function cssListStyleTypeToHtmlType(style) {
|
|
423
|
+
const match = style.match(/list-style-type\s*:\s*([^;]+)/i);
|
|
424
|
+
if (!match) {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
const cssValue = match[1].trim().toLowerCase();
|
|
428
|
+
switch (cssValue) {
|
|
429
|
+
case "upper-roman":
|
|
430
|
+
return "I";
|
|
431
|
+
case "lower-roman":
|
|
432
|
+
return "i";
|
|
433
|
+
case "upper-alpha":
|
|
434
|
+
case "upper-latin":
|
|
435
|
+
return "A";
|
|
436
|
+
case "lower-alpha":
|
|
437
|
+
case "lower-latin":
|
|
438
|
+
return "a";
|
|
439
|
+
default:
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
181
443
|
var OrderedList = Node.create({
|
|
182
444
|
name: "orderedList",
|
|
183
445
|
addOptions() {
|
|
@@ -202,7 +464,30 @@ var OrderedList = Node.create({
|
|
|
202
464
|
},
|
|
203
465
|
type: {
|
|
204
466
|
default: null,
|
|
205
|
-
parseHTML: (element) =>
|
|
467
|
+
parseHTML: (element) => {
|
|
468
|
+
const htmlType = element.getAttribute("type");
|
|
469
|
+
if (htmlType) {
|
|
470
|
+
return htmlType;
|
|
471
|
+
}
|
|
472
|
+
const style = element.getAttribute("style");
|
|
473
|
+
if (style) {
|
|
474
|
+
const mappedFromOl = cssListStyleTypeToHtmlType(style);
|
|
475
|
+
if (mappedFromOl) {
|
|
476
|
+
return mappedFromOl;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
const firstLi = element.querySelector("li");
|
|
480
|
+
if (firstLi) {
|
|
481
|
+
const liStyle = firstLi.getAttribute("style");
|
|
482
|
+
if (liStyle) {
|
|
483
|
+
const mappedFromLi = cssListStyleTypeToHtmlType(liStyle);
|
|
484
|
+
if (mappedFromLi) {
|
|
485
|
+
return mappedFromLi;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
206
491
|
}
|
|
207
492
|
};
|
|
208
493
|
},
|
|
@@ -214,8 +499,15 @@ var OrderedList = Node.create({
|
|
|
214
499
|
];
|
|
215
500
|
},
|
|
216
501
|
renderHTML({ HTMLAttributes }) {
|
|
217
|
-
const { start, ...
|
|
218
|
-
|
|
502
|
+
const { start, type, ...attributesWithoutType } = HTMLAttributes;
|
|
503
|
+
const attrs = mergeAttributes(this.options.HTMLAttributes, attributesWithoutType);
|
|
504
|
+
if (start !== 1) {
|
|
505
|
+
attrs.start = start;
|
|
506
|
+
}
|
|
507
|
+
if (type && type !== "1") {
|
|
508
|
+
attrs.type = type;
|
|
509
|
+
}
|
|
510
|
+
return ["ol", attrs, 0];
|
|
219
511
|
},
|
|
220
512
|
markdownTokenName: "list",
|
|
221
513
|
parseMarkdown: (token, helpers) => {
|
|
@@ -223,11 +515,19 @@ var OrderedList = Node.create({
|
|
|
223
515
|
return [];
|
|
224
516
|
}
|
|
225
517
|
const startValue = token.start || 1;
|
|
518
|
+
const typeValue = token.typeMarker;
|
|
226
519
|
const content = token.items ? parseListItems(token.items, helpers) : [];
|
|
520
|
+
const attrs = {};
|
|
227
521
|
if (startValue !== 1) {
|
|
522
|
+
attrs.start = startValue;
|
|
523
|
+
}
|
|
524
|
+
if (typeValue) {
|
|
525
|
+
attrs.type = typeValue;
|
|
526
|
+
}
|
|
527
|
+
if (Object.keys(attrs).length > 0) {
|
|
228
528
|
return {
|
|
229
529
|
type: "orderedList",
|
|
230
|
-
attrs
|
|
530
|
+
attrs,
|
|
231
531
|
content
|
|
232
532
|
};
|
|
233
533
|
}
|
|
@@ -246,12 +546,12 @@ var OrderedList = Node.create({
|
|
|
246
546
|
name: "orderedList",
|
|
247
547
|
level: "block",
|
|
248
548
|
start: (src) => {
|
|
249
|
-
const match = src.match(
|
|
549
|
+
const match = src.match(ORDERED_LIST_LINE_START_REGEX);
|
|
250
550
|
const index = match == null ? void 0 : match.index;
|
|
251
551
|
return index !== void 0 ? index : -1;
|
|
252
552
|
},
|
|
253
553
|
tokenize: (src, _tokens, lexer) => {
|
|
254
|
-
var _a;
|
|
554
|
+
var _a, _b;
|
|
255
555
|
const lines = src.split("\n");
|
|
256
556
|
const [listItems, consumed] = collectOrderedListItems(lines);
|
|
257
557
|
if (listItems.length === 0) {
|
|
@@ -262,10 +562,12 @@ var OrderedList = Node.create({
|
|
|
262
562
|
return void 0;
|
|
263
563
|
}
|
|
264
564
|
const startValue = ((_a = listItems[0]) == null ? void 0 : _a.number) || 1;
|
|
565
|
+
const typeMarker = (_b = listItems[0]) == null ? void 0 : _b.type;
|
|
265
566
|
return {
|
|
266
567
|
type: "list",
|
|
267
568
|
ordered: true,
|
|
268
569
|
start: startValue,
|
|
570
|
+
typeMarker,
|
|
269
571
|
items,
|
|
270
572
|
raw: lines.slice(0, consumed).join("\n")
|
|
271
573
|
};
|
|
@@ -289,12 +591,47 @@ var OrderedList = Node.create({
|
|
|
289
591
|
"Mod-Shift-7": () => this.editor.commands.toggleOrderedList()
|
|
290
592
|
};
|
|
291
593
|
},
|
|
594
|
+
addProseMirrorPlugins() {
|
|
595
|
+
return [
|
|
596
|
+
new Plugin({
|
|
597
|
+
props: {
|
|
598
|
+
handlePaste: (view, event) => {
|
|
599
|
+
var _a, _b;
|
|
600
|
+
const html = (_a = event.clipboardData) == null ? void 0 : _a.getData("text/html");
|
|
601
|
+
if (html == null ? void 0 : html.trim()) {
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
const text = (_b = event.clipboardData) == null ? void 0 : _b.getData("text/plain");
|
|
605
|
+
if (!text) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
const orderedListContent = parsePlainTextOrderedListPaste(text);
|
|
609
|
+
if (!orderedListContent) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
try {
|
|
613
|
+
const orderedListNode = view.state.schema.nodeFromJSON(orderedListContent);
|
|
614
|
+
const tr = view.state.tr.replaceSelectionWith(orderedListNode);
|
|
615
|
+
view.dispatch(tr);
|
|
616
|
+
return true;
|
|
617
|
+
} catch {
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
})
|
|
623
|
+
];
|
|
624
|
+
},
|
|
292
625
|
addInputRules() {
|
|
626
|
+
const joinPredicate = (match, node) => {
|
|
627
|
+
const hasDefaultType = !node.attrs.type || node.attrs.type === "1";
|
|
628
|
+
return hasDefaultType && node.childCount + node.attrs.start === +match[1];
|
|
629
|
+
};
|
|
293
630
|
let inputRule = wrappingInputRule({
|
|
294
631
|
find: orderedListInputRegex,
|
|
295
632
|
type: this.type,
|
|
296
633
|
getAttributes: (match) => ({ start: +match[1] }),
|
|
297
|
-
joinPredicate
|
|
634
|
+
joinPredicate
|
|
298
635
|
});
|
|
299
636
|
if (this.options.keepMarks || this.options.keepAttributes) {
|
|
300
637
|
inputRule = wrappingInputRule({
|
|
@@ -303,7 +640,7 @@ var OrderedList = Node.create({
|
|
|
303
640
|
keepMarks: this.options.keepMarks,
|
|
304
641
|
keepAttributes: this.options.keepAttributes,
|
|
305
642
|
getAttributes: (match) => ({ start: +match[1], ...this.editor.getAttributes(TextStyleName) }),
|
|
306
|
-
joinPredicate
|
|
643
|
+
joinPredicate,
|
|
307
644
|
editor: this.editor
|
|
308
645
|
});
|
|
309
646
|
}
|
|
@@ -311,7 +648,17 @@ var OrderedList = Node.create({
|
|
|
311
648
|
}
|
|
312
649
|
});
|
|
313
650
|
export {
|
|
651
|
+
ORDERED_LIST_MARKER_PATTERN,
|
|
314
652
|
OrderedList,
|
|
315
|
-
|
|
653
|
+
areOrderedListMarkersSequential,
|
|
654
|
+
buildOrderedListAttrsFromMarker,
|
|
655
|
+
detectMarkerType,
|
|
656
|
+
getListMarker,
|
|
657
|
+
markerToStart,
|
|
658
|
+
orderedListInputRegex,
|
|
659
|
+
parseListMarker,
|
|
660
|
+
parsePlainTextOrderedListPaste,
|
|
661
|
+
toRoman,
|
|
662
|
+
toRomanUpper
|
|
316
663
|
};
|
|
317
664
|
//# sourceMappingURL=index.js.map
|