@markuplint/parser-utils 3.0.0-alpha.6 → 3.0.0-dev.176
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/README.md +8 -3
- package/lib/const.d.ts +3 -0
- package/lib/const.js +5 -1
- package/lib/create-token.js +2 -2
- package/lib/debugger.js +8 -3
- package/lib/detect-element-type.js +3 -3
- package/lib/flatten-nodes.d.ts +2 -0
- package/lib/flatten-nodes.js +251 -0
- package/lib/get-location.js +2 -1
- package/lib/get-space-before.d.ts +1 -0
- package/lib/get-space-before.js +13 -0
- package/lib/idl-attributes.js +25 -5
- package/lib/ignore-block.d.ts +1 -1
- package/lib/ignore-block.js +21 -6
- package/lib/index.d.ts +10 -4
- package/lib/index.js +10 -4
- package/lib/parse-attr.d.ts +27 -0
- package/lib/parse-attr.js +150 -0
- package/lib/parser-error.d.ts +4 -4
- package/lib/remove-deprecated-node.d.ts +7 -0
- package/lib/remove-deprecated-node.js +43 -0
- package/lib/siblings-correction.js +9 -3
- package/lib/tag-splitter.d.ts +7 -0
- package/lib/tag-splitter.js +92 -0
- package/lib/types.d.ts +12 -12
- package/lib/walker.d.ts +1 -1
- package/lib/walker.js +4 -2
- package/package.json +14 -9
- package/test/create-token.spec.js +17 -0
- package/test/flatten-nodes.spec.js +31 -0
- package/test/get-location.spec.js +38 -0
- package/test/ignore-block.spec.js +274 -0
- package/test/ignore-front-matter.spec.js +20 -0
- package/test/parse-attr.spec.js +68 -0
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tokenize = exports.parseAttr = exports.defaultValueDelimiters = void 0;
|
|
4
|
+
const create_token_1 = require("./create-token");
|
|
5
|
+
exports.defaultValueDelimiters = [
|
|
6
|
+
{
|
|
7
|
+
start: "'",
|
|
8
|
+
end: "'",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
start: '"',
|
|
12
|
+
end: '"',
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
const defaultEqual = '=';
|
|
16
|
+
const spaceRegex = /^\s$/;
|
|
17
|
+
function parseAttr(raw, offset, html, options) {
|
|
18
|
+
const tokens = tokenize(raw, options);
|
|
19
|
+
tokens.beforeName;
|
|
20
|
+
const attrToken = (0, create_token_1.createTokenFromRawCode)(raw, offset, html);
|
|
21
|
+
const spacesBeforeName = (0, create_token_1.tokenizer)(tokens.beforeName, attrToken.startLine, attrToken.startCol, attrToken.startOffset);
|
|
22
|
+
const name = (0, create_token_1.tokenizer)(tokens.name, spacesBeforeName.endLine, spacesBeforeName.endCol, spacesBeforeName.endOffset);
|
|
23
|
+
const spacesBeforeEqual = (0, create_token_1.tokenizer)(tokens.afterName, name.endLine, name.endCol, name.endOffset);
|
|
24
|
+
const equal = (0, create_token_1.tokenizer)(tokens.equal, spacesBeforeEqual.endLine, spacesBeforeEqual.endCol, spacesBeforeEqual.endOffset);
|
|
25
|
+
const spacesAfterEqual = (0, create_token_1.tokenizer)(tokens.beforeValue, equal.endLine, equal.endCol, equal.endOffset);
|
|
26
|
+
const startQuote = (0, create_token_1.tokenizer)(tokens.startQuote, spacesAfterEqual.endLine, spacesAfterEqual.endCol, spacesAfterEqual.endOffset);
|
|
27
|
+
const value = (0, create_token_1.tokenizer)(tokens.value, startQuote.endLine, startQuote.endCol, startQuote.endOffset);
|
|
28
|
+
const endQuote = (0, create_token_1.tokenizer)(tokens.endQuote, value.endLine, value.endCol, value.endOffset);
|
|
29
|
+
const attr = {
|
|
30
|
+
type: 'html-attr',
|
|
31
|
+
uuid: (0, create_token_1.uuid)(),
|
|
32
|
+
raw: attrToken.raw,
|
|
33
|
+
startOffset: attrToken.startOffset,
|
|
34
|
+
endOffset: attrToken.endOffset,
|
|
35
|
+
startLine: attrToken.startLine,
|
|
36
|
+
endLine: attrToken.endLine,
|
|
37
|
+
startCol: attrToken.startCol,
|
|
38
|
+
endCol: attrToken.endCol,
|
|
39
|
+
spacesBeforeName,
|
|
40
|
+
name,
|
|
41
|
+
spacesBeforeEqual,
|
|
42
|
+
equal,
|
|
43
|
+
spacesAfterEqual,
|
|
44
|
+
startQuote,
|
|
45
|
+
value,
|
|
46
|
+
endQuote,
|
|
47
|
+
isDuplicatable: false,
|
|
48
|
+
nodeName: name.raw,
|
|
49
|
+
parentNode: null,
|
|
50
|
+
nextNode: null,
|
|
51
|
+
prevNode: null,
|
|
52
|
+
isFragment: false,
|
|
53
|
+
isGhost: false,
|
|
54
|
+
};
|
|
55
|
+
return attr;
|
|
56
|
+
}
|
|
57
|
+
exports.parseAttr = parseAttr;
|
|
58
|
+
function tokenize(raw, options) {
|
|
59
|
+
var _a, _b, _c;
|
|
60
|
+
const valueDelimiters = (_a = options === null || options === void 0 ? void 0 : options.valueDelimiters) !== null && _a !== void 0 ? _a : exports.defaultValueDelimiters;
|
|
61
|
+
const equalDelimiter = (_b = options === null || options === void 0 ? void 0 : options.equal) !== null && _b !== void 0 ? _b : defaultEqual;
|
|
62
|
+
let state = 'b-name';
|
|
63
|
+
const charactors = raw.split('');
|
|
64
|
+
let beforeName = '';
|
|
65
|
+
let name = '';
|
|
66
|
+
let afterName = '';
|
|
67
|
+
let equal = '';
|
|
68
|
+
let valueDelimiter = null;
|
|
69
|
+
let beforeValue = '';
|
|
70
|
+
let startQuote = '';
|
|
71
|
+
let value = '';
|
|
72
|
+
let endQuote = '';
|
|
73
|
+
let afterAttr = '';
|
|
74
|
+
while (charactors.length > 0) {
|
|
75
|
+
const charactor = charactors.shift();
|
|
76
|
+
if (state === 'b-name') {
|
|
77
|
+
if (spaceRegex.test(charactor)) {
|
|
78
|
+
beforeName += charactor;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
name += charactor;
|
|
82
|
+
state = 'name';
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (state === 'name') {
|
|
86
|
+
if (equalDelimiter === charactor) {
|
|
87
|
+
equal = equalDelimiter;
|
|
88
|
+
state = 'value-start';
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (spaceRegex.test(charactor)) {
|
|
92
|
+
afterName += charactor;
|
|
93
|
+
state = 'a-name';
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
name += charactor;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (state === 'a-name') {
|
|
100
|
+
if (equalDelimiter === charactor) {
|
|
101
|
+
equal = equalDelimiter;
|
|
102
|
+
state = 'value-start';
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (spaceRegex.test(charactor)) {
|
|
106
|
+
afterName += charactor;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (state === 'value-start') {
|
|
112
|
+
if (spaceRegex.test(charactor)) {
|
|
113
|
+
beforeValue += charactor;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
valueDelimiter = (_c = valueDelimiters.find(d => d.start === charactor)) !== null && _c !== void 0 ? _c : null;
|
|
117
|
+
if (valueDelimiter) {
|
|
118
|
+
startQuote += valueDelimiter.start;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
value += beforeValue + charactor;
|
|
122
|
+
beforeValue = '';
|
|
123
|
+
}
|
|
124
|
+
state = 'value';
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (state !== 'value') {
|
|
128
|
+
throw new Error('ParseError: unknown parse state in the attribute');
|
|
129
|
+
}
|
|
130
|
+
value += charactor;
|
|
131
|
+
}
|
|
132
|
+
if (valueDelimiter) {
|
|
133
|
+
const endQuoteIndex = value.lastIndexOf(valueDelimiter.end);
|
|
134
|
+
endQuote = value.slice(endQuoteIndex, endQuoteIndex + 1);
|
|
135
|
+
afterAttr = value.slice(endQuoteIndex + 1);
|
|
136
|
+
value = value.slice(0, endQuoteIndex);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
beforeName,
|
|
140
|
+
name,
|
|
141
|
+
afterName,
|
|
142
|
+
equal,
|
|
143
|
+
beforeValue,
|
|
144
|
+
startQuote,
|
|
145
|
+
value,
|
|
146
|
+
endQuote,
|
|
147
|
+
afterAttr,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
exports.tokenize = tokenize;
|
package/lib/parser-error.d.ts
CHANGED
|
@@ -12,10 +12,10 @@ export declare class ParserError extends Error {
|
|
|
12
12
|
raw,
|
|
13
13
|
nodeName,
|
|
14
14
|
}: {
|
|
15
|
-
line?: number;
|
|
16
|
-
col?: number;
|
|
17
|
-
raw?: string;
|
|
18
|
-
nodeName?: string | null;
|
|
15
|
+
readonly line?: number;
|
|
16
|
+
readonly col?: number;
|
|
17
|
+
readonly raw?: string;
|
|
18
|
+
readonly nodeName?: string | null;
|
|
19
19
|
},
|
|
20
20
|
);
|
|
21
21
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeDeprecatedNode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @disruptive
|
|
7
|
+
* @param nodeOrders [Disruptive change]
|
|
8
|
+
*/
|
|
9
|
+
function removeDeprecatedNode(
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
11
|
+
nodeOrders) {
|
|
12
|
+
/**
|
|
13
|
+
* sorting
|
|
14
|
+
*/
|
|
15
|
+
nodeOrders.sort((a, b) => {
|
|
16
|
+
if (a.isGhost || b.isGhost) {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
return a.startOffset - b.startOffset;
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* remove duplicated node
|
|
23
|
+
*/
|
|
24
|
+
const stack = {};
|
|
25
|
+
const removeIndexes = [];
|
|
26
|
+
nodeOrders.forEach((node, i) => {
|
|
27
|
+
if (node.isGhost) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const id = `${node.startLine}:${node.startCol}:${node.endLine}:${node.endCol}`;
|
|
31
|
+
if (stack[id] != null) {
|
|
32
|
+
removeIndexes.push(i);
|
|
33
|
+
}
|
|
34
|
+
stack[id] = i;
|
|
35
|
+
});
|
|
36
|
+
let r = nodeOrders.length;
|
|
37
|
+
while (r-- > 0) {
|
|
38
|
+
if (removeIndexes.includes(r)) {
|
|
39
|
+
nodeOrders.splice(r, 1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.removeDeprecatedNode = removeDeprecatedNode;
|
|
@@ -8,11 +8,17 @@ exports.siblingsCorrection = void 0;
|
|
|
8
8
|
* @affects nodeList[].prevNode
|
|
9
9
|
* @affects nodeList[].nextNode
|
|
10
10
|
*/
|
|
11
|
-
function siblingsCorrection(
|
|
11
|
+
function siblingsCorrection(
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
13
|
+
nodeList) {
|
|
14
|
+
var _a, _b;
|
|
12
15
|
for (let i = 0; i < nodeList.length; i++) {
|
|
13
|
-
const prevNode = nodeList[i - 1]
|
|
16
|
+
const prevNode = (_a = nodeList[i - 1]) !== null && _a !== void 0 ? _a : null;
|
|
14
17
|
const node = nodeList[i];
|
|
15
|
-
|
|
18
|
+
if (!node) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const nextNode = (_b = nodeList[i + 1]) !== null && _b !== void 0 ? _b : null;
|
|
16
22
|
node.prevNode = prevNode;
|
|
17
23
|
node.nextNode = nextNode;
|
|
18
24
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const const_1 = require("./const");
|
|
4
|
+
const parser_utils_1 = require("@markuplint/parser-utils");
|
|
5
|
+
function tagSplitter(raw, line, col) {
|
|
6
|
+
return withLocation(tagSplitterAsString(raw), line, col);
|
|
7
|
+
}
|
|
8
|
+
exports.default = tagSplitter;
|
|
9
|
+
function tagSplitterAsString(raw) {
|
|
10
|
+
const tagMatches = raw.match(const_1.reSplitterTag);
|
|
11
|
+
if (!tagMatches) {
|
|
12
|
+
return [raw];
|
|
13
|
+
}
|
|
14
|
+
const tokens = Array.from(tagMatches);
|
|
15
|
+
tokens.unshift(); // remove all match
|
|
16
|
+
const nodes = [];
|
|
17
|
+
let rest = raw;
|
|
18
|
+
for (const token of tokens) {
|
|
19
|
+
const index = rest.indexOf(token);
|
|
20
|
+
let length = token.length;
|
|
21
|
+
if (index > 0) {
|
|
22
|
+
const text = rest.slice(0, index);
|
|
23
|
+
nodes.push(text);
|
|
24
|
+
length += text.length;
|
|
25
|
+
}
|
|
26
|
+
nodes.push(token);
|
|
27
|
+
rest = rest.slice(length);
|
|
28
|
+
}
|
|
29
|
+
if (rest) {
|
|
30
|
+
nodes.push(rest);
|
|
31
|
+
}
|
|
32
|
+
return nodes;
|
|
33
|
+
}
|
|
34
|
+
function withLocation(nodes, line, col) {
|
|
35
|
+
const result = [];
|
|
36
|
+
for (const node of nodes) {
|
|
37
|
+
if (node[0] !== '<') {
|
|
38
|
+
result.push({
|
|
39
|
+
type: 'text',
|
|
40
|
+
raw: node,
|
|
41
|
+
line,
|
|
42
|
+
col,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const label = node.slice(1).slice(0, -1);
|
|
47
|
+
if (const_1.reTagName.test(label)) {
|
|
48
|
+
result.push({
|
|
49
|
+
type: 'starttag',
|
|
50
|
+
raw: node,
|
|
51
|
+
line,
|
|
52
|
+
col,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else if (label[0] === '/') {
|
|
56
|
+
result.push({
|
|
57
|
+
type: 'endtag',
|
|
58
|
+
raw: node,
|
|
59
|
+
line,
|
|
60
|
+
col,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else if (label[0] === '!') {
|
|
64
|
+
result.push({
|
|
65
|
+
type: 'comment',
|
|
66
|
+
raw: node,
|
|
67
|
+
line,
|
|
68
|
+
col,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else if (label[0] === '?') {
|
|
72
|
+
result.push({
|
|
73
|
+
type: 'boguscomment',
|
|
74
|
+
raw: node,
|
|
75
|
+
line,
|
|
76
|
+
col,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
result.push({
|
|
81
|
+
type: 'text',
|
|
82
|
+
raw: node,
|
|
83
|
+
line,
|
|
84
|
+
col,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
line = (0, parser_utils_1.getEndLine)(node, line);
|
|
89
|
+
col = (0, parser_utils_1.getEndCol)(node, col);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export type Code = {
|
|
2
|
-
type: string;
|
|
3
|
-
index: number;
|
|
4
|
-
startTag: string;
|
|
5
|
-
taggedCode: string;
|
|
6
|
-
endTag: string | null;
|
|
2
|
+
readonly type: string;
|
|
3
|
+
readonly index: number;
|
|
4
|
+
readonly startTag: string;
|
|
5
|
+
readonly taggedCode: string;
|
|
6
|
+
readonly endTag: string | null;
|
|
7
7
|
};
|
|
8
8
|
export type IgnoreTag = {
|
|
9
|
-
type: string;
|
|
10
|
-
start: RegExp
|
|
11
|
-
end: RegExp
|
|
9
|
+
readonly type: string;
|
|
10
|
+
readonly start: Readonly<RegExp>;
|
|
11
|
+
readonly end: Readonly<RegExp>;
|
|
12
12
|
};
|
|
13
13
|
export type IgnoreBlock = {
|
|
14
|
-
source: string;
|
|
15
|
-
replaced: string;
|
|
16
|
-
stack: Code[];
|
|
17
|
-
maskChar: string;
|
|
14
|
+
readonly source: string;
|
|
15
|
+
readonly replaced: string;
|
|
16
|
+
readonly stack: readonly Code[];
|
|
17
|
+
readonly maskChar: string;
|
|
18
18
|
};
|
package/lib/walker.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { MLASTNode, Walker } from '@markuplint/ml-ast';
|
|
2
|
-
export declare function walk(nodeList: MLASTNode[], walker: Walker, depth?: number): void;
|
|
2
|
+
export declare function walk(nodeList: readonly MLASTNode[], walker: Walker, depth?: number): void;
|
package/lib/walker.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.walk = void 0;
|
|
4
|
-
function walk(
|
|
4
|
+
function walk(
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
6
|
+
nodeList, walker, depth = 0) {
|
|
5
7
|
for (const node of nodeList) {
|
|
6
8
|
walker(node, depth);
|
|
7
9
|
if ('childNodes' in node) {
|
|
8
10
|
if (node.type === 'endtag') {
|
|
9
11
|
continue;
|
|
10
12
|
}
|
|
11
|
-
if (node.childNodes && node.childNodes.length) {
|
|
13
|
+
if (node.childNodes && node.childNodes.length > 0) {
|
|
12
14
|
walk(node.childNodes, walker, depth + 1);
|
|
13
15
|
}
|
|
14
16
|
if ('pearNode' in node && node.pearNode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/parser-utils",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-dev.176+f6ad62e9",
|
|
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>",
|
|
@@ -11,18 +11,23 @@
|
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
|
+
"typedoc": {
|
|
15
|
+
"entryPoint": "./src/index.ts"
|
|
16
|
+
},
|
|
14
17
|
"scripts": {
|
|
15
18
|
"build": "tsc",
|
|
16
19
|
"clean": "tsc --build --clean"
|
|
17
20
|
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/uuid": "^8.3.4"
|
|
20
|
-
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@markuplint/ml-ast": "3.0.0-
|
|
23
|
-
"@markuplint/types": "3.0.0-
|
|
24
|
-
"
|
|
25
|
-
"
|
|
22
|
+
"@markuplint/ml-ast": "3.0.0-dev.176+f6ad62e9",
|
|
23
|
+
"@markuplint/types": "3.0.0-dev.176+f6ad62e9",
|
|
24
|
+
"@types/uuid": "^9.0.0",
|
|
25
|
+
"tslib": "^2.4.1",
|
|
26
|
+
"type-fest": "^3.8.0",
|
|
27
|
+
"uuid": "^9.0.0"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@markuplint/ml-core": "3.x"
|
|
26
31
|
},
|
|
27
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "f6ad62e992e1569be4067f1e90d2d6017a658f57"
|
|
28
33
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { tokenizer } = require('../lib/create-token');
|
|
2
|
+
|
|
3
|
+
describe('tokenizer', () => {
|
|
4
|
+
it('empty', () => {
|
|
5
|
+
expect(tokenizer('', 1, 1, 0)).toEqual(
|
|
6
|
+
expect.objectContaining({
|
|
7
|
+
raw: '',
|
|
8
|
+
startLine: 1,
|
|
9
|
+
startCol: 1,
|
|
10
|
+
startOffset: 0,
|
|
11
|
+
endLine: 1,
|
|
12
|
+
endCol: 1,
|
|
13
|
+
endOffset: 0,
|
|
14
|
+
}),
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { isDocumentFragment, createTree } = require('@markuplint/html-parser');
|
|
2
|
+
|
|
3
|
+
const { flattenNodes } = require('../lib/flatten-nodes');
|
|
4
|
+
|
|
5
|
+
function toTree(rawCode) {
|
|
6
|
+
const isFragment = isDocumentFragment(rawCode);
|
|
7
|
+
return createTree(rawCode, isFragment, 0, 0, 0);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('flattenNodes', () => {
|
|
11
|
+
it('a node', () => {
|
|
12
|
+
const raw = '<div></div>';
|
|
13
|
+
const tree = toTree(raw);
|
|
14
|
+
const list = flattenNodes(tree, raw);
|
|
15
|
+
expect(list.length).toStrictEqual(2);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('one depth', () => {
|
|
19
|
+
const raw = '<div><span></span></div>';
|
|
20
|
+
const tree = toTree(raw);
|
|
21
|
+
const list = flattenNodes(tree, raw);
|
|
22
|
+
expect(list.length).toStrictEqual(4);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('two depth', () => {
|
|
26
|
+
const raw = '<div><span><span></span></span></div>';
|
|
27
|
+
const tree = toTree(raw);
|
|
28
|
+
const list = flattenNodes(tree, raw);
|
|
29
|
+
expect(list.length).toStrictEqual(6);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { getEndCol, getEndLine } = require('../lib/get-location');
|
|
2
|
+
|
|
3
|
+
describe('getEndLine', () => {
|
|
4
|
+
it('empty', () => {
|
|
5
|
+
expect(getEndLine('', 1)).toBe(1);
|
|
6
|
+
expect(getEndLine('', 3)).toBe(3);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('basic', () => {
|
|
10
|
+
expect(getEndLine('\n\n', 2)).toBe(4);
|
|
11
|
+
expect(getEndLine('\n\n', 4)).toBe(6);
|
|
12
|
+
expect(getEndLine('\n\n \n \n foo', 1)).toBe(5);
|
|
13
|
+
expect(getEndLine('\n\n \n \n foo', 6)).toBe(10);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('getEndCol', () => {
|
|
18
|
+
it('empty', () => {
|
|
19
|
+
expect(getEndCol('', 1)).toBe(1);
|
|
20
|
+
expect(getEndCol('', 3)).toBe(3);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('basic', () => {
|
|
24
|
+
expect(getEndCol(' ', 2)).toBe(4);
|
|
25
|
+
expect(getEndCol(' ', 4)).toBe(6);
|
|
26
|
+
expect(getEndCol('foo bar', 1)).toBe(8);
|
|
27
|
+
expect(getEndCol('foo bar', 6)).toBe(13);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('with line break', () => {
|
|
31
|
+
expect(getEndCol('foo bar\n', 4)).toBe(1);
|
|
32
|
+
expect(getEndCol('foo bar\n', 4)).toBe(1);
|
|
33
|
+
expect(getEndCol('foo bar\n ', 4)).toBe(3);
|
|
34
|
+
expect(getEndCol('foo bar\n ', 4)).toBe(3);
|
|
35
|
+
expect(getEndCol('foo bar\nfoo bar', 1)).toBe(8);
|
|
36
|
+
expect(getEndCol('foo bar\nfoo bar', 6)).toBe(8);
|
|
37
|
+
});
|
|
38
|
+
});
|