@markuplint/types 3.0.0-canary.5 → 3.0.0-dev.177
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 +1 -1
- package/lib/check-multi-types.d.ts +4 -1
- package/lib/check-multi-types.js +5 -4
- package/lib/check.d.ts +6 -5
- package/lib/check.spec.js +64 -58
- package/lib/css-syntax.js +49 -47
- package/lib/css-syntax.spec.js +152 -149
- package/lib/defs.js +2 -2
- package/lib/enum.d.ts +2 -1
- package/lib/enum.js +1 -1
- package/lib/get-candidate.d.ts +4 -1
- package/lib/keyword-type.js +3 -2
- package/lib/list.d.ts +2 -1
- package/lib/list.js +2 -1
- package/lib/list.spec.js +118 -117
- package/lib/match-result.d.ts +21 -8
- package/lib/match-result.js +2 -1
- package/lib/number.d.ts +1 -1
- package/lib/primitive/index.spec.js +53 -52
- package/lib/primitive/is-quantity.d.ts +5 -1
- package/lib/primitive/is-uint.d.ts +6 -3
- package/lib/primitive/split-unit.d.ts +2 -2
- package/lib/primitive/split-unit.js +2 -2
- package/lib/rfc/is-bcp-47.spec.js +9 -8
- package/lib/token/token-collection.d.ts +71 -56
- package/lib/token/token-collection.js +30 -23
- package/lib/token/token-collection.spec.js +156 -134
- package/lib/token/token.d.ts +58 -52
- package/lib/token/token.js +19 -20
- package/lib/token/types.d.ts +3 -0
- package/lib/token/types.js +2 -0
- package/lib/types.d.ts +79 -55
- package/lib/types.schema.d.ts +1084 -31
- package/lib/w3c/check-serialized-permissions-policy.spec.js +30 -28
- package/lib/whatwg/check-autocomplete.js +6 -6
- package/lib/whatwg/check-autocomplete.spec.js +361 -360
- package/lib/whatwg/check-datetime/datetime-tokens.d.ts +21 -1
- package/lib/whatwg/check-datetime/datetime-tokens.js +9 -6
- package/lib/whatwg/check-datetime/duration-string.js +12 -2
- package/lib/whatwg/check-datetime/index.spec.js +277 -276
- package/lib/whatwg/check-datetime/local-date-and-time-string.js +6 -2
- package/lib/whatwg/check-datetime/time-zone-offset-string.d.ts +1 -1
- package/lib/whatwg/check-datetime/time-zone-offset-string.js +3 -2
- package/lib/whatwg/check-mime-type.d.ts +4 -4
- package/lib/whatwg/check-mime-type.js +1 -1
- package/lib/whatwg/check-mime-type.spec.js +53 -52
- package/lib/whatwg/is-abs-url.spec.js +6 -5
- package/lib/whatwg/is-itemprop-name.js +1 -1
- package/package.json +12 -10
- package/{src/check.spec.ts → test/check.spec.js} +7 -1
- package/{src/css-syntax.spec.ts → test/css-syntax.spec.js} +10 -12
- package/{src/list.spec.ts → test/list.spec.js} +7 -7
- package/{src/primitive/index.spec.ts → test/primitive/index.spec.js} +1 -1
- package/{src/rfc/is-bcp-47.spec.ts → test/rfc/is-bcp-47.spec.js} +1 -1
- package/{src/token/token-collection.spec.ts → test/token/token-collection.spec.js} +2 -3
- package/{src/w3c/check-serialized-permissions-policy.spec.ts → test/w3c/check-serialized-permissions-policy.spec.js} +1 -3
- package/{src/whatwg/check-autocomplete.spec.ts → test/whatwg/check-autocomplete.spec.js} +1 -1
- package/{src/whatwg/check-datetime/index.spec.ts → test/whatwg/check-datetime/index.spec.js} +18 -15
- package/{src/whatwg/check-mime-type.spec.ts → test/whatwg/check-mime-type.spec.js} +1 -1
- package/{src/whatwg/is-abs-url.spec.ts → test/whatwg/is-abs-url.spec.js} +1 -1
- package/types.schema.json +369 -318
- package/gen/specific-schema.json +0 -98
- package/gen/types.ts +0 -66
- package/src/check-multi-types.ts +0 -35
- package/src/check.ts +0 -48
- package/src/css-syntax.ts +0 -188
- package/src/debug.ts +0 -3
- package/src/defs.ts +0 -811
- package/src/enum.ts +0 -25
- package/src/get-candidate.ts +0 -24
- package/src/index.ts +0 -3
- package/src/keyword-type.ts +0 -64
- package/src/list.ts +0 -34
- package/src/match-result.ts +0 -49
- package/src/number.ts +0 -46
- package/src/primitive/index.ts +0 -7
- package/src/primitive/is-float.ts +0 -8
- package/src/primitive/is-int.ts +0 -8
- package/src/primitive/is-non-zero-uint.ts +0 -8
- package/src/primitive/is-quantity.ts +0 -38
- package/src/primitive/is-uint.ts +0 -15
- package/src/primitive/range.ts +0 -14
- package/src/primitive/split-unit.ts +0 -20
- package/src/rfc/is-bcp-47.ts +0 -13
- package/src/token/index.ts +0 -2
- package/src/token/token-collection.ts +0 -444
- package/src/token/token.ts +0 -144
- package/src/types.schema.ts +0 -1062
- package/src/types.ts +0 -118
- package/src/w3c/check-serialized-permissions-policy.ts +0 -303
- package/src/whatwg/check-autocomplete.ts +0 -380
- package/src/whatwg/check-datetime/date-string.ts +0 -44
- package/src/whatwg/check-datetime/datetime-tokens.ts +0 -600
- package/src/whatwg/check-datetime/duration-string.ts +0 -399
- package/src/whatwg/check-datetime/global-date-and-time-string.ts +0 -96
- package/src/whatwg/check-datetime/index.ts +0 -36
- package/src/whatwg/check-datetime/local-date-and-time-string.ts +0 -163
- package/src/whatwg/check-datetime/month-string.ts +0 -31
- package/src/whatwg/check-datetime/time-string.ts +0 -49
- package/src/whatwg/check-datetime/time-zone-offset-string.ts +0 -93
- package/src/whatwg/check-datetime/week-string.ts +0 -41
- package/src/whatwg/check-datetime/year-string.ts +0 -26
- package/src/whatwg/check-datetime/yearless-date-string.ts +0 -38
- package/src/whatwg/check-mime-type.ts +0 -46
- package/src/whatwg/is-abs-url.ts +0 -31
- package/src/whatwg/is-browser-context-name.ts +0 -16
- package/src/whatwg/is-custom-element-name.ts +0 -76
- package/src/whatwg/is-itemprop-name.ts +0 -17
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,444 +0,0 @@
|
|
|
1
|
-
import type { UnmatchedResult } from '..';
|
|
2
|
-
import type { Expect, Result, List } from '../types';
|
|
3
|
-
|
|
4
|
-
import { matched, unmatched } from '../match-result';
|
|
5
|
-
|
|
6
|
-
import { Token } from './token';
|
|
7
|
-
|
|
8
|
-
type TokenCollectionOptions = Partial<
|
|
9
|
-
Omit<List, 'token'> & {
|
|
10
|
-
specificSeparator: string | string[];
|
|
11
|
-
}
|
|
12
|
-
>;
|
|
13
|
-
|
|
14
|
-
export type TokenEachCheck = (head: Token | null, tail: TokenCollection) => Result | void;
|
|
15
|
-
|
|
16
|
-
export class TokenCollection extends Array<Token> {
|
|
17
|
-
static fromPatterns(
|
|
18
|
-
value: Token | string,
|
|
19
|
-
patterns: RegExp[],
|
|
20
|
-
typeOptions?: Omit<TokenCollectionOptions, 'specificSeparator'> & { repeat?: boolean },
|
|
21
|
-
) {
|
|
22
|
-
const origin = typeof value === 'string' ? value : value.origin;
|
|
23
|
-
let strings = typeof value === 'string' ? value : value.value;
|
|
24
|
-
let cumulativeOffset = typeof value === 'string' ? 0 : value.offset;
|
|
25
|
-
const tokens: Token[] = [];
|
|
26
|
-
|
|
27
|
-
function addToken(tokenValue: string) {
|
|
28
|
-
const token = new Token(tokenValue, cumulativeOffset, origin);
|
|
29
|
-
tokens.push(token);
|
|
30
|
-
|
|
31
|
-
strings = strings.slice(tokenValue.length);
|
|
32
|
-
cumulativeOffset += tokenValue.length;
|
|
33
|
-
|
|
34
|
-
return token;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let isBroken = false;
|
|
38
|
-
do {
|
|
39
|
-
isBroken = false;
|
|
40
|
-
for (const pattern of patterns) {
|
|
41
|
-
const res = pattern.exec(strings);
|
|
42
|
-
let value: string;
|
|
43
|
-
|
|
44
|
-
if (!res) {
|
|
45
|
-
isBroken = true;
|
|
46
|
-
value = '';
|
|
47
|
-
} else {
|
|
48
|
-
if (res.index !== 0) {
|
|
49
|
-
value = strings.slice(res.index + res[0].length);
|
|
50
|
-
} else {
|
|
51
|
-
value = res[0] || '';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const token = addToken(value);
|
|
56
|
-
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
token._ = pattern;
|
|
59
|
-
}
|
|
60
|
-
if (isBroken) {
|
|
61
|
-
addToken(strings);
|
|
62
|
-
}
|
|
63
|
-
} while (typeOptions?.repeat && strings);
|
|
64
|
-
|
|
65
|
-
if (strings) {
|
|
66
|
-
addToken(strings);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return TokenCollection._new(tokens, new TokenCollection('', typeOptions));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
static get [Symbol.species]() {
|
|
73
|
-
return Array;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
readonly allowEmpty: NonNullable<List['allowEmpty']>;
|
|
77
|
-
readonly caseInsensitive: NonNullable<List['caseInsensitive']>;
|
|
78
|
-
readonly disallowToSurroundBySpaces: NonNullable<List['disallowToSurroundBySpaces']>;
|
|
79
|
-
readonly number: List['number'];
|
|
80
|
-
readonly ordered: NonNullable<List['ordered']>;
|
|
81
|
-
readonly separator: NonNullable<List['separator']>;
|
|
82
|
-
readonly unique: NonNullable<List['unique']>;
|
|
83
|
-
|
|
84
|
-
constructor(value?: string, typeOptions?: TokenCollectionOptions);
|
|
85
|
-
constructor(value?: number); // for map method etc.
|
|
86
|
-
constructor(value?: string | number, typeOptions?: TokenCollectionOptions) {
|
|
87
|
-
super();
|
|
88
|
-
|
|
89
|
-
this.disallowToSurroundBySpaces = typeOptions?.disallowToSurroundBySpaces || false;
|
|
90
|
-
this.allowEmpty = typeOptions?.allowEmpty || true;
|
|
91
|
-
this.ordered = typeOptions?.ordered || false;
|
|
92
|
-
this.unique = typeOptions?.unique || false;
|
|
93
|
-
this.caseInsensitive = typeOptions?.caseInsensitive || true;
|
|
94
|
-
this.number = typeOptions?.number;
|
|
95
|
-
this.separator = typeOptions?.separator || 'space';
|
|
96
|
-
|
|
97
|
-
if (typeof value === 'number') {
|
|
98
|
-
this.length = value;
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!value) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const separators: string[] = [];
|
|
107
|
-
if (this.separator === 'comma') {
|
|
108
|
-
separators.push(',');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (typeOptions?.specificSeparator) {
|
|
112
|
-
if (Array.isArray(typeOptions.specificSeparator)) {
|
|
113
|
-
separators.push(...typeOptions.specificSeparator);
|
|
114
|
-
} else {
|
|
115
|
-
separators.push(typeOptions.specificSeparator);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const chars = value.split('');
|
|
120
|
-
const values: string[] = [];
|
|
121
|
-
let char: string | undefined;
|
|
122
|
-
while ((char = chars.shift())) {
|
|
123
|
-
const last = values.pop();
|
|
124
|
-
if (!last) {
|
|
125
|
-
values.push(char);
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
const lastChar = last[0];
|
|
129
|
-
if (
|
|
130
|
-
!separators.includes(char) &&
|
|
131
|
-
!separators.includes(last[0]) &&
|
|
132
|
-
((Token.whitespace.includes(lastChar) && Token.whitespace.includes(char)) ||
|
|
133
|
-
(!Token.whitespace.includes(lastChar) && !Token.whitespace.includes(char)))
|
|
134
|
-
) {
|
|
135
|
-
values.push(last + char);
|
|
136
|
-
} else {
|
|
137
|
-
values.push(last);
|
|
138
|
-
values.push(char);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
let offset = 0;
|
|
143
|
-
values.forEach(v => {
|
|
144
|
-
const token = new Token(v, offset, value, separators);
|
|
145
|
-
this.push(token);
|
|
146
|
-
offset += v.length;
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
get value() {
|
|
151
|
-
const value = this.map(t => t.value).join('');
|
|
152
|
-
return value;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
check(options: { expects?: Expect[]; ref?: string; cache?: boolean } = {}) {
|
|
156
|
-
const { expects, ref } = options;
|
|
157
|
-
|
|
158
|
-
if (this.disallowToSurroundBySpaces) {
|
|
159
|
-
for (const token of this) {
|
|
160
|
-
if (token.type === 13) {
|
|
161
|
-
return token.unmatched({
|
|
162
|
-
reason: 'unexpected-space',
|
|
163
|
-
ref,
|
|
164
|
-
expects,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (this.separator === 'comma') {
|
|
171
|
-
const tokensWithoutWP = this.filter(token => token.type !== Token.WhiteSpace);
|
|
172
|
-
const consecutiveComma = tokensWithoutWP.getConsecutiveToken(Token.Comma);
|
|
173
|
-
if (consecutiveComma) {
|
|
174
|
-
return consecutiveComma.unmatched({
|
|
175
|
-
reason: 'unexpected-comma',
|
|
176
|
-
ref,
|
|
177
|
-
expects,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (tokensWithoutWP[0] && tokensWithoutWP[0].type === Token.Comma) {
|
|
182
|
-
return tokensWithoutWP[0].unmatched({
|
|
183
|
-
reason: 'unexpected-comma',
|
|
184
|
-
ref,
|
|
185
|
-
expects,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const takeTurnsError = tokensWithoutWP.takeTurns([Token.Ident, Token.Comma], Token.Ident);
|
|
190
|
-
if (takeTurnsError) {
|
|
191
|
-
if (takeTurnsError.unexpectedLastToken) {
|
|
192
|
-
return takeTurnsError.token.unmatched({
|
|
193
|
-
reason: 'extra-token',
|
|
194
|
-
ref,
|
|
195
|
-
expects,
|
|
196
|
-
});
|
|
197
|
-
} else if (takeTurnsError.token.type === takeTurnsError.expectedTokenNumber) {
|
|
198
|
-
// Consecutive commas
|
|
199
|
-
return takeTurnsError.token.unmatched({
|
|
200
|
-
reason: 'unexpected-comma',
|
|
201
|
-
ref,
|
|
202
|
-
expects,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
return takeTurnsError.token.unmatched({
|
|
206
|
-
reason: 'missing-comma',
|
|
207
|
-
ref,
|
|
208
|
-
expects,
|
|
209
|
-
candidate: `,${takeTurnsError.token.value}`,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const identTokens = this.getIdentTokens();
|
|
215
|
-
|
|
216
|
-
const allowEmpty = this.allowEmpty ?? true;
|
|
217
|
-
if (!allowEmpty && identTokens.length === 0) {
|
|
218
|
-
return unmatched(this.value, 'empty-token', {
|
|
219
|
-
ref,
|
|
220
|
-
expects,
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (this.unique) {
|
|
225
|
-
const duplicated = identTokens.getDuplicated();
|
|
226
|
-
if (duplicated) {
|
|
227
|
-
return duplicated.unmatched({
|
|
228
|
-
partName: 'the content of the list',
|
|
229
|
-
reason: 'duplicated',
|
|
230
|
-
ref,
|
|
231
|
-
expects,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return matched();
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
chunk(split: number) {
|
|
240
|
-
const chunks: TokenCollection[] = [];
|
|
241
|
-
const tokens = this.slice();
|
|
242
|
-
while (tokens.length) {
|
|
243
|
-
const chunkTokens = tokens.splice(0, split);
|
|
244
|
-
const chunk = TokenCollection._new(chunkTokens, this);
|
|
245
|
-
chunks.push(chunk);
|
|
246
|
-
}
|
|
247
|
-
return chunks;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
compareTokens(callback: (prev: Token, current: Token) => Token | null | void) {
|
|
251
|
-
const _tokens = this.slice();
|
|
252
|
-
let prev = _tokens.shift();
|
|
253
|
-
while (prev) {
|
|
254
|
-
const current = _tokens.shift();
|
|
255
|
-
if (!current) {
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const result = callback(prev, current);
|
|
259
|
-
if (result) {
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
prev = current;
|
|
263
|
-
}
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
divide(position: number) {
|
|
268
|
-
const _a = this.slice(0, position);
|
|
269
|
-
const _b = this.slice(position);
|
|
270
|
-
const a = TokenCollection._new(_a, this);
|
|
271
|
-
const b = TokenCollection._new(_b, this);
|
|
272
|
-
return [a, b] as const;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
eachCheck(...callbacks: TokenEachCheck[]): Result {
|
|
276
|
-
let headAndTail = this.headAndTail();
|
|
277
|
-
let head = headAndTail.head;
|
|
278
|
-
let tail = headAndTail.tail;
|
|
279
|
-
let prev: Token | null = null;
|
|
280
|
-
let cumulativeOffset = 0;
|
|
281
|
-
let passCount = 0;
|
|
282
|
-
let firstUnmatched: UnmatchedResult | null = null;
|
|
283
|
-
let wait = 20;
|
|
284
|
-
for (const callback of callbacks) {
|
|
285
|
-
wait--;
|
|
286
|
-
const result = callback.call(this, head, tail);
|
|
287
|
-
if (result && !result.matched) {
|
|
288
|
-
passCount += result.passCount || 0;
|
|
289
|
-
if (prev && result.offset === 0 && result.length === 0) {
|
|
290
|
-
const { offset, line, column } = Token.shiftLocation(prev, cumulativeOffset);
|
|
291
|
-
firstUnmatched = firstUnmatched || {
|
|
292
|
-
...result,
|
|
293
|
-
offset,
|
|
294
|
-
line,
|
|
295
|
-
column,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
if (!prev && this.value.length === 0) {
|
|
299
|
-
firstUnmatched = firstUnmatched || {
|
|
300
|
-
...result,
|
|
301
|
-
reason: 'empty-token',
|
|
302
|
-
expects: undefined,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
switch (result.reason) {
|
|
306
|
-
case 'extra-token': {
|
|
307
|
-
passCount += 1;
|
|
308
|
-
break;
|
|
309
|
-
}
|
|
310
|
-
default: {
|
|
311
|
-
if (typeof result.reason !== 'string') {
|
|
312
|
-
passCount += 2 * wait;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
firstUnmatched = firstUnmatched || result;
|
|
317
|
-
} else if (result && !firstUnmatched && result.matched) {
|
|
318
|
-
return result;
|
|
319
|
-
} else {
|
|
320
|
-
if (head?.value && !head.match(/^\s*$/)) {
|
|
321
|
-
passCount += 4 * wait;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
cumulativeOffset = head?.length || 0;
|
|
325
|
-
headAndTail = tail.headAndTail();
|
|
326
|
-
prev = head;
|
|
327
|
-
head = headAndTail.head;
|
|
328
|
-
tail = headAndTail.tail;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (firstUnmatched) {
|
|
332
|
-
const res = {
|
|
333
|
-
...firstUnmatched,
|
|
334
|
-
passCount,
|
|
335
|
-
};
|
|
336
|
-
return res;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return matched();
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
filter(callback: (value: Token, index: number, array: Token[]) => boolean) {
|
|
343
|
-
return TokenCollection._new(super.filter(callback), this);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
getConsecutiveToken(tokenType: number) {
|
|
347
|
-
const resultToken = this.compareTokens((prev, current) => {
|
|
348
|
-
if (prev.type === tokenType && current.type === tokenType) {
|
|
349
|
-
return current;
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
return resultToken || null;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
getDuplicated() {
|
|
356
|
-
const aList = this.slice();
|
|
357
|
-
const bList = this.slice();
|
|
358
|
-
for (const aToken of aList) {
|
|
359
|
-
for (const bToken of bList) {
|
|
360
|
-
if (aToken.offset === bToken.offset) {
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
let a = aToken.value;
|
|
364
|
-
let b = bToken.value;
|
|
365
|
-
if (this.caseInsensitive) {
|
|
366
|
-
a = a.toLowerCase();
|
|
367
|
-
b = b.toLowerCase();
|
|
368
|
-
}
|
|
369
|
-
if (a === b) {
|
|
370
|
-
return bToken;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return null;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
getIdentTokens() {
|
|
378
|
-
return this.filter(token => token.type === Token.Ident);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
*
|
|
383
|
-
* @param value The token value or the token type or its list
|
|
384
|
-
*/
|
|
385
|
-
has(value: string | RegExp | number | (string | RegExp | number)[]) {
|
|
386
|
-
return this.some(t => t.match(value));
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
headAndTail(): { head: Token | null; tail: TokenCollection } {
|
|
390
|
-
const copy = this.slice();
|
|
391
|
-
const head = copy.shift();
|
|
392
|
-
if (!head) {
|
|
393
|
-
return { head: head || null, tail: TokenCollection._new([], this) };
|
|
394
|
-
}
|
|
395
|
-
const tail = TokenCollection._new(copy, this);
|
|
396
|
-
return { head, tail };
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
*
|
|
401
|
-
* @param value The token value or the token type or its list
|
|
402
|
-
*/
|
|
403
|
-
search(value: string | RegExp | number | (string | RegExp | number)[]) {
|
|
404
|
-
for (const token of this) {
|
|
405
|
-
if (token.includes(value)) {
|
|
406
|
-
return token;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
return null;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
takeTurns(tokenNumbers: ReadonlyArray<number>, lastTokenNumber?: number) {
|
|
413
|
-
const tokens = this.slice();
|
|
414
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
415
|
-
const token = tokens[i];
|
|
416
|
-
const expectedTokenNumber = tokenNumbers[i % tokenNumbers.length];
|
|
417
|
-
if (token.type !== expectedTokenNumber) {
|
|
418
|
-
return {
|
|
419
|
-
unexpectedLastToken: false,
|
|
420
|
-
expectedTokenNumber,
|
|
421
|
-
token,
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
if (lastTokenNumber != null && i === tokens.length - 1 && token.type !== lastTokenNumber) {
|
|
425
|
-
return {
|
|
426
|
-
unexpectedLastToken: true,
|
|
427
|
-
expectedTokenNumber,
|
|
428
|
-
token,
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
toJSON() {
|
|
436
|
-
return this.map(t => t.toJSON());
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
private static _new(tokens: Token[], old?: TokenCollection) {
|
|
440
|
-
const newCollection = new TokenCollection('', old);
|
|
441
|
-
newCollection.push(...tokens);
|
|
442
|
-
return newCollection;
|
|
443
|
-
}
|
|
444
|
-
}
|
package/src/token/token.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import type { UnmatchedResult, UnmatchedResultOptions, UnmatchedResultReason } from '../types';
|
|
2
|
-
|
|
3
|
-
export class Token {
|
|
4
|
-
/**
|
|
5
|
-
* @see https://github.com/csstree/csstree/blob/master/lib/tokenizer/types.js
|
|
6
|
-
*/
|
|
7
|
-
static readonly Comma = 18;
|
|
8
|
-
static readonly Ident = 1;
|
|
9
|
-
static readonly WhiteSpace = 13;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* ASCII whitespace is
|
|
13
|
-
* - U+0009 TAB
|
|
14
|
-
* - U+000A LF
|
|
15
|
-
* - U+000C FF
|
|
16
|
-
* - U+000D CR
|
|
17
|
-
* - U+0020 SPACE.
|
|
18
|
-
*
|
|
19
|
-
* @see https://infra.spec.whatwg.org/#ascii-whitespace
|
|
20
|
-
*/
|
|
21
|
-
static readonly whitespace: ReadonlyArray<string> = ['\u0009', '\u000A', '\u000C', '\u000D', '\u0020'];
|
|
22
|
-
|
|
23
|
-
static getCol(value: string, offset: number) {
|
|
24
|
-
const lines = value.slice(0, offset).split(/\n/g);
|
|
25
|
-
return lines[lines.length - 1].length + 1;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static getLine(value: string, offset: number) {
|
|
29
|
-
return value.slice(0, offset).split(/\n/g).length;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static getType(value: string, separators?: string[]) {
|
|
33
|
-
if (Token.whitespace.includes(value[0])) {
|
|
34
|
-
return Token.WhiteSpace;
|
|
35
|
-
}
|
|
36
|
-
if (separators?.includes(value[0])) {
|
|
37
|
-
switch (value[0]) {
|
|
38
|
-
case ',':
|
|
39
|
-
return Token.Comma;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return Token.Ident;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static shiftLocation(token: Token, offset: number) {
|
|
46
|
-
const shifted = token.offset + offset;
|
|
47
|
-
return {
|
|
48
|
-
offset: shifted,
|
|
49
|
-
line: Token.getLine(token.#originalValue, shifted),
|
|
50
|
-
column: Token.getCol(token.#originalValue, shifted),
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
readonly offset: number;
|
|
55
|
-
#originalValue: string;
|
|
56
|
-
readonly type: number;
|
|
57
|
-
readonly value: string;
|
|
58
|
-
|
|
59
|
-
constructor(value: string, offset: number, originalValue: string, separators?: string[]) {
|
|
60
|
-
this.type = Token.getType(value, separators);
|
|
61
|
-
this.value = value;
|
|
62
|
-
this.offset = offset;
|
|
63
|
-
this.#originalValue = originalValue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
get length() {
|
|
67
|
-
return this.value.length;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
get origin() {
|
|
71
|
-
return this.#originalValue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
*
|
|
76
|
-
* @param value The token value or the token type or its list
|
|
77
|
-
*/
|
|
78
|
-
includes(value: string | RegExp | number | (string | RegExp | number)[], caseInsensitive?: boolean): boolean {
|
|
79
|
-
if (Array.isArray(value)) {
|
|
80
|
-
return value.some(v => this.includes(v));
|
|
81
|
-
}
|
|
82
|
-
if (typeof value === 'string') {
|
|
83
|
-
const a = caseInsensitive ? this.value.toLowerCase() : this.value;
|
|
84
|
-
const b = caseInsensitive ? value.toLowerCase() : value;
|
|
85
|
-
return a.indexOf(b) !== -1;
|
|
86
|
-
}
|
|
87
|
-
if (value instanceof RegExp) {
|
|
88
|
-
const pattern = new RegExp(value, caseInsensitive ? 'i' : '');
|
|
89
|
-
return pattern.test(this.value);
|
|
90
|
-
}
|
|
91
|
-
return this.type === value;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
*
|
|
96
|
-
* @param value The token value or the token type or its list
|
|
97
|
-
*/
|
|
98
|
-
match(value: string | RegExp | number | (string | RegExp | number)[], caseInsensitive?: boolean): boolean {
|
|
99
|
-
if (Array.isArray(value)) {
|
|
100
|
-
return value.some(v => this.match(v));
|
|
101
|
-
}
|
|
102
|
-
if (typeof value === 'string') {
|
|
103
|
-
const a = caseInsensitive ? this.value.toLowerCase() : this.value;
|
|
104
|
-
const b = caseInsensitive ? value.toLowerCase() : value;
|
|
105
|
-
return a === b;
|
|
106
|
-
}
|
|
107
|
-
if (value instanceof RegExp) {
|
|
108
|
-
const pattern = new RegExp(value, caseInsensitive ? 'i' : '');
|
|
109
|
-
return pattern.test(this.value);
|
|
110
|
-
}
|
|
111
|
-
return this.type === value;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
toJSON() {
|
|
115
|
-
return {
|
|
116
|
-
type: this.type,
|
|
117
|
-
value: this.value,
|
|
118
|
-
offset: this.offset,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
toNumber() {
|
|
123
|
-
return parseFloat(this.value);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
unmatched(
|
|
127
|
-
options?: UnmatchedResultOptions & {
|
|
128
|
-
ref?: string;
|
|
129
|
-
reason?: UnmatchedResultReason;
|
|
130
|
-
},
|
|
131
|
-
): UnmatchedResult {
|
|
132
|
-
return {
|
|
133
|
-
...options,
|
|
134
|
-
matched: false,
|
|
135
|
-
ref: options?.ref || null,
|
|
136
|
-
raw: this.value,
|
|
137
|
-
offset: this.offset,
|
|
138
|
-
length: this.value.length,
|
|
139
|
-
line: Token.getLine(this.#originalValue, this.offset),
|
|
140
|
-
column: Token.getCol(this.#originalValue, this.offset),
|
|
141
|
-
reason: options?.reason ?? 'syntax-error',
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|