@markuplint/svelte-parser 3.12.0 → 4.0.0-alpha.10
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/README.md +12 -0
- package/lib/index.d.ts +1 -2
- package/lib/index.js +1 -6
- package/lib/parser.d.ts +54 -0
- package/lib/parser.js +267 -0
- package/lib/svelte-parser/index.d.ts +1 -1
- package/lib/svelte-parser/index.js +4 -8
- package/lib/sveltekit-parser.d.ts +6 -0
- package/lib/sveltekit-parser.js +15 -0
- package/package.json +15 -8
- package/lib/attr.d.ts +0 -10
- package/lib/attr.js +0 -66
- package/lib/directive-tokenizer.d.ts +0 -8
- package/lib/directive-tokenizer.js +0 -105
- package/lib/nodeize.d.ts +0 -9
- package/lib/nodeize.js +0 -293
- package/lib/parse-ctrl-block.d.ts +0 -13
- package/lib/parse-ctrl-block.js +0 -175
- package/lib/parse.d.ts +0 -2
- package/lib/parse.js +0 -52
- package/lib/traverse.d.ts +0 -8
- package/lib/traverse.js +0 -42
- package/test/index.spec.js +0 -556
- package/test/parse-ctrl-block.spec.js +0 -267
- package/test/svelte-parser/index.spec.js +0 -141
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -23,3 +23,15 @@ Add `parser` option to your [configuration](https://markuplint.dev/configuration
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
|
+
|
|
27
|
+
### Use with [SvelteKit](https://kit.svelte.dev/)
|
|
28
|
+
|
|
29
|
+
```diff
|
|
30
|
+
{
|
|
31
|
+
"parser": {
|
|
32
|
+
-- ".svelte$": "@markuplint/svelte-parser"
|
|
33
|
+
++ ".svelte$": "@markuplint/svelte-parser",
|
|
34
|
+
++ ".html$": "@markuplint/svelte-parser/kit"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export declare const endTag = 'xml';
|
|
1
|
+
export { parser } from './parser.js';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.endTag = exports.parse = void 0;
|
|
4
|
-
var parse_1 = require("./parse");
|
|
5
|
-
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return parse_1.parse; } });
|
|
6
|
-
exports.endTag = 'xml';
|
|
1
|
+
export { parser } from './parser.js';
|
package/lib/parser.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/// <reference types="svelte" />
|
|
2
|
+
import type { SvelteNode } from './svelte-parser/index.js';
|
|
3
|
+
import type { MLASTParentNode, MLASTPreprocessorSpecificBlock } from '@markuplint/ml-ast';
|
|
4
|
+
import type { ChildToken, ParseOptions, Token } from '@markuplint/parser-utils';
|
|
5
|
+
import { ParserError, Parser } from '@markuplint/parser-utils';
|
|
6
|
+
declare class SvelteParser extends Parser<SvelteNode> {
|
|
7
|
+
readonly specificBindDirective: ReadonlySet<string>;
|
|
8
|
+
constructor();
|
|
9
|
+
tokenize(): {
|
|
10
|
+
ast: import("svelte/types/compiler/interfaces").TemplateNode[];
|
|
11
|
+
isFragment: boolean;
|
|
12
|
+
};
|
|
13
|
+
parse(raw: string, options?: ParseOptions): import("@markuplint/ml-ast").MLASTDocument;
|
|
14
|
+
parseError(error: any): ParserError;
|
|
15
|
+
nodeize(originNode: SvelteNode, parentNode: MLASTParentNode | null, depth: number): readonly import("@markuplint/ml-ast").MLASTNodeTreeItem[];
|
|
16
|
+
visitPsBlock(token: ChildToken & {
|
|
17
|
+
readonly nodeName: string;
|
|
18
|
+
}, childNodes?: readonly SvelteNode[]): readonly [MLASTPreprocessorSpecificBlock];
|
|
19
|
+
visitChildren(children: readonly SvelteNode[], parentNode: MLASTParentNode | null): never[];
|
|
20
|
+
visitAttr(token: Token): (import("@markuplint/ml-ast").MLASTSpreadAttr & {
|
|
21
|
+
__rightText?: string | undefined;
|
|
22
|
+
}) | {
|
|
23
|
+
isDynamicValue: true | undefined;
|
|
24
|
+
isDirective: true | undefined;
|
|
25
|
+
isDuplicatable: boolean;
|
|
26
|
+
potentialName: string | undefined;
|
|
27
|
+
type: "attr";
|
|
28
|
+
nodeName: string;
|
|
29
|
+
spacesBeforeName: import("@markuplint/ml-ast").MLASTToken;
|
|
30
|
+
name: import("@markuplint/ml-ast").MLASTToken;
|
|
31
|
+
spacesBeforeEqual: import("@markuplint/ml-ast").MLASTToken;
|
|
32
|
+
equal: import("@markuplint/ml-ast").MLASTToken;
|
|
33
|
+
spacesAfterEqual: import("@markuplint/ml-ast").MLASTToken;
|
|
34
|
+
startQuote: import("@markuplint/ml-ast").MLASTToken;
|
|
35
|
+
value: import("@markuplint/ml-ast").MLASTToken;
|
|
36
|
+
endQuote: import("@markuplint/ml-ast").MLASTToken;
|
|
37
|
+
potentialValue?: string | undefined;
|
|
38
|
+
valueType?: "string" | "number" | "boolean" | "code" | undefined;
|
|
39
|
+
candidate?: string | undefined;
|
|
40
|
+
uuid: string;
|
|
41
|
+
raw: string;
|
|
42
|
+
startOffset: number;
|
|
43
|
+
endOffset: number;
|
|
44
|
+
startLine: number;
|
|
45
|
+
endLine: number;
|
|
46
|
+
startCol: number;
|
|
47
|
+
endCol: number;
|
|
48
|
+
__rightText?: string | undefined;
|
|
49
|
+
};
|
|
50
|
+
detectElementType(nodeName: string): import("@markuplint/ml-ast").ElementType;
|
|
51
|
+
visitExpression(token: ChildToken, originBlockNode: SvelteNode): MLASTPreprocessorSpecificBlock[];
|
|
52
|
+
}
|
|
53
|
+
export declare const parser: SvelteParser;
|
|
54
|
+
export {};
|
package/lib/parser.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { getNamespace } from '@markuplint/html-parser';
|
|
2
|
+
import { ParserError, Parser, AttrState } from '@markuplint/parser-utils';
|
|
3
|
+
import { svelteParse } from './svelte-parser/index.js';
|
|
4
|
+
class SvelteParser extends Parser {
|
|
5
|
+
constructor() {
|
|
6
|
+
super({
|
|
7
|
+
endTagType: 'xml',
|
|
8
|
+
ignoreTags: [
|
|
9
|
+
{
|
|
10
|
+
type: 'Script',
|
|
11
|
+
start: '<script',
|
|
12
|
+
end: '</script>',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: 'Style',
|
|
16
|
+
start: '<style',
|
|
17
|
+
end: '</style>',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
maskChar: '-',
|
|
21
|
+
});
|
|
22
|
+
this.specificBindDirective = new Set(['group', 'this']);
|
|
23
|
+
}
|
|
24
|
+
tokenize() {
|
|
25
|
+
return {
|
|
26
|
+
ast: svelteParse(this.rawCode),
|
|
27
|
+
isFragment: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
parse(raw, options) {
|
|
31
|
+
return super.parse(raw, {
|
|
32
|
+
...options,
|
|
33
|
+
ignoreFrontMatter: false,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
parseError(error) {
|
|
37
|
+
if (error instanceof Error && 'start' in error && 'end' in error && 'frame' in error) {
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
const token = this.sliceFragment(error.start.character, error.end.character);
|
|
40
|
+
throw new ParserError(error.message + '\n' + error.frame, token);
|
|
41
|
+
}
|
|
42
|
+
return super.parseError(error);
|
|
43
|
+
}
|
|
44
|
+
nodeize(
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
46
|
+
originNode, parentNode, depth) {
|
|
47
|
+
const token = this.sliceFragment(originNode.start, originNode.end);
|
|
48
|
+
const parentNamespace = parentNode && 'namespace' in parentNode ? parentNode.namespace : 'http://www.w3.org/1999/xhtml';
|
|
49
|
+
switch (originNode.type) {
|
|
50
|
+
case 'Text': {
|
|
51
|
+
return this.visitText({
|
|
52
|
+
...token,
|
|
53
|
+
depth,
|
|
54
|
+
parentNode,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
case 'Comment': {
|
|
58
|
+
return this.visitComment({
|
|
59
|
+
...token,
|
|
60
|
+
depth,
|
|
61
|
+
parentNode,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
case 'MustacheTag': {
|
|
65
|
+
return this.visitPsBlock({
|
|
66
|
+
...token,
|
|
67
|
+
depth,
|
|
68
|
+
parentNode,
|
|
69
|
+
nodeName: 'MustacheTag',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
case 'InlineComponent':
|
|
73
|
+
case 'Element': {
|
|
74
|
+
const children = originNode.children ?? [];
|
|
75
|
+
const reEndTag = new RegExp(`</${originNode.name}\\s*>$`, 'i');
|
|
76
|
+
const startTagEndOffset = children.length > 0
|
|
77
|
+
? children[0]?.start ?? 0
|
|
78
|
+
: token.raw.replace(reEndTag, '').length + token.startOffset;
|
|
79
|
+
const startTagLocation = this.sliceFragment(token.startOffset, startTagEndOffset);
|
|
80
|
+
return this.visitElement({
|
|
81
|
+
...startTagLocation,
|
|
82
|
+
depth,
|
|
83
|
+
parentNode,
|
|
84
|
+
nodeName: originNode.name,
|
|
85
|
+
namespace: getNamespace(originNode.name, parentNamespace),
|
|
86
|
+
}, originNode.children, {
|
|
87
|
+
createEndTagToken: () => {
|
|
88
|
+
if (!reEndTag.test(token.raw)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const endTagRawMatched = token.raw.match(reEndTag);
|
|
92
|
+
if (!endTagRawMatched) {
|
|
93
|
+
throw new Error('Parse error');
|
|
94
|
+
}
|
|
95
|
+
const endTagRaw = endTagRawMatched[0];
|
|
96
|
+
const endTagStartOffset = token.startOffset + token.raw.lastIndexOf(endTagRaw);
|
|
97
|
+
const endTagEndOffset = endTagStartOffset + endTagRaw.length;
|
|
98
|
+
const endTagLocation = this.sliceFragment(endTagStartOffset, endTagEndOffset);
|
|
99
|
+
return {
|
|
100
|
+
...endTagLocation,
|
|
101
|
+
depth,
|
|
102
|
+
parentNode,
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
default: {
|
|
108
|
+
return this.visitExpression({
|
|
109
|
+
...token,
|
|
110
|
+
depth,
|
|
111
|
+
parentNode,
|
|
112
|
+
}, originNode);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
visitPsBlock(token, childNodes = []) {
|
|
117
|
+
const nodes = super.visitPsBlock(token, childNodes);
|
|
118
|
+
const block = nodes.at(0);
|
|
119
|
+
if (!block || block.type !== 'psblock') {
|
|
120
|
+
throw new ParserError('Parse error', token);
|
|
121
|
+
}
|
|
122
|
+
if (nodes.length > 1) {
|
|
123
|
+
throw new ParserError('Parse error', nodes.at(1));
|
|
124
|
+
}
|
|
125
|
+
return [block];
|
|
126
|
+
}
|
|
127
|
+
visitChildren(
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
129
|
+
children, parentNode) {
|
|
130
|
+
const siblings = super.visitChildren(children, parentNode);
|
|
131
|
+
if (siblings.length > 0) {
|
|
132
|
+
throw new ParserError('Discovered child nodes with differing hierarchy levels', siblings[0]);
|
|
133
|
+
}
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
visitAttr(token) {
|
|
137
|
+
const attr = super.visitAttr(token, {
|
|
138
|
+
quoteSet: [
|
|
139
|
+
{ start: '"', end: '"' },
|
|
140
|
+
{ start: "'", end: "'" },
|
|
141
|
+
{ start: '{', end: '}' },
|
|
142
|
+
],
|
|
143
|
+
quoteInValueChars: [
|
|
144
|
+
{ start: '"', end: '"' },
|
|
145
|
+
{ start: "'", end: "'" },
|
|
146
|
+
{ start: '`', end: '`' },
|
|
147
|
+
{ start: '${', end: '}' },
|
|
148
|
+
],
|
|
149
|
+
startState:
|
|
150
|
+
// is shorthand attribute
|
|
151
|
+
token.raw.trim().startsWith('{') ? AttrState.BeforeValue : AttrState.BeforeName,
|
|
152
|
+
});
|
|
153
|
+
if (attr.type === 'spread') {
|
|
154
|
+
return attr;
|
|
155
|
+
}
|
|
156
|
+
let isDynamicValue = attr.startQuote.raw === '{' || undefined;
|
|
157
|
+
let potentialName;
|
|
158
|
+
let isDirective;
|
|
159
|
+
let isDuplicatable = false;
|
|
160
|
+
if (isDynamicValue && attr.name.raw === '') {
|
|
161
|
+
potentialName = attr.value.raw;
|
|
162
|
+
}
|
|
163
|
+
const [baseName, subName] = attr.name.raw.split(':');
|
|
164
|
+
if (subName) {
|
|
165
|
+
isDirective = true;
|
|
166
|
+
if (baseName === 'bind' && !this.specificBindDirective.has(subName)) {
|
|
167
|
+
potentialName = subName;
|
|
168
|
+
isDirective = undefined;
|
|
169
|
+
isDynamicValue = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (baseName?.toLowerCase() === 'class') {
|
|
173
|
+
isDuplicatable = true;
|
|
174
|
+
if (subName) {
|
|
175
|
+
potentialName = 'class';
|
|
176
|
+
isDynamicValue = true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (attr.startQuote.raw === '{' && attr.endQuote.raw === '}') {
|
|
180
|
+
isDynamicValue = true;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
...attr,
|
|
184
|
+
isDynamicValue,
|
|
185
|
+
isDirective,
|
|
186
|
+
isDuplicatable,
|
|
187
|
+
potentialName,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
detectElementType(nodeName) {
|
|
191
|
+
return super.detectElementType(nodeName, /[.A-Z]/);
|
|
192
|
+
}
|
|
193
|
+
visitExpression(token,
|
|
194
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
195
|
+
originBlockNode) {
|
|
196
|
+
const props = ['', 'else', 'pending', 'then', 'catch'];
|
|
197
|
+
const expressions = [];
|
|
198
|
+
const blockType = originBlockNode.type.toLowerCase().replace('block', '');
|
|
199
|
+
const nodeList = new Map();
|
|
200
|
+
for (const prop of props) {
|
|
201
|
+
let node = (originBlockNode[prop] ?? originBlockNode);
|
|
202
|
+
if (nodeList.has(node)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (node.type === 'ElseBlock' && node.children?.[0]?.elseif) {
|
|
206
|
+
node = node.children[0];
|
|
207
|
+
while (node != null) {
|
|
208
|
+
if (!['IfBlock', 'ElseBlock'].includes(node.type)) {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
const type = node.elseif ? 'elseif' : 'else';
|
|
212
|
+
nodeList.set(node, type);
|
|
213
|
+
node = node.else ?? node.children?.[0] ?? null;
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
let type = prop || blockType;
|
|
218
|
+
if (prop === 'pending') {
|
|
219
|
+
type = 'await';
|
|
220
|
+
}
|
|
221
|
+
nodeList.set(node, type);
|
|
222
|
+
}
|
|
223
|
+
let lastChild = null;
|
|
224
|
+
for (const [node, type] of nodeList.entries()) {
|
|
225
|
+
let start = node.start;
|
|
226
|
+
let end = node.end;
|
|
227
|
+
if (type === 'await') {
|
|
228
|
+
start = originBlockNode.start;
|
|
229
|
+
}
|
|
230
|
+
end = node.children?.[0]?.start ?? end;
|
|
231
|
+
if (type === 'else' && originBlockNode.type === 'EachBlock') {
|
|
232
|
+
start = lastChild?.end ?? start;
|
|
233
|
+
}
|
|
234
|
+
if (['else', 'elseif'].includes(type) && originBlockNode.type === 'IfBlock') {
|
|
235
|
+
start = lastChild?.end ?? start;
|
|
236
|
+
}
|
|
237
|
+
const tag = this.sliceFragment(start, end);
|
|
238
|
+
if (node.children && Array.isArray(node.children)) {
|
|
239
|
+
lastChild = node.children.at(-1) ?? null;
|
|
240
|
+
}
|
|
241
|
+
const expression = this.visitPsBlock({
|
|
242
|
+
...tag,
|
|
243
|
+
depth: token.depth,
|
|
244
|
+
parentNode: token.parentNode,
|
|
245
|
+
nodeName: type,
|
|
246
|
+
}, node.children)[0];
|
|
247
|
+
expressions.push(expression);
|
|
248
|
+
}
|
|
249
|
+
const lastText = this.sliceFragment(lastChild?.end ?? originBlockNode.end, originBlockNode.end);
|
|
250
|
+
if (lastText.raw) {
|
|
251
|
+
// Cut before whitespace
|
|
252
|
+
const index = lastText.raw.search(/\S/);
|
|
253
|
+
const lastToken = this.sliceFragment(lastText.startOffset + index, originBlockNode.end);
|
|
254
|
+
if (lastToken.raw) {
|
|
255
|
+
const expression = this.visitPsBlock({
|
|
256
|
+
...lastToken,
|
|
257
|
+
depth: token.depth,
|
|
258
|
+
parentNode: token.parentNode,
|
|
259
|
+
nodeName: '/' + blockType,
|
|
260
|
+
})[0];
|
|
261
|
+
expressions.push(expression);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return expressions;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export const parser = new SvelteParser();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="svelte" />
|
|
2
2
|
import type { Directive, TemplateNode, Attribute, SpreadAttribute } from 'svelte/types/compiler/interfaces';
|
|
3
3
|
export type SvelteNode = TemplateNode;
|
|
4
|
-
export
|
|
4
|
+
export declare function svelteParse(template: string): SvelteNode[];
|
|
5
5
|
export type SvelteDirective = Directive | Attribute | SpreadAttribute;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
function svelteParse(template) {
|
|
5
|
-
var _a;
|
|
6
|
-
const ast = (0, compiler_1.parse)(template, { customElement: true });
|
|
1
|
+
import { parse } from 'svelte/compiler';
|
|
2
|
+
export function svelteParse(template) {
|
|
3
|
+
const ast = parse(template, { customElement: true });
|
|
7
4
|
const start = ast.html.start;
|
|
8
|
-
const children =
|
|
5
|
+
const children = ast.html.children ?? [];
|
|
9
6
|
if (children[0] && children[0].end === start) {
|
|
10
7
|
children.shift();
|
|
11
8
|
}
|
|
12
9
|
return children;
|
|
13
10
|
}
|
|
14
|
-
exports.default = svelteParse;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HtmlParser } from '@markuplint/html-parser';
|
|
2
|
+
class SvelteKitTemplateParser extends HtmlParser {
|
|
3
|
+
constructor() {
|
|
4
|
+
super({
|
|
5
|
+
ignoreTags: [
|
|
6
|
+
{
|
|
7
|
+
type: 'sveltekit-placeholder',
|
|
8
|
+
start: '%sveltekit.',
|
|
9
|
+
end: '%',
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export const parser = new SvelteKitTemplateParser();
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/svelte-parser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.10",
|
|
4
4
|
"description": "Svelte parser for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"private": false,
|
|
9
|
-
"
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./kit": {
|
|
15
|
+
"import": "./lib/sveltekit-parser.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
10
18
|
"types": "lib/index.d.ts",
|
|
11
19
|
"publishConfig": {
|
|
12
20
|
"access": "public"
|
|
@@ -16,11 +24,10 @@
|
|
|
16
24
|
"clean": "tsc --build --clean"
|
|
17
25
|
},
|
|
18
26
|
"dependencies": {
|
|
19
|
-
"@markuplint/html-parser": "
|
|
20
|
-
"@markuplint/ml-ast": "
|
|
21
|
-
"@markuplint/parser-utils": "
|
|
22
|
-
"svelte": "^4.2.
|
|
23
|
-
"tslib": "^2.6.2"
|
|
27
|
+
"@markuplint/html-parser": "4.0.0-alpha.10",
|
|
28
|
+
"@markuplint/ml-ast": "4.0.0-alpha.10",
|
|
29
|
+
"@markuplint/parser-utils": "4.0.0-alpha.10",
|
|
30
|
+
"svelte": "^4.2.9"
|
|
24
31
|
},
|
|
25
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "b41153ea665aa8f091daf6114a06047f4ccb8350"
|
|
26
33
|
}
|
package/lib/attr.d.ts
DELETED
package/lib/attr.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.attr = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const parser_utils_1 = require("@markuplint/parser-utils");
|
|
6
|
-
const directive_tokenizer_1 = tslib_1.__importDefault(require("./directive-tokenizer"));
|
|
7
|
-
const mustacheTag = {
|
|
8
|
-
start: '{',
|
|
9
|
-
end: '}',
|
|
10
|
-
};
|
|
11
|
-
const specificBindDirective = ['bind:group', 'bind:this'];
|
|
12
|
-
function attr(
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
14
|
-
attr, rawHTML) {
|
|
15
|
-
const isShorthand = attr.value && Array.isArray(attr.value)
|
|
16
|
-
? attr.value.some((val) => val.type === 'AttributeShorthand')
|
|
17
|
-
: false;
|
|
18
|
-
const { start, end } = attr;
|
|
19
|
-
if (attr.type === 'Spread') {
|
|
20
|
-
return {
|
|
21
|
-
__spreadAttr: true,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
let token;
|
|
25
|
-
if (attr.type === 'Attribute' && !isShorthand) {
|
|
26
|
-
const { raw } = (0, parser_utils_1.sliceFragment)(rawHTML, start, end);
|
|
27
|
-
token = (0, parser_utils_1.parseAttr)(raw, start, rawHTML, {
|
|
28
|
-
valueDelimiters: [...parser_utils_1.defaultValueDelimiters, mustacheTag],
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
const { raw, startLine, startCol, startOffset } = (0, parser_utils_1.sliceFragment)(rawHTML, start, end);
|
|
33
|
-
const valueToken = isShorthand
|
|
34
|
-
? attr.name
|
|
35
|
-
: attr.expression && 'start' in attr.expression && 'end' in attr.expression
|
|
36
|
-
? (0, parser_utils_1.sliceFragment)(rawHTML, attr.expression.start, attr.expression.end).raw
|
|
37
|
-
: '';
|
|
38
|
-
token = (0, directive_tokenizer_1.default)(raw, valueToken, startLine, startCol, startOffset);
|
|
39
|
-
}
|
|
40
|
-
if (!specificBindDirective.includes(token.name.raw) && /^bind:/i.test(token.name.raw)) {
|
|
41
|
-
// Remove "bind:"
|
|
42
|
-
token.potentialName = token.name.raw.slice(5);
|
|
43
|
-
token.isDirective = undefined;
|
|
44
|
-
token.isDynamicValue = true;
|
|
45
|
-
}
|
|
46
|
-
if (isShorthand) {
|
|
47
|
-
token.potentialName = token.value.raw.trim();
|
|
48
|
-
token.isDirective = undefined;
|
|
49
|
-
token.isDynamicValue = true;
|
|
50
|
-
}
|
|
51
|
-
const [baseName, subName] = token.name.raw.split(':');
|
|
52
|
-
if ((baseName === null || baseName === void 0 ? void 0 : baseName.toLowerCase()) === 'class') {
|
|
53
|
-
token.isDuplicatable = true;
|
|
54
|
-
if (subName) {
|
|
55
|
-
token.potentialName = 'class';
|
|
56
|
-
token.isDynamicValue = true;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (token.startQuote.raw === '{' && token.endQuote.raw === '}') {
|
|
60
|
-
token.isDynamicValue = true;
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
...token,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
exports.attr = attr;
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const html_parser_1 = require("@markuplint/html-parser");
|
|
4
|
-
const parser_utils_1 = require("@markuplint/parser-utils");
|
|
5
|
-
// eslint-disable-next-line no-control-regex
|
|
6
|
-
const reNameOnly = /^[^\x00-\x1f\x7f-\x9f {>/=]+/;
|
|
7
|
-
// eslint-disable-next-line no-control-regex
|
|
8
|
-
const reBeforeStructure = /^(\s*)([^\x00-\x1f\x7f-\x9f {>/=]+)(\s*)(=)(\s*){(\s*)$/;
|
|
9
|
-
const reBeforeStructureWithoutName = /^{(\s*)$/;
|
|
10
|
-
const reAfterStructure = /(\s*)}/;
|
|
11
|
-
function directiveTokenizer(raw, rawValue, line, col, startOffset) {
|
|
12
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
13
|
-
let spacesBeforeAttrString = '';
|
|
14
|
-
let nameChars = '';
|
|
15
|
-
let spacesBeforeEqualChars = '';
|
|
16
|
-
let equalChars = null;
|
|
17
|
-
let spacesAfterEqualChars = '';
|
|
18
|
-
let valueChars = '';
|
|
19
|
-
const [before, after] = raw.split(rawValue);
|
|
20
|
-
const beforeMatchedMap = before === null || before === void 0 ? void 0 : before.match(reBeforeStructure);
|
|
21
|
-
const beforeWithoutNameMatchedMap = before === null || before === void 0 ? void 0 : before.match(reBeforeStructureWithoutName);
|
|
22
|
-
const afterMatchedMap = after === null || after === void 0 ? void 0 : after.match(reAfterStructure);
|
|
23
|
-
if (beforeMatchedMap && afterMatchedMap) {
|
|
24
|
-
spacesBeforeAttrString = (_a = beforeMatchedMap[1]) !== null && _a !== void 0 ? _a : '';
|
|
25
|
-
nameChars = (_b = beforeMatchedMap[2]) !== null && _b !== void 0 ? _b : '';
|
|
26
|
-
spacesBeforeEqualChars = (_c = beforeMatchedMap[3]) !== null && _c !== void 0 ? _c : '';
|
|
27
|
-
equalChars = (_d = beforeMatchedMap[4]) !== null && _d !== void 0 ? _d : null;
|
|
28
|
-
spacesAfterEqualChars = (_e = beforeMatchedMap[5]) !== null && _e !== void 0 ? _e : '';
|
|
29
|
-
valueChars = ((_f = beforeMatchedMap[6]) !== null && _f !== void 0 ? _f : '') + rawValue + ((_g = afterMatchedMap[1]) !== null && _g !== void 0 ? _g : '');
|
|
30
|
-
}
|
|
31
|
-
else if (beforeWithoutNameMatchedMap && afterMatchedMap) {
|
|
32
|
-
valueChars = ((_h = beforeWithoutNameMatchedMap[1]) !== null && _h !== void 0 ? _h : '') + rawValue + ((_j = afterMatchedMap[1]) !== null && _j !== void 0 ? _j : '');
|
|
33
|
-
}
|
|
34
|
-
else if (reNameOnly.test(raw)) {
|
|
35
|
-
const token = (0, html_parser_1.attrTokenizer)(raw, line, col, startOffset);
|
|
36
|
-
token.isDirective = true;
|
|
37
|
-
return token;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
throw new SyntaxError('Illegal attribute token');
|
|
41
|
-
}
|
|
42
|
-
let offset = startOffset;
|
|
43
|
-
const attrToken = (0, parser_utils_1.tokenizer)(raw, line, col, offset);
|
|
44
|
-
const spacesBeforeName = (0, parser_utils_1.tokenizer)(spacesBeforeAttrString, line, col, offset);
|
|
45
|
-
line = spacesBeforeName.endLine;
|
|
46
|
-
col = spacesBeforeName.endCol;
|
|
47
|
-
offset = spacesBeforeName.endOffset;
|
|
48
|
-
const name = (0, parser_utils_1.tokenizer)(nameChars, line, col, offset);
|
|
49
|
-
line = name.endLine;
|
|
50
|
-
col = name.endCol;
|
|
51
|
-
offset = name.endOffset;
|
|
52
|
-
const spacesBeforeEqual = (0, parser_utils_1.tokenizer)(spacesBeforeEqualChars, line, col, offset);
|
|
53
|
-
line = spacesBeforeEqual.endLine;
|
|
54
|
-
col = spacesBeforeEqual.endCol;
|
|
55
|
-
offset = spacesBeforeEqual.endOffset;
|
|
56
|
-
const equal = (0, parser_utils_1.tokenizer)(equalChars, line, col, offset);
|
|
57
|
-
line = equal.endLine;
|
|
58
|
-
col = equal.endCol;
|
|
59
|
-
offset = equal.endOffset;
|
|
60
|
-
const spacesAfterEqual = (0, parser_utils_1.tokenizer)(spacesAfterEqualChars, line, col, offset);
|
|
61
|
-
line = spacesAfterEqual.endLine;
|
|
62
|
-
col = spacesAfterEqual.endCol;
|
|
63
|
-
offset = spacesAfterEqual.endOffset;
|
|
64
|
-
const startQuote = (0, parser_utils_1.tokenizer)('{', line, col, offset);
|
|
65
|
-
line = startQuote.endLine;
|
|
66
|
-
col = startQuote.endCol;
|
|
67
|
-
offset = startQuote.endOffset;
|
|
68
|
-
const value = (0, parser_utils_1.tokenizer)(valueChars, line, col, offset);
|
|
69
|
-
line = value.endLine;
|
|
70
|
-
col = value.endCol;
|
|
71
|
-
offset = value.endOffset;
|
|
72
|
-
const endQuote = (0, parser_utils_1.tokenizer)('}', line, col, offset);
|
|
73
|
-
line = endQuote.endLine;
|
|
74
|
-
col = endQuote.endCol;
|
|
75
|
-
offset = endQuote.endOffset;
|
|
76
|
-
const result = {
|
|
77
|
-
type: 'html-attr',
|
|
78
|
-
uuid: (0, parser_utils_1.uuid)(),
|
|
79
|
-
raw: attrToken.raw,
|
|
80
|
-
startOffset: attrToken.startOffset,
|
|
81
|
-
endOffset: attrToken.endOffset,
|
|
82
|
-
startLine: attrToken.startLine,
|
|
83
|
-
endLine: attrToken.endLine,
|
|
84
|
-
startCol: attrToken.startCol,
|
|
85
|
-
endCol: attrToken.endCol,
|
|
86
|
-
spacesBeforeName,
|
|
87
|
-
name,
|
|
88
|
-
spacesBeforeEqual,
|
|
89
|
-
equal,
|
|
90
|
-
spacesAfterEqual,
|
|
91
|
-
startQuote,
|
|
92
|
-
value,
|
|
93
|
-
endQuote,
|
|
94
|
-
isDirective: true,
|
|
95
|
-
isDuplicatable: false,
|
|
96
|
-
nodeName: name.raw,
|
|
97
|
-
parentNode: null,
|
|
98
|
-
nextNode: null,
|
|
99
|
-
prevNode: null,
|
|
100
|
-
isFragment: false,
|
|
101
|
-
isGhost: false,
|
|
102
|
-
};
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
exports.default = directiveTokenizer;
|
package/lib/nodeize.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { SvelteNode } from './svelte-parser';
|
|
2
|
-
import type { MLASTNode, MLASTParentNode, ParserOptions } from '@markuplint/ml-ast';
|
|
3
|
-
export declare function nodeize(
|
|
4
|
-
originNode: SvelteNode,
|
|
5
|
-
prevNode: MLASTNode | null,
|
|
6
|
-
parentNode: MLASTParentNode | null,
|
|
7
|
-
rawHtml: string,
|
|
8
|
-
options?: ParserOptions,
|
|
9
|
-
): MLASTNode | MLASTNode[] | null;
|