@markuplint/types 3.0.0-rc.4 → 3.0.0

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 (73) hide show
  1. package/lib/check-multi-types.d.ts +1 -4
  2. package/lib/get-candidate.d.ts +1 -4
  3. package/lib/match-result.d.ts +8 -21
  4. package/lib/primitive/is-uint.d.ts +3 -6
  5. package/lib/primitive/split-unit.d.ts +2 -2
  6. package/lib/token/token-collection.d.ts +55 -64
  7. package/lib/token/token.d.ts +52 -57
  8. package/lib/types.d.ts +55 -79
  9. package/lib/types.schema.d.ts +31 -1033
  10. package/lib/whatwg/check-datetime/datetime-tokens.d.ts +1 -21
  11. package/lib/whatwg/check-datetime/time-zone-offset-string.d.ts +1 -1
  12. package/lib/whatwg/check-mime-type.d.ts +4 -4
  13. package/package.json +2 -2
  14. package/gen/specific-schema.json +0 -98
  15. package/gen/types.ts +0 -66
  16. package/src/check-multi-types.ts +0 -35
  17. package/src/check.spec.ts +0 -83
  18. package/src/check.ts +0 -48
  19. package/src/css-syntax.spec.ts +0 -167
  20. package/src/css-syntax.ts +0 -188
  21. package/src/debug.ts +0 -3
  22. package/src/defs.ts +0 -811
  23. package/src/enum.ts +0 -25
  24. package/src/get-candidate.ts +0 -24
  25. package/src/index.ts +0 -3
  26. package/src/keyword-type.ts +0 -64
  27. package/src/list.spec.ts +0 -133
  28. package/src/list.ts +0 -34
  29. package/src/match-result.ts +0 -49
  30. package/src/number.ts +0 -46
  31. package/src/primitive/index.spec.ts +0 -65
  32. package/src/primitive/index.ts +0 -7
  33. package/src/primitive/is-float.ts +0 -8
  34. package/src/primitive/is-int.ts +0 -8
  35. package/src/primitive/is-non-zero-uint.ts +0 -8
  36. package/src/primitive/is-quantity.ts +0 -38
  37. package/src/primitive/is-uint.ts +0 -15
  38. package/src/primitive/range.ts +0 -14
  39. package/src/primitive/split-unit.ts +0 -20
  40. package/src/rfc/is-bcp-47.spec.ts +0 -23
  41. package/src/rfc/is-bcp-47.ts +0 -13
  42. package/src/token/index.ts +0 -2
  43. package/src/token/token-collection.spec.ts +0 -147
  44. package/src/token/token-collection.ts +0 -444
  45. package/src/token/token.ts +0 -144
  46. package/src/types.schema.ts +0 -1062
  47. package/src/types.ts +0 -118
  48. package/src/w3c/check-serialized-permissions-policy.spec.ts +0 -38
  49. package/src/w3c/check-serialized-permissions-policy.ts +0 -303
  50. package/src/whatwg/check-autocomplete.spec.ts +0 -387
  51. package/src/whatwg/check-autocomplete.ts +0 -380
  52. package/src/whatwg/check-datetime/date-string.ts +0 -44
  53. package/src/whatwg/check-datetime/datetime-tokens.ts +0 -600
  54. package/src/whatwg/check-datetime/duration-string.ts +0 -399
  55. package/src/whatwg/check-datetime/global-date-and-time-string.ts +0 -96
  56. package/src/whatwg/check-datetime/index.spec.ts +0 -333
  57. package/src/whatwg/check-datetime/index.ts +0 -36
  58. package/src/whatwg/check-datetime/local-date-and-time-string.ts +0 -163
  59. package/src/whatwg/check-datetime/month-string.ts +0 -31
  60. package/src/whatwg/check-datetime/time-string.ts +0 -49
  61. package/src/whatwg/check-datetime/time-zone-offset-string.ts +0 -93
  62. package/src/whatwg/check-datetime/week-string.ts +0 -41
  63. package/src/whatwg/check-datetime/year-string.ts +0 -26
  64. package/src/whatwg/check-datetime/yearless-date-string.ts +0 -38
  65. package/src/whatwg/check-mime-type.spec.ts +0 -59
  66. package/src/whatwg/check-mime-type.ts +0 -46
  67. package/src/whatwg/is-abs-url.spec.ts +0 -8
  68. package/src/whatwg/is-abs-url.ts +0 -31
  69. package/src/whatwg/is-browser-context-name.ts +0 -16
  70. package/src/whatwg/is-custom-element-name.ts +0 -76
  71. package/src/whatwg/is-itemprop-name.ts +0 -17
  72. package/tsconfig.test.json +0 -3
  73. 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
- }