@markuplint/types 3.0.0-alpha.2 → 3.0.0-alpha.27

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.
Files changed (72) hide show
  1. package/README.md +12 -8
  2. package/lib/css-syntax.js +6 -6
  3. package/lib/defs.js +1 -0
  4. package/lib/get-candidate.d.ts +1 -1
  5. package/lib/token/token-collection.d.ts +2 -2
  6. package/lib/token/token-collection.js +47 -47
  7. package/lib/token/token.js +7 -7
  8. package/lib/types.d.ts +16 -16
  9. package/lib/types.schema.d.ts +5 -5
  10. package/package.json +7 -5
  11. package/patches/css-tree+2.3.1.patch +23 -0
  12. package/types.schema.json +67 -16
  13. package/gen/specific-schema.json +0 -98
  14. package/gen/types.ts +0 -66
  15. package/src/check-multi-types.ts +0 -35
  16. package/src/check.spec.ts +0 -83
  17. package/src/check.ts +0 -48
  18. package/src/css-syntax.spec.ts +0 -167
  19. package/src/css-syntax.ts +0 -188
  20. package/src/debug.ts +0 -3
  21. package/src/defs.ts +0 -810
  22. package/src/enum.ts +0 -25
  23. package/src/get-candidate.ts +0 -24
  24. package/src/index.ts +0 -3
  25. package/src/keyword-type.ts +0 -64
  26. package/src/list.spec.ts +0 -133
  27. package/src/list.ts +0 -34
  28. package/src/match-result.ts +0 -49
  29. package/src/number.ts +0 -46
  30. package/src/primitive/index.spec.ts +0 -65
  31. package/src/primitive/index.ts +0 -7
  32. package/src/primitive/is-float.ts +0 -8
  33. package/src/primitive/is-int.ts +0 -8
  34. package/src/primitive/is-non-zero-uint.ts +0 -8
  35. package/src/primitive/is-quantity.ts +0 -38
  36. package/src/primitive/is-uint.ts +0 -15
  37. package/src/primitive/range.ts +0 -14
  38. package/src/primitive/split-unit.ts +0 -20
  39. package/src/rfc/is-bcp-47.spec.ts +0 -23
  40. package/src/rfc/is-bcp-47.ts +0 -13
  41. package/src/token/index.ts +0 -2
  42. package/src/token/token-collection.spec.ts +0 -147
  43. package/src/token/token-collection.ts +0 -444
  44. package/src/token/token.ts +0 -144
  45. package/src/types.schema.ts +0 -1062
  46. package/src/types.ts +0 -118
  47. package/src/w3c/check-serialized-permissions-policy.spec.ts +0 -38
  48. package/src/w3c/check-serialized-permissions-policy.ts +0 -303
  49. package/src/whatwg/check-autocomplete.spec.ts +0 -387
  50. package/src/whatwg/check-autocomplete.ts +0 -380
  51. package/src/whatwg/check-datetime/date-string.ts +0 -44
  52. package/src/whatwg/check-datetime/datetime-tokens.ts +0 -600
  53. package/src/whatwg/check-datetime/duration-string.ts +0 -399
  54. package/src/whatwg/check-datetime/global-date-and-time-string.ts +0 -96
  55. package/src/whatwg/check-datetime/index.spec.ts +0 -333
  56. package/src/whatwg/check-datetime/index.ts +0 -36
  57. package/src/whatwg/check-datetime/local-date-and-time-string.ts +0 -163
  58. package/src/whatwg/check-datetime/month-string.ts +0 -31
  59. package/src/whatwg/check-datetime/time-string.ts +0 -49
  60. package/src/whatwg/check-datetime/time-zone-offset-string.ts +0 -93
  61. package/src/whatwg/check-datetime/week-string.ts +0 -41
  62. package/src/whatwg/check-datetime/year-string.ts +0 -26
  63. package/src/whatwg/check-datetime/yearless-date-string.ts +0 -38
  64. package/src/whatwg/check-mime-type.spec.ts +0 -59
  65. package/src/whatwg/check-mime-type.ts +0 -46
  66. package/src/whatwg/is-abs-url.spec.ts +0 -8
  67. package/src/whatwg/is-abs-url.ts +0 -31
  68. package/src/whatwg/is-browser-context-name.ts +0 -16
  69. package/src/whatwg/is-custom-element-name.ts +0 -76
  70. package/src/whatwg/is-itemprop-name.ts +0 -17
  71. package/tsconfig.test.json +0 -3
  72. package/tsconfig.tsbuildinfo +0 -1
package/src/types.ts DELETED
@@ -1,118 +0,0 @@
1
- import type { cssSyntaxMatch } from './css-syntax';
2
-
3
- export type { Type, List, Enum, CssSyntax, KeywordDefinedType, Number } from './types.schema';
4
-
5
- export type Result = UnmatchedResult | MatchedResult;
6
-
7
- export type UnmatchedResult = {
8
- matched: false;
9
- ref: string | null;
10
- raw: string;
11
- length: number;
12
- offset: number;
13
- line: number;
14
- column: number;
15
- reason: UnmatchedResultReason;
16
- passCount?: number;
17
- } & UnmatchedResultOptions;
18
-
19
- export type UnmatchedResultOptions = {
20
- partName?: string;
21
- expects?: Expect[];
22
- extra?: Expect;
23
- candidate?: string;
24
- };
25
-
26
- export type UnmatchedResultReason =
27
- | 'syntax-error'
28
- | 'typo'
29
- | 'missing-token'
30
- | 'missing-comma'
31
- | 'unexpected-token'
32
- | 'unexpected-space'
33
- | 'unexpected-newline'
34
- | 'unexpected-comma'
35
- | 'empty-token'
36
- | 'out-of-range'
37
- | 'doesnt-exist-in-enum'
38
- | 'duplicated'
39
- | 'illegal-combination'
40
- | 'illegal-order'
41
- | 'extra-token'
42
- | 'must-be-percent-encoded'
43
- | 'must-be-serialized'
44
- | {
45
- type: 'out-of-range';
46
- gt?: number;
47
- gte?: number;
48
- lt?: number;
49
- lte?: number;
50
- }
51
- | {
52
- type: 'out-of-range-length-char';
53
- gte: number;
54
- lte?: number;
55
- }
56
- | {
57
- type: 'out-of-range-length-digit';
58
- gte: number;
59
- lte?: number;
60
- };
61
-
62
- export type MatchedResult = {
63
- matched: true;
64
- };
65
-
66
- export type Expect = {
67
- type: 'const' | 'format' | 'syntax' | 'regexp' | 'common';
68
- value: string;
69
- };
70
-
71
- export type FormattedPrimitiveTypeCheck = (value: string) => boolean;
72
-
73
- export type FormattedPrimitiveTypeCreator<O = never> = (options?: O) => FormattedPrimitiveTypeCheck;
74
-
75
- export type Defs = Record<string, CustomCssSyntax | CustomSyntax>;
76
-
77
- export type CustomSyntax = {
78
- ref: string;
79
- expects?: Expect[];
80
- is: CustomSyntaxCheck;
81
- };
82
-
83
- export type CustomSyntaxCheck = (value: string) => Result;
84
- export type CustomSyntaxChecker<O = {}> = (options?: O) => CustomSyntaxCheck;
85
-
86
- export type CustomCssSyntax = {
87
- ref: string;
88
- caseSensitive?: boolean;
89
- expects?: Expect[];
90
- syntax: {
91
- apply: `<${string}>`;
92
- def: Record<string, string | CssSyntaxTokenizer>;
93
- /**
94
- * @deprecated
95
- */
96
- ebnf?: Record<string, string | string[]>;
97
- /**
98
- * @deprecated
99
- */
100
- properties?: Record<string, string>;
101
- };
102
- };
103
-
104
- export type CSSSyntaxToken = {
105
- type: number;
106
- value: string;
107
- index: number;
108
- balance: number;
109
- node?: any;
110
- };
111
-
112
- export type CssSyntaxTokenizer = (
113
- token: CSSSyntaxToken | null,
114
- getNextToken: GetNextToken,
115
- match: typeof cssSyntaxMatch,
116
- ) => number;
117
-
118
- export type GetNextToken = (length: number) => CSSSyntaxToken | null;
@@ -1,38 +0,0 @@
1
- // @ts-nocheck
2
-
3
- import { checkSerializedPermissionsPolicy } from './check-serialized-permissions-policy';
4
-
5
- const check = checkSerializedPermissionsPolicy();
6
-
7
- test('checkSerializedPermissionsPolicy', () => {
8
- expect(check('').reason).toBe('empty-token');
9
- expect(check(' ').reason).toBe('unexpected-token');
10
- // expect(check('a').reason).toBe('missing-token');
11
- expect(check('a').matched).toBe(true); // Current supported
12
- expect(check('a:').reason).toBe('unexpected-token');
13
- // expect(check('a ').reason).toBe('missing-token'); // Current supported
14
- expect(check('a ').matched).toBe(true);
15
- expect(check('a a').reason).toBe('unexpected-token');
16
- expect(check('a *').matched).toBe(true);
17
- expect(check('a *a').reason).toBe('unexpected-token');
18
- expect(check('a none').reason).toBe('missing-token');
19
- expect(check("a 'none'").matched).toBe(true);
20
- expect(check('a https://markuplint.dev').matched).toBe(true);
21
- expect(check('a https://markuplint.dev/path/to').reason).toBe('extra-token');
22
- expect(check('a https://マルチバイト.abc.xyz').reason).toBe('must-be-serialized');
23
- expect(check('a * https://markuplint.dev').matched).toBe(true);
24
- expect(check("a * https://markuplint.dev 'none'").matched).toBe(true);
25
- // expect(check("a * https://markuplint.dev 'none';b").reason).toBe('missing-token');
26
- expect(check("a * https://markuplint.dev 'none';b").matched).toBe(true); // Current supported
27
- // expect(check("a * https://markuplint.dev 'none';b ").reason).toBe('missing-token');
28
- expect(check("a * https://markuplint.dev 'none';b ").matched).toBe(true); // Current supported
29
- expect(check("a * https://markuplint.dev 'none';b *").matched).toBe(true);
30
- expect(check("a * https://markuplint.dev 'none';b *;c 'none'").matched).toBe(true);
31
- expect(check("a * https://markuplint.dev 'none'; b *; c 'none'").matched).toBe(true);
32
- });
33
-
34
- test('YouTube embed', () => {
35
- expect(
36
- check('accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture').matched,
37
- ).toBe(true);
38
- });
@@ -1,303 +0,0 @@
1
- import type { Token } from '../token';
2
- import type { CustomSyntaxChecker } from '../types';
3
-
4
- import { log } from '../debug';
5
- import { matched, unmatched } from '../match-result';
6
- import { TokenCollection } from '../token';
7
-
8
- /**
9
- * @see https://w3c.github.io/webappsec-permissions-policy/#serialized-permissions-policy
10
- *
11
- * > Policy Directives in HTML attributes are represented as their
12
- * > ASCII serialization, with the following ABNF:
13
- * > ```abnf
14
- * > serialized-permissions-policy = serialized-policy-directive *(";" serialized-policy-directive)
15
- * > serialized-policy-directive = feature-identifier RWS allow-list
16
- * > feature-identifier = 1*( ALPHA / DIGIT / "-")
17
- * > allow-list = allow-list-value *(RWS allow-list-value)
18
- * > allow-list-value = serialized-origin / "*" / "'self'" / "'src'" / "'none'"
19
- * > ```
20
- *
21
- * But change below according to current supported:
22
- *
23
- * ```abnf
24
- * serialized-policy-directive = feature-identifier [RWS allow-list]
25
- * ```
26
- *
27
- * `allow-list` is optional.
28
- */
29
- export const checkSerializedPermissionsPolicy: CustomSyntaxChecker = () => value => {
30
- const res = _checkSerializedPermissionsPolicy(value);
31
-
32
- if (!res.matched) {
33
- log('Failed: %O', res);
34
- }
35
-
36
- return res;
37
- };
38
-
39
- function _checkSerializedPermissionsPolicy(value: string) {
40
- /**
41
- * The list of serialized-policy-directive
42
- *
43
- * > ```abnf
44
- * > serialized-policy-directive *(";" serialized-policy-directive)
45
- * > ```
46
- */
47
- const patterns = [
48
- /**
49
- * serialized-policy-directive
50
- */
51
- /[^;]*/,
52
- /**
53
- * separator
54
- */
55
- /;?/,
56
- ];
57
- const tokens = TokenCollection.fromPatterns(value, patterns, { repeat: true });
58
- const serializedPolicyDirectives = tokens.chunk(patterns.length);
59
-
60
- log('Serialized Permissions Policy: %s => %O', value, serializedPolicyDirectives);
61
-
62
- for (const [serializedPolicyDirective] of serializedPolicyDirectives) {
63
- if (!serializedPolicyDirective || !serializedPolicyDirective.value) {
64
- return unmatched('', 'empty-token');
65
- }
66
-
67
- const [aw, featureIdentifier, rws, allowListValue] = TokenCollection.fromPatterns(serializedPolicyDirective, [
68
- /**
69
- * Any whitespace
70
- */
71
- /\s*/,
72
-
73
- /**
74
- * feature-identifier
75
- *
76
- * > ```abnf
77
- * > feature-identifier = 1*( ALPHA / DIGIT / "-")
78
- * > ```
79
- */
80
- /[^\s]*/,
81
-
82
- /**
83
- * RWS (Required whitespace)
84
- *
85
- * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.3
86
- */
87
- /\s*/,
88
-
89
- /**
90
- * allow-list-value
91
- */
92
- /.*/,
93
- ]);
94
-
95
- log('Serialized Policy Directive: %s => %O', serializedPolicyDirective.value, {
96
- aw,
97
- featureIdentifier,
98
- rws,
99
- allowListValue,
100
- });
101
-
102
- /**
103
- * > ```abnf
104
- * > feature-identifier = 1*( ALPHA / DIGIT / "-")
105
- * > ```
106
- */
107
- if (!featureIdentifier || !featureIdentifier.match(/^[a-z0-9-]+$/i)) {
108
- return featureIdentifier.unmatched({
109
- reason: 'unexpected-token',
110
- expects: [{ type: 'common', value: 'feature-identifier' }],
111
- partName: 'feature-identifier',
112
- });
113
- }
114
-
115
- if (!rws || !rws.value) {
116
- // return unmatched('', 'missing-token', {
117
- // expects: [{ type: 'common', value: 'whitespace' }],
118
- // partName: 'directive',
119
- // });
120
- continue;
121
- }
122
-
123
- if (!allowListValue || !allowListValue.value) {
124
- // return unmatched('', 'missing-token', {
125
- // expects: [{ type: 'common', value: 'allow-list' }],
126
- // partName: 'allow-list',
127
- // });
128
- continue;
129
- }
130
-
131
- const allowListPatterns = [
132
- // Value
133
- /[^\s]*/,
134
- // Separator
135
- /\s*/,
136
- ];
137
- const allowListTokens = TokenCollection.fromPatterns(allowListValue, allowListPatterns, { repeat: true });
138
- const allowList = allowListTokens.chunk(allowListPatterns.length);
139
-
140
- log('Allow List: %s => %O', allowListTokens.value, allowList);
141
-
142
- for (const [allow] of allowList) {
143
- if (!allow || !allow.value) {
144
- return unmatched('', 'missing-token', {
145
- expects: [
146
- { type: 'const', value: '*' },
147
- { type: 'const', value: "'self'" },
148
- { type: 'const', value: "'src'" },
149
- { type: 'const', value: "'none'" },
150
- { type: 'common', value: 'serialized-origin' },
151
- ],
152
- partName: 'allow-list',
153
- });
154
- }
155
-
156
- const origin = checkSerializedOrigin(allow);
157
-
158
- if (origin.matched) {
159
- continue;
160
- }
161
-
162
- if (origin.reason !== 'syntax-error') {
163
- return origin;
164
- }
165
-
166
- if (allow.match(['*', "'self'", "'src'", "'none'"], true)) {
167
- continue;
168
- }
169
-
170
- if (allow.match(['self', 'src', 'none'], true)) {
171
- return allow.unmatched({
172
- reason: 'missing-token',
173
- expects: [{ type: 'common', value: 'single-quote' }],
174
- partName: 'keyword',
175
- });
176
- }
177
-
178
- return allow.unmatched({
179
- reason: 'unexpected-token',
180
- expects: [
181
- { type: 'const', value: '*' },
182
- { type: 'const', value: "'self'" },
183
- { type: 'const', value: "'src'" },
184
- { type: 'const', value: "'none'" },
185
- { type: 'common', value: 'serialized-origin' },
186
- ],
187
- partName: 'allow-list',
188
- });
189
- }
190
- }
191
-
192
- return matched();
193
- }
194
-
195
- /**
196
- * serialized-origin
197
- *
198
- * > serialized-origin is the serialization of an origin.
199
- * > However, the code points U+0027 ('), U+0021 (*), U+002C (,)
200
- * > and U+003B (;) MUST NOT appear in the serialization.
201
- * > If they are required, they must be percent-encoded
202
- * > as "%27", "%2A", "%2C" or "%3B", respectively.
203
- */
204
- function checkSerializedOrigin(token: Token) {
205
- const url = parseUrl(token.value);
206
-
207
- log('Parse URL: "%s" => %O', token.value, url);
208
-
209
- if (!url) {
210
- return token.unmatched({
211
- expects: [{ type: 'common', value: 'serialized-origin' }],
212
- });
213
- }
214
-
215
- if (url.pathname && url.pathname !== '/') {
216
- return token.unmatched({
217
- reason: 'extra-token',
218
- extra: { type: 'common', value: 'pathname' },
219
- partName: 'serialized-origin',
220
- });
221
- }
222
-
223
- if (url.search) {
224
- return token.unmatched({
225
- reason: 'extra-token',
226
- extra: { type: 'common', value: 'query' },
227
- partName: 'serialized-origin',
228
- });
229
- }
230
-
231
- if (url.hash) {
232
- return token.unmatched({
233
- reason: 'extra-token',
234
- extra: { type: 'common', value: 'hash' },
235
- partName: 'serialized-origin',
236
- });
237
- }
238
-
239
- if (url.username) {
240
- return token.unmatched({
241
- reason: 'extra-token',
242
- extra: { type: 'common', value: 'username' },
243
- partName: 'serialized-origin',
244
- });
245
- }
246
-
247
- if (url.password) {
248
- return token.unmatched({
249
- reason: 'extra-token',
250
- extra: { type: 'common', value: 'password' },
251
- partName: 'serialized-origin',
252
- });
253
- }
254
-
255
- if (!token.value.includes(url.host)) {
256
- return token.unmatched({
257
- reason: 'must-be-serialized',
258
- partName: 'serialized-origin',
259
- });
260
- }
261
-
262
- if (token.includes("'")) {
263
- return token.unmatched({
264
- expects: [{ type: 'const', value: '%27' }],
265
- reason: 'must-be-percent-encoded',
266
- partName: 'serialized-origin',
267
- });
268
- }
269
-
270
- if (token.includes('*')) {
271
- return token.unmatched({
272
- expects: [{ type: 'const', value: '%2A' }],
273
- reason: 'must-be-percent-encoded',
274
- partName: 'serialized-origin',
275
- });
276
- }
277
-
278
- if (token.includes(',')) {
279
- return token.unmatched({
280
- expects: [{ type: 'const', value: '%2C' }],
281
- reason: 'must-be-percent-encoded',
282
- partName: 'serialized-origin',
283
- });
284
- }
285
-
286
- if (token.includes(';')) {
287
- return token.unmatched({
288
- expects: [{ type: 'const', value: '%3B' }],
289
- reason: 'must-be-percent-encoded',
290
- partName: 'serialized-origin',
291
- });
292
- }
293
-
294
- return matched();
295
- }
296
-
297
- function parseUrl(value: string) {
298
- try {
299
- return new URL(value);
300
- } catch {
301
- return null;
302
- }
303
- }