@markuplint/types 3.0.0-alpha.0 → 3.0.0-alpha.2
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/css-syntax.spec.js +1 -1
- package/lib/defs.js +4 -4
- package/lib/get-candidate.d.ts +3 -0
- package/lib/{get-candicate.js → get-candidate.js} +8 -8
- package/lib/list.spec.js +4 -4
- package/lib/number.js +4 -4
- package/lib/primitive/is-uint.d.ts +1 -1
- package/lib/primitive/is-uint.js +4 -4
- package/lib/token/token-collection.d.ts +21 -21
- package/lib/token/token-collection.js +101 -101
- package/lib/token/token-collection.spec.js +2 -2
- package/lib/token/token.d.ts +22 -22
- package/lib/token/token.js +36 -36
- package/lib/types.d.ts +2 -2
- package/lib/types.schema.d.ts +3 -0
- package/lib/whatwg/check-autocomplete.js +55 -15
- package/lib/whatwg/check-autocomplete.spec.js +19 -10
- package/lib/whatwg/check-datetime/datetime-tokens.d.ts +1 -1
- package/lib/whatwg/check-datetime/datetime-tokens.js +16 -16
- package/lib/whatwg/check-datetime/global-date-and-time-string.js +3 -3
- package/lib/whatwg/check-datetime/local-date-and-time-string.js +2 -2
- package/lib/whatwg/check-datetime/time-string.js +1 -1
- package/lib/whatwg/check-datetime/time-zone-offset-string.js +4 -4
- package/lib/whatwg/check-mime-type.js +1 -1
- package/lib/whatwg/check-mime-type.spec.js +3 -3
- package/package.json +4 -4
- package/src/css-syntax.spec.ts +1 -1
- package/src/defs.ts +4 -4
- package/src/{get-candicate.ts → get-candidate.ts} +6 -6
- package/src/list.spec.ts +4 -4
- package/src/number.ts +4 -4
- package/src/primitive/is-uint.ts +4 -4
- package/src/token/token-collection.spec.ts +2 -2
- package/src/token/token-collection.ts +113 -113
- package/src/token/token.ts +58 -58
- package/src/types.schema.ts +3 -0
- package/src/types.ts +2 -2
- package/src/whatwg/check-autocomplete.spec.ts +19 -10
- package/src/whatwg/check-autocomplete.ts +71 -15
- package/src/whatwg/check-datetime/datetime-tokens.ts +18 -18
- package/src/whatwg/check-datetime/global-date-and-time-string.ts +3 -3
- package/src/whatwg/check-datetime/local-date-and-time-string.ts +4 -4
- package/src/whatwg/check-datetime/time-string.ts +2 -2
- package/src/whatwg/check-datetime/time-zone-offset-string.ts +4 -4
- package/src/whatwg/check-mime-type.spec.ts +3 -3
- package/src/whatwg/check-mime-type.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/get-candicate.d.ts +0 -3
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ check('2020-02-30', 'DateTime');
|
|
|
61
61
|
| `BrowsingContextNameOrKeyword` | `a[target]` and more | [WHATWG](https://html.spec.whatwg.org/multipage/browsers.html#valid-browsing-context-name-or-keyword) | ✅ |
|
|
62
62
|
| `HTTPSchemaURL` | `a[ping]` (as list) and more | [WHATWG](https://html.spec.whatwg.org/multipage/links.html#ping) | ✅ |
|
|
63
63
|
| `MIMEType` | `embed[type]` and more | [WHATWG](https://mimesniff.spec.whatwg.org/#valid-mime-type) | ✅ |
|
|
64
|
-
| `ItemProp` | The `itemprop`
|
|
64
|
+
| `ItemProp` | The `itemprop` attribute (as list) | [WHATWG](https://html.spec.whatwg.org/multipage/microdata.html#names:-the-itemprop-attribute) | ✅ |
|
|
65
65
|
| `Srcset` | `img[srcset]` and more | [WHATWG](https://html.spec.whatwg.org/multipage/images.html#srcset-attributes) | ✅ |
|
|
66
66
|
| `SourceSizeList` | `img[sizes]` and more | [WHATWG](https://html.spec.whatwg.org/multipage/images.html#sizes-attributes) | ✅ |
|
|
67
67
|
| `IconSize` | `link[sizes]` (as list) | [WHATWG](https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes) | ✅ |
|
package/lib/css-syntax.spec.js
CHANGED
|
@@ -106,7 +106,7 @@ test('custom-type-checking', () => {
|
|
|
106
106
|
expect((0, css_syntax_1.cssSyntaxMatch)('1', custom).matched).toBe(true);
|
|
107
107
|
expect((0, css_syntax_1.cssSyntaxMatch)('0', custom).matched).toBe(false);
|
|
108
108
|
});
|
|
109
|
-
test('case-
|
|
109
|
+
test('case-sensitive', () => {
|
|
110
110
|
const custom = {
|
|
111
111
|
ref: 'n/a',
|
|
112
112
|
caseSensitive: true,
|
package/lib/defs.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.tokenizers = exports.types = void 0;
|
|
4
4
|
const check_multi_types_1 = require("./check-multi-types");
|
|
5
|
-
const
|
|
5
|
+
const get_candidate_1 = require("./get-candidate");
|
|
6
6
|
const match_result_1 = require("./match-result");
|
|
7
7
|
const primitive_1 = require("./primitive");
|
|
8
8
|
const is_bcp_47_1 = require("./rfc/is-bcp-47");
|
|
@@ -275,8 +275,8 @@ exports.types = {
|
|
|
275
275
|
return (0, match_result_1.matched)();
|
|
276
276
|
}
|
|
277
277
|
if (value[0] === '_') {
|
|
278
|
-
const
|
|
279
|
-
return (0, match_result_1.unmatched)(value, 'unexpected-token', {
|
|
278
|
+
const candidate = (0, get_candidate_1.getCandidate)(value, keywords);
|
|
279
|
+
return (0, match_result_1.unmatched)(value, 'unexpected-token', { candidate });
|
|
280
280
|
}
|
|
281
281
|
return (0, match_result_1.matches)((0, is_browser_context_name_1.isBrowserContextName)())(value);
|
|
282
282
|
},
|
|
@@ -420,7 +420,7 @@ exports.types = {
|
|
|
420
420
|
if (value === 'any') {
|
|
421
421
|
return (0, match_result_1.matched)();
|
|
422
422
|
}
|
|
423
|
-
const tokens = new token_1.TokenCollection(value, {
|
|
423
|
+
const tokens = new token_1.TokenCollection(value, { specificSeparator: 'x' });
|
|
424
424
|
const [width, sep, height, ...tail] = tokens;
|
|
425
425
|
if (!width) {
|
|
426
426
|
return (0, match_result_1.unmatched)(value, 'unexpected-token');
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getCandidate = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const leven_1 = tslib_1.__importDefault(require("leven"));
|
|
6
|
-
function
|
|
6
|
+
function getCandidate(value, ...candidates) {
|
|
7
7
|
if (!value) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
-
const list =
|
|
11
|
-
let
|
|
10
|
+
const list = candidates.flat(2).filter((s) => !!s);
|
|
11
|
+
let candidate;
|
|
12
12
|
let maxRatio = 0;
|
|
13
13
|
list.forEach(word => {
|
|
14
14
|
const dist = (0, leven_1.default)(value.trim().toLowerCase(), word.trim().toLowerCase());
|
|
15
15
|
const ratio = 1 - dist / word.length;
|
|
16
16
|
if (0.5 <= ratio && maxRatio < ratio) {
|
|
17
|
-
|
|
17
|
+
candidate = word;
|
|
18
18
|
}
|
|
19
19
|
maxRatio = Math.max(ratio, maxRatio);
|
|
20
20
|
});
|
|
21
|
-
if (value ===
|
|
21
|
+
if (value === candidate) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
return
|
|
24
|
+
return candidate;
|
|
25
25
|
}
|
|
26
|
-
exports.
|
|
26
|
+
exports.getCandidate = getCandidate;
|
package/lib/list.spec.js
CHANGED
|
@@ -48,7 +48,7 @@ test('Zero comma (disallowToSurroundBySpaces)', () => {
|
|
|
48
48
|
test('Location of the token', () => {
|
|
49
49
|
const type = { token: 'Accept', separator: 'comma' };
|
|
50
50
|
expect((0, list_1.checkList)('x/y;a=b', type)).toStrictEqual({
|
|
51
|
-
|
|
51
|
+
candidate: 'x/y',
|
|
52
52
|
column: 4,
|
|
53
53
|
expects: [{ type: 'format', value: 'MIME Type with no parameters' }],
|
|
54
54
|
length: 4,
|
|
@@ -61,7 +61,7 @@ test('Location of the token', () => {
|
|
|
61
61
|
ref: 'https://html.spec.whatwg.org/multipage/input.html#attr-input-accept',
|
|
62
62
|
});
|
|
63
63
|
expect((0, list_1.checkList)('x/y,x/y;a=b', type)).toStrictEqual({
|
|
64
|
-
|
|
64
|
+
candidate: 'x/y',
|
|
65
65
|
column: 8,
|
|
66
66
|
expects: [{ type: 'format', value: 'MIME Type with no parameters' }],
|
|
67
67
|
length: 4,
|
|
@@ -74,7 +74,7 @@ test('Location of the token', () => {
|
|
|
74
74
|
ref: 'https://html.spec.whatwg.org/multipage/input.html#attr-input-accept',
|
|
75
75
|
});
|
|
76
76
|
expect((0, list_1.checkList)('x/y\n,\nx/y;a=b', type)).toStrictEqual({
|
|
77
|
-
|
|
77
|
+
candidate: 'x/y',
|
|
78
78
|
column: 4,
|
|
79
79
|
expects: [{ type: 'format', value: 'MIME Type with no parameters' }],
|
|
80
80
|
length: 4,
|
|
@@ -116,7 +116,7 @@ test('Missing comma', () => {
|
|
|
116
116
|
const type = { token: 'Accept', separator: 'comma' };
|
|
117
117
|
expect((0, list_1.checkList)('a/b,x/y a/z', type)).toStrictEqual({
|
|
118
118
|
column: 9,
|
|
119
|
-
|
|
119
|
+
candidate: ',a/z',
|
|
120
120
|
expects: undefined,
|
|
121
121
|
length: 3,
|
|
122
122
|
line: 1,
|
package/lib/number.js
CHANGED
|
@@ -17,22 +17,22 @@ function checkNumber(value, type, ref) {
|
|
|
17
17
|
const isInt = type.type === 'integer';
|
|
18
18
|
if (type.gt != null && n <= type.gt) {
|
|
19
19
|
return (0, match_result_1.unmatched)(value, 'out-of-range', {
|
|
20
|
-
|
|
20
|
+
candidate: clampable && isInt ? `${type.gt + 1}` : undefined,
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
if (type.gte != null && n < type.gte) {
|
|
24
24
|
return (0, match_result_1.unmatched)(value, 'out-of-range', {
|
|
25
|
-
|
|
25
|
+
candidate: clampable ? `${type.gte}` : undefined,
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
if (type.lt != null && type.lt <= n) {
|
|
29
29
|
return (0, match_result_1.unmatched)(value, 'out-of-range', {
|
|
30
|
-
|
|
30
|
+
candidate: clampable && isInt ? `${type.lt - 1}` : undefined,
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
if (type.lte != null && type.lte < n) {
|
|
34
34
|
return (0, match_result_1.unmatched)(value, 'out-of-range', {
|
|
35
|
-
|
|
35
|
+
candidate: clampable ? `${type.lte}` : undefined,
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
}
|
package/lib/primitive/is-uint.js
CHANGED
|
@@ -6,12 +6,12 @@ exports.isUint = void 0;
|
|
|
6
6
|
*
|
|
7
7
|
* @param value
|
|
8
8
|
*/
|
|
9
|
-
function isUint(value,
|
|
9
|
+
function isUint(value, options) {
|
|
10
10
|
const matched = /^[0-9]+$/.test(value);
|
|
11
|
-
if (matched &&
|
|
11
|
+
if (matched && options) {
|
|
12
12
|
const n = parseInt(value, 10);
|
|
13
|
-
if (
|
|
14
|
-
return isFinite(n) &&
|
|
13
|
+
if (options.gt != null) {
|
|
14
|
+
return isFinite(n) && options.gt < n;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
return matched;
|
|
@@ -2,61 +2,61 @@ import type { UnmatchedResult } from '..';
|
|
|
2
2
|
import type { Expect, Result, List } from '../types';
|
|
3
3
|
import { Token } from './token';
|
|
4
4
|
declare type TokenCollectionOptions = Partial<Omit<List, 'token'> & {
|
|
5
|
-
|
|
5
|
+
specificSeparator: string | string[];
|
|
6
6
|
}>;
|
|
7
7
|
export declare type TokenEachCheck = (head: Token | null, tail: TokenCollection) => Result | void;
|
|
8
8
|
export declare class TokenCollection extends Array<Token> {
|
|
9
|
-
|
|
10
|
-
static fromPatterns(value: Token | string, patterns: RegExp[], typeOptions?: Omit<TokenCollectionOptions, 'speificSeparator'> & {
|
|
9
|
+
static fromPatterns(value: Token | string, patterns: RegExp[], typeOptions?: Omit<TokenCollectionOptions, 'specificSeparator'> & {
|
|
11
10
|
repeat?: boolean;
|
|
12
11
|
}): TokenCollection;
|
|
13
12
|
static get [Symbol.species](): ArrayConstructor;
|
|
14
|
-
readonly disallowToSurroundBySpaces: NonNullable<List['disallowToSurroundBySpaces']>;
|
|
15
13
|
readonly allowEmpty: NonNullable<List['allowEmpty']>;
|
|
16
|
-
readonly ordered: NonNullable<List['ordered']>;
|
|
17
|
-
readonly unique: NonNullable<List['unique']>;
|
|
18
14
|
readonly caseInsensitive: NonNullable<List['caseInsensitive']>;
|
|
15
|
+
readonly disallowToSurroundBySpaces: NonNullable<List['disallowToSurroundBySpaces']>;
|
|
19
16
|
readonly number: List['number'];
|
|
17
|
+
readonly ordered: NonNullable<List['ordered']>;
|
|
20
18
|
readonly separator: NonNullable<List['separator']>;
|
|
19
|
+
readonly unique: NonNullable<List['unique']>;
|
|
21
20
|
constructor(value?: string, typeOptions?: TokenCollectionOptions);
|
|
22
21
|
constructor(value?: number);
|
|
23
22
|
get value(): string;
|
|
23
|
+
check(options?: {
|
|
24
|
+
expects?: Expect[];
|
|
25
|
+
ref?: string;
|
|
26
|
+
cache?: boolean;
|
|
27
|
+
}): import("..").MatchedResult | UnmatchedResult;
|
|
28
|
+
chunk(split: number): TokenCollection[];
|
|
29
|
+
compareTokens(callback: (prev: Token, current: Token) => Token | null | void): Token | null | undefined;
|
|
30
|
+
divide(position: number): readonly [TokenCollection, TokenCollection];
|
|
31
|
+
eachCheck(...callbacks: TokenEachCheck[]): Result;
|
|
24
32
|
filter(callback: (value: Token, index: number, array: Token[]) => boolean): TokenCollection;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
tail: TokenCollection;
|
|
28
|
-
};
|
|
33
|
+
getConsecutiveToken(tokenType: number): Token | null;
|
|
34
|
+
getDuplicated(): Token | null;
|
|
29
35
|
getIdentTokens(): TokenCollection;
|
|
30
|
-
compareTokens(callback: (prev: Token, current: Token) => Token | null | void): Token | null | undefined;
|
|
31
36
|
/**
|
|
32
37
|
*
|
|
33
38
|
* @param value The token value or the token type or its list
|
|
34
39
|
*/
|
|
35
40
|
has(value: string | RegExp | number | (string | RegExp | number)[]): boolean;
|
|
41
|
+
headAndTail(): {
|
|
42
|
+
head: Token | null;
|
|
43
|
+
tail: TokenCollection;
|
|
44
|
+
};
|
|
36
45
|
/**
|
|
37
46
|
*
|
|
38
47
|
* @param value The token value or the token type or its list
|
|
39
48
|
*/
|
|
40
49
|
search(value: string | RegExp | number | (string | RegExp | number)[]): Token | null;
|
|
41
|
-
check(options?: {
|
|
42
|
-
expects?: Expect[];
|
|
43
|
-
ref?: string;
|
|
44
|
-
cache?: boolean;
|
|
45
|
-
}): import("..").MatchedResult | UnmatchedResult;
|
|
46
|
-
getConsecutiveToken(tokenType: number): Token | null;
|
|
47
50
|
takeTurns(tokenNumbers: ReadonlyArray<number>, lastTokenNumber?: number): {
|
|
48
51
|
unexpectedLastToken: boolean;
|
|
49
52
|
expectedTokenNumber: number;
|
|
50
53
|
token: Token;
|
|
51
54
|
} | null;
|
|
52
|
-
eachCheck(...callbacks: TokenEachCheck[]): Result;
|
|
53
|
-
getDuplicated(): Token | null;
|
|
54
|
-
divide(position: number): readonly [TokenCollection, TokenCollection];
|
|
55
|
-
chunk(split: number): TokenCollection[];
|
|
56
55
|
toJSON(): {
|
|
57
56
|
type: number;
|
|
58
57
|
value: string;
|
|
59
58
|
offset: number;
|
|
60
59
|
}[];
|
|
60
|
+
private static _new;
|
|
61
61
|
}
|
|
62
62
|
export {};
|
|
@@ -24,12 +24,12 @@ class TokenCollection extends Array {
|
|
|
24
24
|
if (this.separator === 'comma') {
|
|
25
25
|
separators.push(',');
|
|
26
26
|
}
|
|
27
|
-
if (typeOptions === null || typeOptions === void 0 ? void 0 : typeOptions.
|
|
28
|
-
if (Array.isArray(typeOptions.
|
|
29
|
-
separators.push(...typeOptions.
|
|
27
|
+
if (typeOptions === null || typeOptions === void 0 ? void 0 : typeOptions.specificSeparator) {
|
|
28
|
+
if (Array.isArray(typeOptions.specificSeparator)) {
|
|
29
|
+
separators.push(...typeOptions.specificSeparator);
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
separators.push(typeOptions.
|
|
32
|
+
separators.push(typeOptions.specificSeparator);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
const chars = value.split('');
|
|
@@ -60,11 +60,6 @@ class TokenCollection extends Array {
|
|
|
60
60
|
offset += v.length;
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
-
static _new(tokens, old) {
|
|
64
|
-
const newCollection = new TokenCollection('', old);
|
|
65
|
-
newCollection.push(...tokens);
|
|
66
|
-
return newCollection;
|
|
67
|
-
}
|
|
68
63
|
static fromPatterns(value, patterns, typeOptions) {
|
|
69
64
|
const origin = typeof value === 'string' ? value : value.origin;
|
|
70
65
|
let strings = typeof value === 'string' ? value : value.value;
|
|
@@ -77,14 +72,14 @@ class TokenCollection extends Array {
|
|
|
77
72
|
cumulativeOffset += tokenValue.length;
|
|
78
73
|
return token;
|
|
79
74
|
}
|
|
80
|
-
let
|
|
75
|
+
let isBroken = false;
|
|
81
76
|
do {
|
|
82
|
-
|
|
77
|
+
isBroken = false;
|
|
83
78
|
for (const pattern of patterns) {
|
|
84
79
|
const res = pattern.exec(strings);
|
|
85
80
|
let value;
|
|
86
81
|
if (!res) {
|
|
87
|
-
|
|
82
|
+
isBroken = true;
|
|
88
83
|
value = '';
|
|
89
84
|
}
|
|
90
85
|
else {
|
|
@@ -99,7 +94,7 @@ class TokenCollection extends Array {
|
|
|
99
94
|
// @ts-ignore
|
|
100
95
|
token._ = pattern;
|
|
101
96
|
}
|
|
102
|
-
if (
|
|
97
|
+
if (isBroken) {
|
|
103
98
|
addToken(strings);
|
|
104
99
|
}
|
|
105
100
|
} while ((typeOptions === null || typeOptions === void 0 ? void 0 : typeOptions.repeat) && strings);
|
|
@@ -115,56 +110,6 @@ class TokenCollection extends Array {
|
|
|
115
110
|
const value = this.map(t => t.value).join('');
|
|
116
111
|
return value;
|
|
117
112
|
}
|
|
118
|
-
filter(callback) {
|
|
119
|
-
return TokenCollection._new(super.filter(callback), this);
|
|
120
|
-
}
|
|
121
|
-
headAndTail() {
|
|
122
|
-
const copy = this.slice();
|
|
123
|
-
const head = copy.shift();
|
|
124
|
-
if (!head) {
|
|
125
|
-
return { head: head || null, tail: TokenCollection._new([], this) };
|
|
126
|
-
}
|
|
127
|
-
const tail = TokenCollection._new(copy, this);
|
|
128
|
-
return { head, tail };
|
|
129
|
-
}
|
|
130
|
-
getIdentTokens() {
|
|
131
|
-
return this.filter(token => token.type === token_1.Token.Ident);
|
|
132
|
-
}
|
|
133
|
-
compareTokens(callback) {
|
|
134
|
-
const _tokens = this.slice();
|
|
135
|
-
let prev = _tokens.shift();
|
|
136
|
-
while (prev) {
|
|
137
|
-
const current = _tokens.shift();
|
|
138
|
-
if (!current) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const result = callback(prev, current);
|
|
142
|
-
if (result) {
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
prev = current;
|
|
146
|
-
}
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
*
|
|
151
|
-
* @param value The token value or the token type or its list
|
|
152
|
-
*/
|
|
153
|
-
has(value) {
|
|
154
|
-
return this.some(t => t.match(value));
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
*
|
|
158
|
-
* @param value The token value or the token type or its list
|
|
159
|
-
*/
|
|
160
|
-
search(value) {
|
|
161
|
-
for (const token of this) {
|
|
162
|
-
if (token.includes(value)) {
|
|
163
|
-
return token;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
113
|
check(options = {}) {
|
|
169
114
|
var _c;
|
|
170
115
|
const { expects, ref } = options;
|
|
@@ -217,7 +162,7 @@ class TokenCollection extends Array {
|
|
|
217
162
|
reason: 'missing-comma',
|
|
218
163
|
ref,
|
|
219
164
|
expects,
|
|
220
|
-
|
|
165
|
+
candidate: `,${takeTurnsError.token.value}`,
|
|
221
166
|
});
|
|
222
167
|
}
|
|
223
168
|
}
|
|
@@ -242,36 +187,39 @@ class TokenCollection extends Array {
|
|
|
242
187
|
}
|
|
243
188
|
return (0, match_result_1.matched)();
|
|
244
189
|
}
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
if (prev.type === tokenType && current.type === tokenType) {
|
|
248
|
-
return current;
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
return resultToken || null;
|
|
252
|
-
}
|
|
253
|
-
takeTurns(tokenNumbers, lastTokenNumber) {
|
|
190
|
+
chunk(split) {
|
|
191
|
+
const chunks = [];
|
|
254
192
|
const tokens = this.slice();
|
|
255
|
-
|
|
256
|
-
const
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
193
|
+
while (tokens.length) {
|
|
194
|
+
const chunkTokens = tokens.splice(0, split);
|
|
195
|
+
const chunk = TokenCollection._new(chunkTokens, this);
|
|
196
|
+
chunks.push(chunk);
|
|
197
|
+
}
|
|
198
|
+
return chunks;
|
|
199
|
+
}
|
|
200
|
+
compareTokens(callback) {
|
|
201
|
+
const _tokens = this.slice();
|
|
202
|
+
let prev = _tokens.shift();
|
|
203
|
+
while (prev) {
|
|
204
|
+
const current = _tokens.shift();
|
|
205
|
+
if (!current) {
|
|
206
|
+
return;
|
|
264
207
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
expectedTokenNumber,
|
|
269
|
-
token,
|
|
270
|
-
};
|
|
208
|
+
const result = callback(prev, current);
|
|
209
|
+
if (result) {
|
|
210
|
+
return result;
|
|
271
211
|
}
|
|
212
|
+
prev = current;
|
|
272
213
|
}
|
|
273
214
|
return null;
|
|
274
215
|
}
|
|
216
|
+
divide(position) {
|
|
217
|
+
const _a = this.slice(0, position);
|
|
218
|
+
const _b = this.slice(position);
|
|
219
|
+
const a = TokenCollection._new(_a, this);
|
|
220
|
+
const b = TokenCollection._new(_b, this);
|
|
221
|
+
return [a, b];
|
|
222
|
+
}
|
|
275
223
|
eachCheck(...callbacks) {
|
|
276
224
|
let headAndTail = this.headAndTail();
|
|
277
225
|
let head = headAndTail.head;
|
|
@@ -338,6 +286,17 @@ class TokenCollection extends Array {
|
|
|
338
286
|
}
|
|
339
287
|
return (0, match_result_1.matched)();
|
|
340
288
|
}
|
|
289
|
+
filter(callback) {
|
|
290
|
+
return TokenCollection._new(super.filter(callback), this);
|
|
291
|
+
}
|
|
292
|
+
getConsecutiveToken(tokenType) {
|
|
293
|
+
const resultToken = this.compareTokens((prev, current) => {
|
|
294
|
+
if (prev.type === tokenType && current.type === tokenType) {
|
|
295
|
+
return current;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
return resultToken || null;
|
|
299
|
+
}
|
|
341
300
|
getDuplicated() {
|
|
342
301
|
const aList = this.slice();
|
|
343
302
|
const bList = this.slice();
|
|
@@ -359,25 +318,66 @@ class TokenCollection extends Array {
|
|
|
359
318
|
}
|
|
360
319
|
return null;
|
|
361
320
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const _b = this.slice(position);
|
|
365
|
-
const a = TokenCollection._new(_a, this);
|
|
366
|
-
const b = TokenCollection._new(_b, this);
|
|
367
|
-
return [a, b];
|
|
321
|
+
getIdentTokens() {
|
|
322
|
+
return this.filter(token => token.type === token_1.Token.Ident);
|
|
368
323
|
}
|
|
369
|
-
|
|
370
|
-
|
|
324
|
+
/**
|
|
325
|
+
*
|
|
326
|
+
* @param value The token value or the token type or its list
|
|
327
|
+
*/
|
|
328
|
+
has(value) {
|
|
329
|
+
return this.some(t => t.match(value));
|
|
330
|
+
}
|
|
331
|
+
headAndTail() {
|
|
332
|
+
const copy = this.slice();
|
|
333
|
+
const head = copy.shift();
|
|
334
|
+
if (!head) {
|
|
335
|
+
return { head: head || null, tail: TokenCollection._new([], this) };
|
|
336
|
+
}
|
|
337
|
+
const tail = TokenCollection._new(copy, this);
|
|
338
|
+
return { head, tail };
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
*
|
|
342
|
+
* @param value The token value or the token type or its list
|
|
343
|
+
*/
|
|
344
|
+
search(value) {
|
|
345
|
+
for (const token of this) {
|
|
346
|
+
if (token.includes(value)) {
|
|
347
|
+
return token;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
takeTurns(tokenNumbers, lastTokenNumber) {
|
|
371
353
|
const tokens = this.slice();
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
|
|
354
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
355
|
+
const token = tokens[i];
|
|
356
|
+
const expectedTokenNumber = tokenNumbers[i % tokenNumbers.length];
|
|
357
|
+
if (token.type !== expectedTokenNumber) {
|
|
358
|
+
return {
|
|
359
|
+
unexpectedLastToken: false,
|
|
360
|
+
expectedTokenNumber,
|
|
361
|
+
token,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
if (lastTokenNumber != null && i === tokens.length - 1 && token.type !== lastTokenNumber) {
|
|
365
|
+
return {
|
|
366
|
+
unexpectedLastToken: true,
|
|
367
|
+
expectedTokenNumber,
|
|
368
|
+
token,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
376
371
|
}
|
|
377
|
-
return
|
|
372
|
+
return null;
|
|
378
373
|
}
|
|
379
374
|
toJSON() {
|
|
380
375
|
return this.map(t => t.toJSON());
|
|
381
376
|
}
|
|
377
|
+
static _new(tokens, old) {
|
|
378
|
+
const newCollection = new TokenCollection('', old);
|
|
379
|
+
newCollection.push(...tokens);
|
|
380
|
+
return newCollection;
|
|
381
|
+
}
|
|
382
382
|
}
|
|
383
383
|
exports.TokenCollection = TokenCollection;
|
|
@@ -41,7 +41,7 @@ test('parse', () => {
|
|
|
41
41
|
},
|
|
42
42
|
]);
|
|
43
43
|
});
|
|
44
|
-
test('parse
|
|
44
|
+
test('parse comma separator', () => {
|
|
45
45
|
expect(new token_collection_1.TokenCollection('a,, ,b,cde', { separator: 'comma' }).toJSON()).toStrictEqual([
|
|
46
46
|
{
|
|
47
47
|
offset: 0,
|
|
@@ -85,7 +85,7 @@ test('parse camma separator', () => {
|
|
|
85
85
|
},
|
|
86
86
|
]);
|
|
87
87
|
});
|
|
88
|
-
test('A
|
|
88
|
+
test('A comma is an ident if the comma is not a separator', () => {
|
|
89
89
|
expect(new token_collection_1.TokenCollection('a ,cde , f').toJSON()).toStrictEqual([
|
|
90
90
|
{
|
|
91
91
|
offset: 0,
|
package/lib/token/token.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import type { UnmatchedResult, UnmatchedResultOptions, UnmatchedResultReason } from '../types';
|
|
2
2
|
export declare class Token {
|
|
3
3
|
#private;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
static
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
column: number;
|
|
11
|
-
};
|
|
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;
|
|
12
10
|
/**
|
|
13
11
|
* ASCII whitespace is
|
|
14
12
|
* - U+0009 TAB
|
|
@@ -20,36 +18,38 @@ export declare class Token {
|
|
|
20
18
|
* @see https://infra.spec.whatwg.org/#ascii-whitespace
|
|
21
19
|
*/
|
|
22
20
|
static readonly whitespace: ReadonlyArray<string>;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
static
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
static getCol(value: string, offset: number): number;
|
|
22
|
+
static getLine(value: string, offset: number): number;
|
|
23
|
+
static getType(value: string, separators?: string[]): 1 | 13 | 18;
|
|
24
|
+
static shiftLocation(token: Token, offset: number): {
|
|
25
|
+
offset: number;
|
|
26
|
+
line: number;
|
|
27
|
+
column: number;
|
|
28
|
+
};
|
|
29
|
+
readonly offset: number;
|
|
29
30
|
readonly type: number;
|
|
30
31
|
readonly value: string;
|
|
31
|
-
readonly offset: number;
|
|
32
32
|
constructor(value: string, offset: number, originalValue: string, separators?: string[]);
|
|
33
33
|
get length(): number;
|
|
34
34
|
get origin(): string;
|
|
35
|
-
unmatched(options?: UnmatchedResultOptions & {
|
|
36
|
-
ref?: string;
|
|
37
|
-
reason?: UnmatchedResultReason;
|
|
38
|
-
}): UnmatchedResult;
|
|
39
35
|
/**
|
|
40
36
|
*
|
|
41
37
|
* @param value The token value or the token type or its list
|
|
42
38
|
*/
|
|
43
|
-
|
|
39
|
+
includes(value: string | RegExp | number | (string | RegExp | number)[], caseInsensitive?: boolean): boolean;
|
|
44
40
|
/**
|
|
45
41
|
*
|
|
46
42
|
* @param value The token value or the token type or its list
|
|
47
43
|
*/
|
|
48
|
-
|
|
49
|
-
toNumber(): number;
|
|
44
|
+
match(value: string | RegExp | number | (string | RegExp | number)[], caseInsensitive?: boolean): boolean;
|
|
50
45
|
toJSON(): {
|
|
51
46
|
type: number;
|
|
52
47
|
value: string;
|
|
53
48
|
offset: number;
|
|
54
49
|
};
|
|
50
|
+
toNumber(): number;
|
|
51
|
+
unmatched(options?: UnmatchedResultOptions & {
|
|
52
|
+
ref?: string;
|
|
53
|
+
reason?: UnmatchedResultReason;
|
|
54
|
+
}): UnmatchedResult;
|
|
55
55
|
}
|