@markuplint/parser-utils 4.0.0-alpha.6 → 4.0.0-alpha.8
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/LICENSE +1 -1
- package/lib/const.d.ts +2 -1
- package/lib/const.js +2 -1
- package/lib/ignore-block.d.ts +1 -1
- package/lib/ignore-block.js +69 -118
- package/lib/types.d.ts +1 -0
- package/package.json +5 -5
package/LICENSE
CHANGED
package/lib/const.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const reSplitterTag: RegExp;
|
|
|
11
11
|
* - U+0009 CHARACTER TABULATION (tab) => `\t`
|
|
12
12
|
* - U+000A LINE FEED (LF) => `\n`
|
|
13
13
|
* - U+000C FORM FEED (FF) => `\f`
|
|
14
|
+
* - U+000D CARRIAGE RETURN (CR) => `\r`
|
|
14
15
|
* - U+0020 SPACE => ` `
|
|
15
16
|
*/
|
|
16
|
-
export declare const defaultSpaces: readonly ["\t", "\n", "\f", " "];
|
|
17
|
+
export declare const defaultSpaces: readonly ["\t", "\n", "\f", "\r", " "];
|
package/lib/const.js
CHANGED
|
@@ -100,6 +100,7 @@ export const reSplitterTag = /<[^>]+>/g;
|
|
|
100
100
|
* - U+0009 CHARACTER TABULATION (tab) => `\t`
|
|
101
101
|
* - U+000A LINE FEED (LF) => `\n`
|
|
102
102
|
* - U+000C FORM FEED (FF) => `\f`
|
|
103
|
+
* - U+000D CARRIAGE RETURN (CR) => `\r`
|
|
103
104
|
* - U+0020 SPACE => ` `
|
|
104
105
|
*/
|
|
105
|
-
export const defaultSpaces = ['\t', '\n', '\f', ' '];
|
|
106
|
+
export const defaultSpaces = ['\t', '\n', '\f', '\r', ' '];
|
package/lib/ignore-block.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { IgnoreBlock, IgnoreTag } from './types.js';
|
|
2
2
|
import type { MLASTNode } from '@markuplint/ml-ast';
|
|
3
3
|
export declare function ignoreBlock(source: string, tags: readonly IgnoreTag[], maskChar?: string): IgnoreBlock;
|
|
4
|
-
export declare function restoreNode(nodeList: MLASTNode[], ignoreBlock: IgnoreBlock): MLASTNode[];
|
|
4
|
+
export declare function restoreNode(nodeList: MLASTNode[], ignoreBlock: IgnoreBlock, throwErrorWhenTagHasUnresolved?: boolean): MLASTNode[];
|
package/lib/ignore-block.js
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import { MASK_CHAR } from './const.js';
|
|
2
2
|
import { uuid } from './create-token.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { getCol, getLine } from './get-location.js';
|
|
4
|
+
import { ParserError } from './parser-error.js';
|
|
5
5
|
export function ignoreBlock(source, tags, maskChar = MASK_CHAR) {
|
|
6
6
|
let replaced = source;
|
|
7
7
|
const stack = [];
|
|
8
8
|
for (const tag of tags) {
|
|
9
|
-
// Replace tags in attributes
|
|
10
|
-
const attr = maskText(prepend(tag.start, '(?<=(?:"|\'))'), append(tag.end, '(?=(?:"|\'))'), replaced, (startTag, taggedCode, endTag) => {
|
|
11
|
-
const mask = maskChar.repeat(startTag.length) +
|
|
12
|
-
taggedCode.replaceAll(/[^\n]/g, maskChar) +
|
|
13
|
-
maskChar.repeat((endTag ?? '').length);
|
|
14
|
-
return mask;
|
|
15
|
-
});
|
|
16
|
-
replaced = attr.replaced;
|
|
17
|
-
stack.push(...attr.stack.map(res => ({ ...res, type: tag.type })));
|
|
18
|
-
// Replace tags in other nodes
|
|
19
9
|
const text = maskText(tag.start, tag.end, replaced, (startTag, taggedCode, endTag) => {
|
|
20
10
|
const mask = maskChar.repeat(startTag.length) +
|
|
21
11
|
taggedCode.replaceAll(/[^\n]/g, maskChar) +
|
|
@@ -49,6 +39,7 @@ function maskText(start, end, replaced, masking) {
|
|
|
49
39
|
startTag,
|
|
50
40
|
taggedCode,
|
|
51
41
|
endTag: endTag ?? null,
|
|
42
|
+
resolved: false,
|
|
52
43
|
});
|
|
53
44
|
/**
|
|
54
45
|
* It will not replace line breaks because detects line number.
|
|
@@ -62,103 +53,48 @@ function maskText(start, end, replaced, masking) {
|
|
|
62
53
|
}
|
|
63
54
|
export function restoreNode(
|
|
64
55
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
65
|
-
nodeList,
|
|
56
|
+
nodeList,
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
58
|
+
ignoreBlock, throwErrorWhenTagHasUnresolved = true) {
|
|
66
59
|
nodeList = [...nodeList];
|
|
67
60
|
const { source, stack, maskChar } = ignoreBlock;
|
|
68
|
-
for (const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const parentNode = node.parentNode;
|
|
74
|
-
const index = nodeList.indexOf(node);
|
|
75
|
-
const insertList = [];
|
|
76
|
-
let text = node.raw;
|
|
77
|
-
let pointer = 0;
|
|
78
|
-
for (const tag of stack) {
|
|
79
|
-
if (node.startOffset <= tag.index && tag.index < node.endOffset) {
|
|
80
|
-
const start = tag.index - node.startOffset;
|
|
81
|
-
const body = tag.startTag + tag.taggedCode + (tag.endTag ?? '');
|
|
82
|
-
const above = node.raw.slice(pointer, start);
|
|
83
|
-
const below = text.slice(above.length + body.length);
|
|
84
|
-
if (above) {
|
|
85
|
-
const offset = node.startOffset + pointer;
|
|
86
|
-
const { raw, startOffset, endOffset, startLine, endLine, startCol, endCol } = sliceFragment(source, offset, offset + above.length);
|
|
87
|
-
const textNode = {
|
|
88
|
-
...node,
|
|
89
|
-
uuid: uuid(),
|
|
90
|
-
type: 'text',
|
|
91
|
-
raw,
|
|
92
|
-
startOffset,
|
|
93
|
-
endOffset,
|
|
94
|
-
startLine,
|
|
95
|
-
endLine,
|
|
96
|
-
startCol,
|
|
97
|
-
endCol,
|
|
98
|
-
};
|
|
99
|
-
if (node.prevNode?.nextNode) {
|
|
100
|
-
node.prevNode.nextNode = textNode;
|
|
101
|
-
}
|
|
102
|
-
if (node.nextNode?.prevNode) {
|
|
103
|
-
node.nextNode.prevNode = textNode;
|
|
104
|
-
}
|
|
105
|
-
insertList.push(textNode);
|
|
106
|
-
}
|
|
107
|
-
if (body) {
|
|
108
|
-
const offset = node.startOffset + pointer + above.length;
|
|
109
|
-
const { raw, startOffset, endOffset, startLine, endLine, startCol, endCol } = sliceFragment(source, offset, offset + body.length);
|
|
110
|
-
const bodyNode = {
|
|
111
|
-
uuid: uuid(),
|
|
112
|
-
type: 'psblock',
|
|
113
|
-
nodeName: `#ps:${tag.type}`,
|
|
114
|
-
raw,
|
|
115
|
-
parentNode: node.parentNode,
|
|
116
|
-
prevNode: null,
|
|
117
|
-
nextNode: null,
|
|
118
|
-
isFragment: node.isFragment,
|
|
119
|
-
isGhost: false,
|
|
120
|
-
startOffset,
|
|
121
|
-
endOffset,
|
|
122
|
-
startLine,
|
|
123
|
-
endLine,
|
|
124
|
-
startCol,
|
|
125
|
-
endCol,
|
|
126
|
-
};
|
|
127
|
-
if (node.prevNode?.nextNode) {
|
|
128
|
-
node.prevNode.nextNode = bodyNode;
|
|
129
|
-
}
|
|
130
|
-
if (node.nextNode?.prevNode) {
|
|
131
|
-
node.nextNode.prevNode = bodyNode;
|
|
132
|
-
}
|
|
133
|
-
insertList.push(bodyNode);
|
|
134
|
-
}
|
|
135
|
-
text = below;
|
|
136
|
-
pointer = start + body.length;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (text) {
|
|
140
|
-
const offset = node.endOffset - text.length;
|
|
141
|
-
const { raw, startOffset, endOffset, startLine, endLine, startCol, endCol } = sliceFragment(source, offset, offset + text.length);
|
|
142
|
-
const textNode = {
|
|
143
|
-
...node,
|
|
144
|
-
uuid: uuid(),
|
|
145
|
-
type: 'text',
|
|
146
|
-
raw,
|
|
147
|
-
startOffset,
|
|
148
|
-
endOffset,
|
|
149
|
-
startLine,
|
|
150
|
-
endLine,
|
|
151
|
-
startCol,
|
|
152
|
-
endCol,
|
|
153
|
-
};
|
|
154
|
-
insertList.push(textNode);
|
|
155
|
-
}
|
|
156
|
-
siblingsCorrection(insertList);
|
|
157
|
-
if (parentNode) {
|
|
158
|
-
parentNode.childNodes = insertList;
|
|
159
|
-
}
|
|
160
|
-
nodeList.splice(index, 1, ...insertList);
|
|
61
|
+
for (const tag of stack) {
|
|
62
|
+
const node = nodeList.find(node => node.startOffset === tag.index);
|
|
63
|
+
if (!node) {
|
|
64
|
+
continue;
|
|
161
65
|
}
|
|
66
|
+
const psNode = {
|
|
67
|
+
uuid: uuid(),
|
|
68
|
+
type: 'psblock',
|
|
69
|
+
nodeName: `#ps:${tag.type}`,
|
|
70
|
+
raw: `${tag.startTag}${tag.taggedCode}${tag.endTag ?? ''}`,
|
|
71
|
+
parentNode: node.parentNode,
|
|
72
|
+
prevNode: null,
|
|
73
|
+
nextNode: null,
|
|
74
|
+
isFragment: node.isFragment,
|
|
75
|
+
isGhost: false,
|
|
76
|
+
startOffset: node.startOffset,
|
|
77
|
+
endOffset: node.endOffset,
|
|
78
|
+
startLine: node.startLine,
|
|
79
|
+
endLine: node.endLine,
|
|
80
|
+
startCol: node.startCol,
|
|
81
|
+
endCol: node.endCol,
|
|
82
|
+
};
|
|
83
|
+
if (node.prevNode?.nextNode) {
|
|
84
|
+
node.prevNode.nextNode = psNode;
|
|
85
|
+
}
|
|
86
|
+
if (node.nextNode?.prevNode) {
|
|
87
|
+
node.nextNode.prevNode = psNode;
|
|
88
|
+
}
|
|
89
|
+
if (node.parentNode?.childNodes) {
|
|
90
|
+
const index = node.parentNode.childNodes.indexOf(node);
|
|
91
|
+
node.parentNode.childNodes.splice(index, 1, psNode);
|
|
92
|
+
}
|
|
93
|
+
const index = nodeList.indexOf(node);
|
|
94
|
+
nodeList.splice(index, 1, psNode);
|
|
95
|
+
tag.resolved = true;
|
|
96
|
+
}
|
|
97
|
+
for (const node of nodeList) {
|
|
162
98
|
if (node.type === 'starttag') {
|
|
163
99
|
for (const attr of node.attributes) {
|
|
164
100
|
if (attr.type === 'ps-attr' || attr.value.raw === '' || !hasIgnoreBlock(attr.value.raw, maskChar)) {
|
|
@@ -173,8 +109,35 @@ nodeList, ignoreBlock) {
|
|
|
173
109
|
const below = attr.value.raw.slice(offset + length);
|
|
174
110
|
attr.value.raw = above + raw + below;
|
|
175
111
|
attr.isDynamicValue = true;
|
|
112
|
+
tag.resolved = true;
|
|
176
113
|
}
|
|
114
|
+
attr.raw =
|
|
115
|
+
attr.spacesBeforeName.raw +
|
|
116
|
+
attr.name.raw +
|
|
117
|
+
attr.spacesBeforeEqual.raw +
|
|
118
|
+
attr.equal.raw +
|
|
119
|
+
attr.spacesAfterEqual.raw +
|
|
120
|
+
attr.startQuote.raw +
|
|
121
|
+
attr.value.raw +
|
|
122
|
+
attr.endQuote.raw;
|
|
177
123
|
}
|
|
124
|
+
// Update node raw
|
|
125
|
+
const length = attr.raw.length;
|
|
126
|
+
const offset = attr.startOffset - node.startOffset - attr.spacesBeforeName.raw.length;
|
|
127
|
+
const above = node.raw.slice(0, offset);
|
|
128
|
+
const below = node.raw.slice(offset + length);
|
|
129
|
+
node.raw = above + attr.raw + below;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (throwErrorWhenTagHasUnresolved) {
|
|
134
|
+
for (const tag of stack) {
|
|
135
|
+
if (!tag.resolved) {
|
|
136
|
+
throw new ParserError('Parsing failed. Unsupported syntax detected', {
|
|
137
|
+
line: getLine(source, tag.index),
|
|
138
|
+
col: getCol(source, tag.index),
|
|
139
|
+
raw: tag.startTag + tag.taggedCode + (tag.endTag ?? ''),
|
|
140
|
+
});
|
|
178
141
|
}
|
|
179
142
|
}
|
|
180
143
|
}
|
|
@@ -197,18 +160,6 @@ function removeGlobalOption(reg) {
|
|
|
197
160
|
}
|
|
198
161
|
return new RegExp(reg.source, reg.ignoreCase ? 'i' : '');
|
|
199
162
|
}
|
|
200
|
-
function prepend(reg, str) {
|
|
201
|
-
if (typeof reg === 'string') {
|
|
202
|
-
return new RegExp(str + escapeRegExpForStr(reg));
|
|
203
|
-
}
|
|
204
|
-
return new RegExp(str + reg.source, reg.ignoreCase ? 'i' : '');
|
|
205
|
-
}
|
|
206
|
-
function append(reg, str) {
|
|
207
|
-
if (typeof reg === 'string') {
|
|
208
|
-
return new RegExp(escapeRegExpForStr(reg) + str);
|
|
209
|
-
}
|
|
210
|
-
return new RegExp(reg.source + str, reg.ignoreCase ? 'i' : '');
|
|
211
|
-
}
|
|
212
163
|
function hasIgnoreBlock(textContent, maskChar) {
|
|
213
164
|
return textContent.includes(maskChar);
|
|
214
165
|
}
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/parser-utils",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.8",
|
|
4
4
|
"description": "Utility module for markuplint parser plugin",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"clean": "tsc --build --clean"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@markuplint/ml-ast": "4.0.0-alpha.
|
|
28
|
-
"@markuplint/types": "4.0.0-alpha.
|
|
27
|
+
"@markuplint/ml-ast": "4.0.0-alpha.8",
|
|
28
|
+
"@markuplint/types": "4.0.0-alpha.8",
|
|
29
29
|
"@types/uuid": "^9.0.7",
|
|
30
30
|
"espree": "^9.6.1",
|
|
31
|
-
"type-fest": "^4.
|
|
31
|
+
"type-fest": "^4.9.0",
|
|
32
32
|
"uuid": "^9.0.1"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "5bcd25f13ff804af0d09aaabd87e495af668e6a8"
|
|
35
35
|
}
|