@markuplint/types 4.0.0-alpha.3 → 4.0.0-dev.28
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/lib/css-syntax.js +11 -9
- package/lib/defs.js +3 -3
- package/lib/enum.js +1 -1
- package/lib/get-candidate.js +2 -2
- package/lib/keyword-type.js +3 -3
- package/lib/number.d.ts +2 -2
- package/lib/number.js +2 -2
- package/lib/primitive/is-float.js +1 -1
- package/lib/primitive/is-int.js +1 -1
- package/lib/primitive/is-non-zero-uint.js +1 -1
- package/lib/primitive/is-uint.js +3 -3
- package/lib/primitive/range.js +2 -2
- package/lib/primitive/split-unit.js +1 -1
- package/lib/token/token-collection.js +14 -15
- package/lib/token/token.d.ts +1 -1
- package/lib/token/token.js +7 -6
- package/lib/w3c/check-serialized-permissions-policy.js +5 -5
- package/lib/whatwg/check-autocomplete.js +10 -13
- package/lib/whatwg/check-datetime/date-string.js +3 -3
- package/lib/whatwg/check-datetime/datetime-tokens.js +18 -18
- package/lib/whatwg/check-datetime/duration-string.js +30 -29
- package/lib/whatwg/check-datetime/global-date-and-time-string.js +8 -8
- package/lib/whatwg/check-datetime/local-date-and-time-string.js +17 -16
- package/lib/whatwg/check-datetime/month-string.js +1 -1
- package/lib/whatwg/check-datetime/time-string.js +4 -4
- package/lib/whatwg/check-datetime/time-zone-offset-string.js +6 -6
- package/lib/whatwg/check-datetime/week-string.js +2 -2
- package/lib/whatwg/check-datetime/yearless-date-string.js +2 -2
- package/lib/whatwg/is-abs-url.js +7 -7
- package/package.json +6 -7
package/lib/css-syntax.js
CHANGED
|
@@ -30,7 +30,7 @@ export function cssSyntaxMatch(value, type) {
|
|
|
30
30
|
...tokenizers,
|
|
31
31
|
...type.syntax.def,
|
|
32
32
|
};
|
|
33
|
-
Object.keys(types)
|
|
33
|
+
for (const key of Object.keys(types)) {
|
|
34
34
|
const valueOrChecker = types[key];
|
|
35
35
|
if (typeof valueOrChecker === 'string') {
|
|
36
36
|
typesExtended[key] = valueOrChecker;
|
|
@@ -38,12 +38,14 @@ export function cssSyntaxMatch(value, type) {
|
|
|
38
38
|
else if (valueOrChecker) {
|
|
39
39
|
typesCheckers[key] = valueOrChecker;
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|
|
42
42
|
propsExtended = { ...type.syntax.properties };
|
|
43
43
|
if (type.caseSensitive) {
|
|
44
44
|
caseSensitive = true;
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
for (const key of Object.keys(typesExtended))
|
|
46
|
+
eachMimicCases(key, typesExtended);
|
|
47
|
+
for (const key of Object.keys(propsExtended))
|
|
48
|
+
eachMimicCases(key, propsExtended);
|
|
47
49
|
value = mimicCases(value);
|
|
48
50
|
}
|
|
49
51
|
ref = type.ref;
|
|
@@ -53,11 +55,11 @@ export function cssSyntaxMatch(value, type) {
|
|
|
53
55
|
types: typesExtended,
|
|
54
56
|
properties: propsExtended,
|
|
55
57
|
}).lexer;
|
|
56
|
-
Object.keys(typesCheckers)
|
|
58
|
+
for (const key of Object.keys(typesCheckers)) {
|
|
57
59
|
const checker = typesCheckers[key];
|
|
58
60
|
// @ts-ignore
|
|
59
61
|
lexer.addType_(key, (token, getNextToken) => checker?.(token, getNextToken, cssSyntaxMatch));
|
|
60
|
-
}
|
|
62
|
+
}
|
|
61
63
|
const { isProp, name } = detectName(defName);
|
|
62
64
|
// @ts-ignore
|
|
63
65
|
const matcher = isProp ? lexer.properties[name] : lexer.types[name];
|
|
@@ -116,7 +118,7 @@ export function cssSyntaxMatch(value, type) {
|
|
|
116
118
|
}
|
|
117
119
|
function detectName(def) {
|
|
118
120
|
const isProp = def.search("<'") === 0;
|
|
119
|
-
const name = def.
|
|
121
|
+
const name = def.replaceAll(/^<'?|'?>$/g, '');
|
|
120
122
|
return {
|
|
121
123
|
isProp,
|
|
122
124
|
name,
|
|
@@ -140,8 +142,8 @@ obj) {
|
|
|
140
142
|
obj[key] = mimicCases(value);
|
|
141
143
|
}
|
|
142
144
|
function mimicCases(value) {
|
|
143
|
-
return value.
|
|
145
|
+
return value.replaceAll(/[A-Z]/g, $0 => `${MIMIC_TAG_L}${$0}${MIMIC_TAG_R}`);
|
|
144
146
|
}
|
|
145
147
|
function deMimicCases(value) {
|
|
146
|
-
return value.
|
|
148
|
+
return value.replaceAll(new RegExp(`${MIMIC_TAG_L}([A-Z])${MIMIC_TAG_R}`, 'g'), (_, $1) => $1);
|
|
147
149
|
}
|
package/lib/defs.js
CHANGED
|
@@ -20,7 +20,7 @@ export const types = {
|
|
|
20
20
|
},
|
|
21
21
|
NoEmptyAny: {
|
|
22
22
|
ref: '',
|
|
23
|
-
is: value => (
|
|
23
|
+
is: value => (value.length > 0 ? matched() : unmatched(value, 'empty-token')),
|
|
24
24
|
},
|
|
25
25
|
OneLineAny: {
|
|
26
26
|
ref: '',
|
|
@@ -91,9 +91,9 @@ export const types = {
|
|
|
91
91
|
// NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
|
|
92
92
|
const nameStartChar = /[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}]/u;
|
|
93
93
|
// NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
|
|
94
|
-
const nameCharTail = /-|[
|
|
94
|
+
const nameCharTail = /-|[\d.\u00B7]|[\u0300-\u036F\u203F\u2040]/;
|
|
95
95
|
// Name ::= NameStartChar (NameChar)*
|
|
96
|
-
const name = RegExp(`(?:${nameStartChar.source})(?:${nameCharTail})*`, 'u');
|
|
96
|
+
const name = new RegExp(`(?:${nameStartChar.source})(?:${nameCharTail})*`, 'u');
|
|
97
97
|
return name.test(value) ? matched() : unmatched(value, 'unexpected-token');
|
|
98
98
|
},
|
|
99
99
|
},
|
package/lib/enum.js
CHANGED
|
@@ -5,7 +5,7 @@ export function checkEnum(value, type, ref) {
|
|
|
5
5
|
if (!disallowToSurroundBySpaces) {
|
|
6
6
|
value = value.trim();
|
|
7
7
|
}
|
|
8
|
-
let values = type.enum
|
|
8
|
+
let values = [...type.enum];
|
|
9
9
|
if (caseInsensitive) {
|
|
10
10
|
value = value.toLowerCase();
|
|
11
11
|
values = type.enum.map(v => v.toLowerCase());
|
package/lib/get-candidate.js
CHANGED
|
@@ -6,14 +6,14 @@ export function getCandidate(value, ...candidates) {
|
|
|
6
6
|
const list = candidates.flat(2).filter((s) => !!s);
|
|
7
7
|
let candidate;
|
|
8
8
|
let maxRatio = 0;
|
|
9
|
-
|
|
9
|
+
for (const word of list) {
|
|
10
10
|
const dist = leven(value.trim().toLowerCase(), word.trim().toLowerCase());
|
|
11
11
|
const ratio = 1 - dist / word.length;
|
|
12
12
|
if (0.5 <= ratio && maxRatio < ratio) {
|
|
13
13
|
candidate = word;
|
|
14
14
|
}
|
|
15
15
|
maxRatio = Math.max(ratio, maxRatio);
|
|
16
|
-
}
|
|
16
|
+
}
|
|
17
17
|
if (value === candidate) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
package/lib/keyword-type.js
CHANGED
|
@@ -35,12 +35,12 @@ function _checkKeywordType(value, type) {
|
|
|
35
35
|
try {
|
|
36
36
|
return cssSyntaxMatch(value, type);
|
|
37
37
|
}
|
|
38
|
-
catch (
|
|
39
|
-
if (
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error instanceof Error && error.message === 'MARKUPLINT_TYPE_NO_EXIST') {
|
|
40
40
|
log("Allow all of any value because the type doesn't exist");
|
|
41
41
|
return matched();
|
|
42
42
|
}
|
|
43
|
-
throw
|
|
43
|
+
throw error;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
const matches = isCSSSyntax(def) ? cssSyntaxMatch(value, def) : def.is(value);
|
package/lib/number.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Result } from './types.js';
|
|
2
|
-
import type { Number } from './types.schema.js';
|
|
3
|
-
export declare function checkNumber(value: string, type: Readonly<
|
|
2
|
+
import type { Number as TypeNumber } from './types.schema.js';
|
|
3
|
+
export declare function checkNumber(value: string, type: Readonly<TypeNumber>, ref?: string): Result;
|
package/lib/number.js
CHANGED
|
@@ -6,8 +6,8 @@ export function checkNumber(value, type, ref) {
|
|
|
6
6
|
}
|
|
7
7
|
const syntaxMatched = type.type === 'float' ? isFloat(value) : isInt(value);
|
|
8
8
|
if (syntaxMatched) {
|
|
9
|
-
const n = parseFloat(value);
|
|
10
|
-
if (!isFinite(n)) {
|
|
9
|
+
const n = Number.parseFloat(value);
|
|
10
|
+
if (!Number.isFinite(n)) {
|
|
11
11
|
return unmatched(value, 'unexpected-token');
|
|
12
12
|
}
|
|
13
13
|
const clampable = type.clampable;
|
package/lib/primitive/is-int.js
CHANGED
package/lib/primitive/is-uint.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @param value
|
|
5
5
|
*/
|
|
6
6
|
export function isUint(value, options) {
|
|
7
|
-
const matched =
|
|
7
|
+
const matched = /^\d+$/.test(value);
|
|
8
8
|
if (matched && options) {
|
|
9
|
-
const n = parseInt(value, 10);
|
|
9
|
+
const n = Number.parseInt(value, 10);
|
|
10
10
|
if (options.gt != null) {
|
|
11
|
-
return isFinite(n) && options.gt < n;
|
|
11
|
+
return Number.isFinite(n) && options.gt < n;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
return matched;
|
package/lib/primitive/range.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export function splitUnit(value) {
|
|
7
7
|
value = value.trim().toLowerCase();
|
|
8
|
-
const matched = value.match(/(
|
|
8
|
+
const matched = value.match(/(^-?\.\d+|^-?\d+(?:\.\d+(?:e[+-]\d+)?)?)([a-z]+$)/i);
|
|
9
9
|
if (!matched) {
|
|
10
10
|
return {
|
|
11
11
|
num: value,
|
|
@@ -21,18 +21,18 @@ export class TokenCollection extends Array {
|
|
|
21
21
|
for (const pattern of patterns) {
|
|
22
22
|
const res = pattern.exec(strings);
|
|
23
23
|
let value;
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
if (res.index !== 0) {
|
|
30
|
-
value = strings.slice(res.index + res[0].length);
|
|
24
|
+
if (res) {
|
|
25
|
+
if (res.index === 0) {
|
|
26
|
+
value = res[0] ?? '';
|
|
31
27
|
}
|
|
32
28
|
else {
|
|
33
|
-
value = res[0]
|
|
29
|
+
value = strings.slice(res.index + res[0].length);
|
|
34
30
|
}
|
|
35
31
|
}
|
|
32
|
+
else {
|
|
33
|
+
isBroken = true;
|
|
34
|
+
value = '';
|
|
35
|
+
}
|
|
36
36
|
const token = addToken(value);
|
|
37
37
|
// @ts-ignore
|
|
38
38
|
token._ = pattern;
|
|
@@ -79,7 +79,7 @@ export class TokenCollection extends Array {
|
|
|
79
79
|
separators.push(...typeOptions.specificSeparator);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
const chars = value
|
|
82
|
+
const chars = [...value];
|
|
83
83
|
const values = [];
|
|
84
84
|
let char;
|
|
85
85
|
while ((char = chars.shift())) {
|
|
@@ -97,16 +97,15 @@ export class TokenCollection extends Array {
|
|
|
97
97
|
values.push(last + char);
|
|
98
98
|
}
|
|
99
99
|
else {
|
|
100
|
-
values.push(last);
|
|
101
|
-
values.push(char);
|
|
100
|
+
values.push(last, char);
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
103
|
let offset = 0;
|
|
105
|
-
|
|
104
|
+
for (const v of values) {
|
|
106
105
|
const token = new Token(v, offset, value, separators);
|
|
107
106
|
this.push(token);
|
|
108
107
|
offset += v.length;
|
|
109
|
-
}
|
|
108
|
+
}
|
|
110
109
|
}
|
|
111
110
|
get value() {
|
|
112
111
|
const value = this.map(t => t.value).join('');
|
|
@@ -268,7 +267,7 @@ export class TokenCollection extends Array {
|
|
|
268
267
|
return result;
|
|
269
268
|
}
|
|
270
269
|
else {
|
|
271
|
-
if (head?.value && !head.
|
|
270
|
+
if (head?.value && !head.matches(/^\s*$/)) {
|
|
272
271
|
passCount += 4 * wait;
|
|
273
272
|
}
|
|
274
273
|
}
|
|
@@ -327,7 +326,7 @@ export class TokenCollection extends Array {
|
|
|
327
326
|
* @param value The token value or the token type or its list
|
|
328
327
|
*/
|
|
329
328
|
has(value) {
|
|
330
|
-
return this.some(t => t.
|
|
329
|
+
return this.some(t => t.matches(value));
|
|
331
330
|
}
|
|
332
331
|
headAndTail() {
|
|
333
332
|
const copy = this.slice();
|
package/lib/token/token.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export declare class Token {
|
|
|
42
42
|
*
|
|
43
43
|
* @param value The token value or the token type or its list
|
|
44
44
|
*/
|
|
45
|
-
|
|
45
|
+
matches(value: TokenValue, caseInsensitive?: boolean): boolean;
|
|
46
46
|
toJSON(): {
|
|
47
47
|
type: number;
|
|
48
48
|
value: string;
|
package/lib/token/token.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export class Token {
|
|
2
2
|
static getCol(value, offset) {
|
|
3
3
|
const lines = value.slice(0, offset).split(/\n/g);
|
|
4
|
-
return (lines
|
|
4
|
+
return (lines.at(-1) ?? '').length + 1;
|
|
5
5
|
}
|
|
6
6
|
static getLine(value, offset) {
|
|
7
7
|
return value.slice(0, offset).split(/\n/g).length;
|
|
@@ -12,8 +12,9 @@ export class Token {
|
|
|
12
12
|
}
|
|
13
13
|
if (separators?.includes(value[0] ?? '')) {
|
|
14
14
|
switch (value[0]) {
|
|
15
|
-
case ',':
|
|
15
|
+
case ',': {
|
|
16
16
|
return Token.Comma;
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
return Token.Ident;
|
|
@@ -61,9 +62,9 @@ export class Token {
|
|
|
61
62
|
*
|
|
62
63
|
* @param value The token value or the token type or its list
|
|
63
64
|
*/
|
|
64
|
-
|
|
65
|
+
matches(value, caseInsensitive) {
|
|
65
66
|
if (Array.isArray(value)) {
|
|
66
|
-
return value.some(v => this.
|
|
67
|
+
return value.some(v => this.matches(v));
|
|
67
68
|
}
|
|
68
69
|
if (typeof value === 'string') {
|
|
69
70
|
const a = caseInsensitive ? this.value.toLowerCase() : this.value;
|
|
@@ -84,8 +85,8 @@ export class Token {
|
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
toNumber() {
|
|
87
|
-
const num = parseFloat(this.value);
|
|
88
|
-
return isNaN(num) ? 0 : num;
|
|
88
|
+
const num = Number.parseFloat(this.value);
|
|
89
|
+
return Number.isNaN(num) ? 0 : num;
|
|
89
90
|
}
|
|
90
91
|
unmatched(options) {
|
|
91
92
|
return {
|
|
@@ -66,7 +66,7 @@ function _checkSerializedPermissionsPolicy(value) {
|
|
|
66
66
|
* > feature-identifier = 1*( ALPHA / DIGIT / "-")
|
|
67
67
|
* > ```
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
/\S*/,
|
|
70
70
|
/**
|
|
71
71
|
* RWS (Required whitespace)
|
|
72
72
|
*
|
|
@@ -89,7 +89,7 @@ function _checkSerializedPermissionsPolicy(value) {
|
|
|
89
89
|
* > feature-identifier = 1*( ALPHA / DIGIT / "-")
|
|
90
90
|
* > ```
|
|
91
91
|
*/
|
|
92
|
-
if (!featureIdentifier || !featureIdentifier.
|
|
92
|
+
if (!featureIdentifier || !featureIdentifier.matches(/^[\da-z-]+$/i)) {
|
|
93
93
|
return featureIdentifier.unmatched({
|
|
94
94
|
reason: 'unexpected-token',
|
|
95
95
|
expects: [{ type: 'common', value: 'feature-identifier' }],
|
|
@@ -112,7 +112,7 @@ function _checkSerializedPermissionsPolicy(value) {
|
|
|
112
112
|
}
|
|
113
113
|
const allowListPatterns = [
|
|
114
114
|
// Value
|
|
115
|
-
|
|
115
|
+
/\S*/,
|
|
116
116
|
// Separator
|
|
117
117
|
/\s*/,
|
|
118
118
|
];
|
|
@@ -139,10 +139,10 @@ function _checkSerializedPermissionsPolicy(value) {
|
|
|
139
139
|
if (origin.reason !== 'syntax-error') {
|
|
140
140
|
return origin;
|
|
141
141
|
}
|
|
142
|
-
if (allow.
|
|
142
|
+
if (allow.matches(['*', "'self'", "'src'", "'none'"], true)) {
|
|
143
143
|
continue;
|
|
144
144
|
}
|
|
145
|
-
if (allow.
|
|
145
|
+
if (allow.matches(['self', 'src', 'none'], true)) {
|
|
146
146
|
return allow.unmatched({
|
|
147
147
|
reason: 'missing-token',
|
|
148
148
|
expects: [{ type: 'common', value: 'single-quote' }],
|
|
@@ -128,7 +128,7 @@ export const checkAutoComplete = () => value => {
|
|
|
128
128
|
// > an ordered set of space-separated tokens consisting of
|
|
129
129
|
// > just autofill detail tokens
|
|
130
130
|
// > (i.e. the "on" and "off" keywords are not allowed).
|
|
131
|
-
if (head.
|
|
131
|
+
if (head.matches(['on', 'off'], true)) {
|
|
132
132
|
if (tail[0]) {
|
|
133
133
|
acLog('[Unmatched ("%s")] Unexpected pair with "on" or "off": "%s"', value, tail.value);
|
|
134
134
|
return tail[0].unmatched({
|
|
@@ -147,7 +147,7 @@ export const checkAutoComplete = () => value => {
|
|
|
147
147
|
// > Optionally, a token whose first eight characters are
|
|
148
148
|
// > an ASCII case-insensitive match for the string "section-",
|
|
149
149
|
// > meaning that the field belongs to the named group.
|
|
150
|
-
if (head.
|
|
150
|
+
if (head.matches(namedGroup, true)) {
|
|
151
151
|
hasNamedGroup = true;
|
|
152
152
|
const sectionToken = tail.search(namedGroup);
|
|
153
153
|
if (sectionToken) {
|
|
@@ -170,7 +170,7 @@ export const checkAutoComplete = () => value => {
|
|
|
170
170
|
// > one of the following strings:
|
|
171
171
|
// > - "shipping", meaning the field is part of the shipping address or contact information
|
|
172
172
|
// > - "billing", meaning the field is part of the billing address or contact information
|
|
173
|
-
if (head.
|
|
173
|
+
if (head.matches(partOfAddress, true)) {
|
|
174
174
|
hasPartOfAddress = true;
|
|
175
175
|
const partToken = tail.search(partOfAddress);
|
|
176
176
|
if (partToken) {
|
|
@@ -194,14 +194,14 @@ export const checkAutoComplete = () => value => {
|
|
|
194
194
|
return matched();
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
-
if (head.
|
|
197
|
+
if (head.matches(contactingTokens, true)) {
|
|
198
198
|
hasContactingToken = true;
|
|
199
199
|
const contactableFiledToken = tail[0];
|
|
200
200
|
if (!contactableFiledToken) {
|
|
201
201
|
// Missing autofill field name but it is valid
|
|
202
202
|
return matched();
|
|
203
203
|
}
|
|
204
|
-
if (!contactableFiledToken.
|
|
204
|
+
if (!contactableFiledToken.matches(contactableFieldNames, true)) {
|
|
205
205
|
const candidate = getCandidate(contactableFiledToken.value, contactableFieldNames);
|
|
206
206
|
acLog('[Unmatched ("%s")] Unexpected token: "%s"', value, contactableFiledToken.value);
|
|
207
207
|
return contactableFiledToken.unmatched({
|
|
@@ -215,7 +215,7 @@ export const checkAutoComplete = () => value => {
|
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
if (tail[1]) {
|
|
218
|
-
if (tail[1].
|
|
218
|
+
if (tail[1].matches(webauthnFieldNames)) {
|
|
219
219
|
return matched();
|
|
220
220
|
}
|
|
221
221
|
const candidate = getCandidate(tail[1].value, webauthnFieldNames);
|
|
@@ -238,9 +238,9 @@ export const checkAutoComplete = () => value => {
|
|
|
238
238
|
}
|
|
239
239
|
return matched();
|
|
240
240
|
}
|
|
241
|
-
if (head.
|
|
241
|
+
if (head.matches([...autofillFieldNames, ...contactableFieldNames], true)) {
|
|
242
242
|
if (tail[0]) {
|
|
243
|
-
if (tail[0].
|
|
243
|
+
if (tail[0].matches(webauthnFieldNames)) {
|
|
244
244
|
return matched();
|
|
245
245
|
}
|
|
246
246
|
const candidate = getCandidate(tail[0].value, webauthnFieldNames);
|
|
@@ -263,7 +263,7 @@ export const checkAutoComplete = () => value => {
|
|
|
263
263
|
}
|
|
264
264
|
return matched();
|
|
265
265
|
}
|
|
266
|
-
if (head.
|
|
266
|
+
if (head.matches(webauthnFieldNames)) {
|
|
267
267
|
return matched();
|
|
268
268
|
}
|
|
269
269
|
const expects = [
|
|
@@ -286,10 +286,7 @@ export const checkAutoComplete = () => value => {
|
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
else if (!hasPartOfAddress) {
|
|
289
|
-
expects.unshift(...partOfAddress
|
|
290
|
-
.slice()
|
|
291
|
-
.reverse()
|
|
292
|
-
.map(token => ({
|
|
289
|
+
expects.unshift(...[...partOfAddress].reverse().map(token => ({
|
|
293
290
|
type: 'const',
|
|
294
291
|
value: token,
|
|
295
292
|
})));
|
|
@@ -10,13 +10,13 @@ export const checkDateString = () => function checkDateString(value) {
|
|
|
10
10
|
// YYYY
|
|
11
11
|
/[^-]*/,
|
|
12
12
|
// -
|
|
13
|
-
|
|
13
|
+
/\D?/,
|
|
14
14
|
// MM
|
|
15
15
|
/[^-]*/,
|
|
16
16
|
// -
|
|
17
|
-
|
|
17
|
+
/\D/,
|
|
18
18
|
// DD
|
|
19
|
-
|
|
19
|
+
/.\d*/,
|
|
20
20
|
]);
|
|
21
21
|
log('Date: "%s" => %O', tokens.value, tokens);
|
|
22
22
|
const res = tokens.eachCheck(datetimeTokenCheck.year, datetimeTokenCheck.hyphen, datetimeTokenCheck.month, datetimeTokenCheck.hyphen, datetimeTokenCheck.date, datetimeTokenCheck.extra);
|
|
@@ -21,7 +21,7 @@ export const datetimeTokenCheck = {
|
|
|
21
21
|
partName: 'year',
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
if (!year.
|
|
24
|
+
if (!year.matches(/^\d+$/)) {
|
|
25
25
|
return year.unmatched({
|
|
26
26
|
reason: 'unexpected-token',
|
|
27
27
|
expects: [],
|
|
@@ -56,7 +56,7 @@ export const datetimeTokenCheck = {
|
|
|
56
56
|
partName: 'month',
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
-
if (!month.
|
|
59
|
+
if (!month.matches(/^\d+$/)) {
|
|
60
60
|
return month.unmatched({
|
|
61
61
|
reason: 'unexpected-token',
|
|
62
62
|
expects: [],
|
|
@@ -99,7 +99,7 @@ export const datetimeTokenCheck = {
|
|
|
99
99
|
partName: 'date',
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
|
-
if (!date.
|
|
102
|
+
if (!date.matches(/^\d+$/)) {
|
|
103
103
|
return date.unmatched({
|
|
104
104
|
reason: 'unexpected-token',
|
|
105
105
|
expects: [],
|
|
@@ -140,7 +140,7 @@ export const datetimeTokenCheck = {
|
|
|
140
140
|
partName: 'hour',
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
|
-
if (!hour.
|
|
143
|
+
if (!hour.matches(/^\d+$/)) {
|
|
144
144
|
return hour.unmatched({
|
|
145
145
|
reason: 'unexpected-token',
|
|
146
146
|
expects: [],
|
|
@@ -174,7 +174,7 @@ export const datetimeTokenCheck = {
|
|
|
174
174
|
partName: 'minute',
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
if (!minute.
|
|
177
|
+
if (!minute.matches(/^\d+$/)) {
|
|
178
178
|
return minute.unmatched({
|
|
179
179
|
reason: 'unexpected-token',
|
|
180
180
|
expects: [],
|
|
@@ -208,7 +208,7 @@ export const datetimeTokenCheck = {
|
|
|
208
208
|
partName: 'second',
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
-
if (!second.
|
|
211
|
+
if (!second.matches(/^\d+$/)) {
|
|
212
212
|
return second.unmatched({
|
|
213
213
|
reason: 'unexpected-token',
|
|
214
214
|
expects: [],
|
|
@@ -242,14 +242,14 @@ export const datetimeTokenCheck = {
|
|
|
242
242
|
partName: 'fractional part',
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
-
if (!secondFP.
|
|
245
|
+
if (!secondFP.matches(/^\d+$/)) {
|
|
246
246
|
return secondFP.unmatched({
|
|
247
247
|
reason: 'unexpected-token',
|
|
248
248
|
expects: [],
|
|
249
249
|
partName: 'fractional part',
|
|
250
250
|
});
|
|
251
251
|
}
|
|
252
|
-
if (!(
|
|
252
|
+
if (!(secondFP.length > 0 && secondFP.length <= 3)) {
|
|
253
253
|
return secondFP.unmatched({
|
|
254
254
|
reason: { type: 'out-of-range-length-digit', gte: 1, lte: 3 },
|
|
255
255
|
expects: [],
|
|
@@ -268,7 +268,7 @@ export const datetimeTokenCheck = {
|
|
|
268
268
|
partName: 'week',
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
|
-
if (!week.
|
|
271
|
+
if (!week.matches(/^\d+$/)) {
|
|
272
272
|
return week.unmatched({
|
|
273
273
|
reason: 'unexpected-token',
|
|
274
274
|
expects: [],
|
|
@@ -303,7 +303,7 @@ export const datetimeTokenCheck = {
|
|
|
303
303
|
partName: 'datetime',
|
|
304
304
|
});
|
|
305
305
|
}
|
|
306
|
-
if (!hyphen.
|
|
306
|
+
if (!hyphen.matches('-')) {
|
|
307
307
|
return hyphen.unmatched({
|
|
308
308
|
reason: 'unexpected-token',
|
|
309
309
|
expects: [{ type: 'common', value: 'hyphen' }],
|
|
@@ -322,7 +322,7 @@ export const datetimeTokenCheck = {
|
|
|
322
322
|
partName: 'time',
|
|
323
323
|
});
|
|
324
324
|
}
|
|
325
|
-
if (!colon.
|
|
325
|
+
if (!colon.matches(':')) {
|
|
326
326
|
return colon.unmatched({
|
|
327
327
|
reason: 'unexpected-token',
|
|
328
328
|
expects: [{ type: 'common', value: 'colon' }],
|
|
@@ -339,7 +339,7 @@ export const datetimeTokenCheck = {
|
|
|
339
339
|
if (!colon || !colon.value) {
|
|
340
340
|
return matched();
|
|
341
341
|
}
|
|
342
|
-
if (!colon.
|
|
342
|
+
if (!colon.matches(':')) {
|
|
343
343
|
return colon.unmatched({
|
|
344
344
|
reason: 'unexpected-token',
|
|
345
345
|
expects: [{ type: 'common', value: 'colon' }],
|
|
@@ -356,7 +356,7 @@ export const datetimeTokenCheck = {
|
|
|
356
356
|
if (!dot || !dot.value) {
|
|
357
357
|
return matched();
|
|
358
358
|
}
|
|
359
|
-
if (!dot.
|
|
359
|
+
if (!dot.matches('.')) {
|
|
360
360
|
return dot.unmatched({
|
|
361
361
|
reason: 'unexpected-token',
|
|
362
362
|
expects: [{ type: 'common', value: 'decimal point' }],
|
|
@@ -377,7 +377,7 @@ export const datetimeTokenCheck = {
|
|
|
377
377
|
],
|
|
378
378
|
});
|
|
379
379
|
}
|
|
380
|
-
if (!sep.
|
|
380
|
+
if (!sep.matches(['T', ' '])) {
|
|
381
381
|
return sep.unmatched({
|
|
382
382
|
reason: 'unexpected-token',
|
|
383
383
|
expects: [
|
|
@@ -397,7 +397,7 @@ export const datetimeTokenCheck = {
|
|
|
397
397
|
expects: [{ type: 'const', value: 'T' }],
|
|
398
398
|
});
|
|
399
399
|
}
|
|
400
|
-
if (!sep.
|
|
400
|
+
if (!sep.matches('T')) {
|
|
401
401
|
return sep.unmatched({
|
|
402
402
|
reason: 'unexpected-token',
|
|
403
403
|
expects: [{ type: 'const', value: 'T' }],
|
|
@@ -420,7 +420,7 @@ export const datetimeTokenCheck = {
|
|
|
420
420
|
partName: 'time-zone',
|
|
421
421
|
});
|
|
422
422
|
}
|
|
423
|
-
if (!colon.
|
|
423
|
+
if (!colon.matches(['+', '-'])) {
|
|
424
424
|
return colon.unmatched({
|
|
425
425
|
reason: 'unexpected-token',
|
|
426
426
|
expects: [
|
|
@@ -442,7 +442,7 @@ export const datetimeTokenCheck = {
|
|
|
442
442
|
partName: 'time-zone',
|
|
443
443
|
});
|
|
444
444
|
}
|
|
445
|
-
if (!weekSign.
|
|
445
|
+
if (!weekSign.matches('W')) {
|
|
446
446
|
return weekSign.unmatched({
|
|
447
447
|
reason: 'unexpected-token',
|
|
448
448
|
expects: [{ type: 'const', value: 'W' }],
|
|
@@ -502,5 +502,5 @@ export function getMaxWeekNum(year) {
|
|
|
502
502
|
}
|
|
503
503
|
date--;
|
|
504
504
|
}
|
|
505
|
-
return NaN;
|
|
505
|
+
return Number.NaN;
|
|
506
506
|
}
|
|
@@ -10,11 +10,11 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
10
10
|
// PnDTnHnMnS
|
|
11
11
|
const tokens = TokenCollection.fromPatterns(value, [
|
|
12
12
|
// Start sign P
|
|
13
|
-
/[
|
|
13
|
+
/[^\dT]?/,
|
|
14
14
|
// date part
|
|
15
15
|
/[^T]*/,
|
|
16
16
|
// Time sign T
|
|
17
|
-
|
|
17
|
+
/\D?/,
|
|
18
18
|
// Time part
|
|
19
19
|
/.*/,
|
|
20
20
|
]);
|
|
@@ -26,7 +26,7 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
26
26
|
partName: 'duration',
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
if (!p.
|
|
29
|
+
if (!p.matches('P', false)) {
|
|
30
30
|
return p.unmatched({
|
|
31
31
|
reason: 'unexpected-token',
|
|
32
32
|
expects: [{ type: 'const', value: 'P' }],
|
|
@@ -37,12 +37,12 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
37
37
|
if (!d || !d.value) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
const [num, sign, extra] = TokenCollection.fromPatterns(d, [
|
|
40
|
+
const [num, sign, extra] = TokenCollection.fromPatterns(d, [/\d+/, /./]);
|
|
41
41
|
if (!num) {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
log('Date part: "%s" => %O', d.value, { num, sign });
|
|
45
|
-
if (!num.
|
|
45
|
+
if (!num.matches(/^\d+$/)) {
|
|
46
46
|
return num.unmatched({
|
|
47
47
|
reason: 'unexpected-token',
|
|
48
48
|
expects: [],
|
|
@@ -55,7 +55,7 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
55
55
|
partName: 'date',
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
-
if (!sign.
|
|
58
|
+
if (!sign.matches('D', false)) {
|
|
59
59
|
return sign.unmatched({
|
|
60
60
|
reason: 'unexpected-token',
|
|
61
61
|
expects: [{ type: 'const', value: 'D' }],
|
|
@@ -74,7 +74,7 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
74
74
|
expects: [{ type: 'const', value: 'T' }],
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
|
-
if (!t.
|
|
77
|
+
if (!t.matches('T', false)) {
|
|
78
78
|
return t.unmatched({
|
|
79
79
|
reason: 'unexpected-token',
|
|
80
80
|
expects: [{ type: 'const', value: 'T' }],
|
|
@@ -93,11 +93,11 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
93
93
|
}
|
|
94
94
|
const timeTokens = TokenCollection.fromPatterns(time, [
|
|
95
95
|
// Hour part
|
|
96
|
-
|
|
96
|
+
/\d+(\.\d*)?\D?/,
|
|
97
97
|
// Minute part
|
|
98
|
-
|
|
98
|
+
/\d+(\.\d*)?\D?/,
|
|
99
99
|
// Second part
|
|
100
|
-
|
|
100
|
+
/\d+(\.\d*)?\D?/,
|
|
101
101
|
]);
|
|
102
102
|
log('Time part: "%s" => %O', timeTokens.value, timeTokens);
|
|
103
103
|
const [h, m, s] = timeTokens;
|
|
@@ -120,12 +120,12 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
120
120
|
reason: 'extra-token',
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
|
-
const [num, dpfp, sign] = TokenCollection.fromPatterns(t, [
|
|
123
|
+
const [num, dpfp, sign] = TokenCollection.fromPatterns(t, [/\d+/, /(\.\d*)?/, /\D+/]);
|
|
124
124
|
if (!num) {
|
|
125
125
|
continue;
|
|
126
126
|
}
|
|
127
127
|
log('Time part (h|m|s): "%s" => %O', t.value, { num, dpfp, sign });
|
|
128
|
-
if (!num.
|
|
128
|
+
if (!num.matches(/^\d+$/)) {
|
|
129
129
|
return num.unmatched({
|
|
130
130
|
reason: 'unexpected-token',
|
|
131
131
|
expects: [{ type: 'common', value: 'number' }],
|
|
@@ -133,12 +133,12 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
135
|
if (dpfp && dpfp.value) {
|
|
136
|
-
const [dp, fp] = TokenCollection.fromPatterns(dpfp, [/\./,
|
|
136
|
+
const [dp, fp] = TokenCollection.fromPatterns(dpfp, [/\./, /\d+/]);
|
|
137
137
|
if (!dp) {
|
|
138
138
|
continue;
|
|
139
139
|
}
|
|
140
140
|
log('Second fractional part (h|m|s): "%s" => %O', dpfp.value, { dp, fp });
|
|
141
|
-
if (!dp.
|
|
141
|
+
if (!dp.matches('.')) {
|
|
142
142
|
return dp.unmatched({
|
|
143
143
|
reason: 'unexpected-token',
|
|
144
144
|
expects: [],
|
|
@@ -151,14 +151,14 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
151
151
|
partName: 'second',
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
|
-
if (!fp.
|
|
154
|
+
if (!fp.matches(/^\d+$/)) {
|
|
155
155
|
return fp.unmatched({
|
|
156
156
|
reason: 'unexpected-token',
|
|
157
157
|
expects: [],
|
|
158
158
|
partName: 'fractional part',
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
|
-
if (!(
|
|
161
|
+
if (!(fp.length > 0 && fp.length <= 3)) {
|
|
162
162
|
return fp.unmatched({
|
|
163
163
|
reason: { type: 'out-of-range-length-digit', gte: 1, lte: 3 },
|
|
164
164
|
expects: [],
|
|
@@ -177,16 +177,16 @@ export const checkDurationISO8601LikeString = () => function checkDurationISO860
|
|
|
177
177
|
partName: 'time',
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
-
if (specified.has('M') && sign.
|
|
180
|
+
if (specified.has('M') && sign.matches('H', false)) {
|
|
181
181
|
return sign.unmatched({
|
|
182
182
|
reason: 'unexpected-token',
|
|
183
183
|
expects: [{ type: 'const', value: 'S' }],
|
|
184
184
|
partName: 'time',
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
-
if (!sign.
|
|
188
|
-
(sign.
|
|
189
|
-
(sign.
|
|
187
|
+
if (!sign.matches(['H', 'M', 'S'], false) ||
|
|
188
|
+
(sign.matches('H', false) && specified.has('H')) ||
|
|
189
|
+
(sign.matches('M', false) && specified.has('M'))) {
|
|
190
190
|
return sign.unmatched({
|
|
191
191
|
reason: 'unexpected-token',
|
|
192
192
|
expects: expects.filter(e => !specified.has(e.value)),
|
|
@@ -214,16 +214,16 @@ export const checkDurationComponentListString = () => function checkDurationComp
|
|
|
214
214
|
// 2. One or more ASCII digits, representing a number of time units,
|
|
215
215
|
// scaled by the duration time component scale specified (see below)
|
|
216
216
|
// to represent a number of seconds.
|
|
217
|
-
|
|
217
|
+
/\d+/,
|
|
218
218
|
// 3. If the duration time component scale specified is 1 (i.e. the units are seconds),
|
|
219
219
|
// then, optionally, a U+002E FULL STOP character (.) followed by
|
|
220
220
|
// one, two, or three ASCII digits, representing a fraction of a second.
|
|
221
|
-
/(
|
|
221
|
+
/(\.\d*)?/,
|
|
222
222
|
// 4. Zero or more ASCII whitespace.
|
|
223
223
|
/\s*/,
|
|
224
224
|
// 5. One of the following characters, representing the duration time component scale
|
|
225
225
|
// of the time unit used in the numeric part of the duration time component:
|
|
226
|
-
|
|
226
|
+
/\D/,
|
|
227
227
|
// 6. Zero or more ASCII whitespace.
|
|
228
228
|
/\s*/,
|
|
229
229
|
];
|
|
@@ -232,7 +232,8 @@ export const checkDurationComponentListString = () => function checkDurationComp
|
|
|
232
232
|
const specified = new Set();
|
|
233
233
|
for (const component of components) {
|
|
234
234
|
log('Duration Component: "%s" => %O', component.value, component);
|
|
235
|
-
const
|
|
235
|
+
const dpfp = component[2];
|
|
236
|
+
const unit = component[4];
|
|
236
237
|
const res = component.eachCheck(ws => { }, num => {
|
|
237
238
|
if (!num || !num.value) {
|
|
238
239
|
const reason = dpfp?.value || unit?.value ? 'unexpected-token' : 'missing-token';
|
|
@@ -258,21 +259,21 @@ export const checkDurationComponentListString = () => function checkDurationComp
|
|
|
258
259
|
partName: 'unit',
|
|
259
260
|
});
|
|
260
261
|
}
|
|
261
|
-
const [, fp] = TokenCollection.fromPatterns(dpfp, [/\./,
|
|
262
|
+
const [, fp] = TokenCollection.fromPatterns(dpfp, [/\./, /\d+/]);
|
|
262
263
|
if (!fp || !fp.value) {
|
|
263
264
|
return unmatched('', 'missing-token', {
|
|
264
265
|
expects: [{ type: 'common', value: 'fractional part' }],
|
|
265
266
|
partName: 'fractional part',
|
|
266
267
|
});
|
|
267
268
|
}
|
|
268
|
-
if (!fp.
|
|
269
|
+
if (!fp.matches(/\d+/)) {
|
|
269
270
|
return fp.unmatched({
|
|
270
271
|
reason: 'unexpected-token',
|
|
271
272
|
expects: [{ type: 'common', value: 'fractional part' }],
|
|
272
273
|
partName: 'fractional part',
|
|
273
274
|
});
|
|
274
275
|
}
|
|
275
|
-
if (!(
|
|
276
|
+
if (!(fp.length > 0 && fp.length <= 3)) {
|
|
276
277
|
return fp.unmatched({
|
|
277
278
|
reason: { type: 'out-of-range-length-digit', gte: 1, lte: 3 },
|
|
278
279
|
expects: [],
|
|
@@ -301,14 +302,14 @@ export const checkDurationComponentListString = () => function checkDurationComp
|
|
|
301
302
|
partName: 'unit',
|
|
302
303
|
});
|
|
303
304
|
}
|
|
304
|
-
if (dpfp && dpfp.value && unit.
|
|
305
|
+
if (dpfp && dpfp.value && unit.matches(['w', 'd', 'h', 'm'])) {
|
|
305
306
|
return unit.unmatched({
|
|
306
307
|
reason: 'unexpected-token',
|
|
307
308
|
expects: [{ type: 'const', value: 's' }],
|
|
308
309
|
partName: 'unit',
|
|
309
310
|
});
|
|
310
311
|
}
|
|
311
|
-
if (!unit.
|
|
312
|
+
if (!unit.matches(['w', 'd', 'h', 'm', 's'])) {
|
|
312
313
|
return unit.unmatched({
|
|
313
314
|
reason: 'unexpected-token',
|
|
314
315
|
expects,
|
|
@@ -12,23 +12,23 @@ export const checkGlobalDateAndTimeString = () => function checkGlobalDateAndTim
|
|
|
12
12
|
// YYYY
|
|
13
13
|
/[^-]*/,
|
|
14
14
|
// -
|
|
15
|
-
|
|
15
|
+
/\D?/,
|
|
16
16
|
// MM
|
|
17
17
|
/[^-]*/,
|
|
18
18
|
// -
|
|
19
|
-
|
|
19
|
+
/\D?/,
|
|
20
20
|
// DD
|
|
21
|
-
/[
|
|
21
|
+
/[^\sT]*/,
|
|
22
22
|
// T \s
|
|
23
|
-
|
|
23
|
+
/\D?/,
|
|
24
24
|
// hh
|
|
25
25
|
/[^:]*/,
|
|
26
26
|
// :
|
|
27
|
-
|
|
27
|
+
/\D?/,
|
|
28
28
|
// mm
|
|
29
|
-
/[
|
|
29
|
+
/[^+:Z-]*/,
|
|
30
30
|
// :ss.sss
|
|
31
|
-
/(:[
|
|
31
|
+
/(:[^+Z-]*)?/,
|
|
32
32
|
// time-zone
|
|
33
33
|
/.*/,
|
|
34
34
|
]);
|
|
@@ -37,7 +37,7 @@ export const checkGlobalDateAndTimeString = () => function checkGlobalDateAndTim
|
|
|
37
37
|
if (!second || !second.value) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
const secondTokens = TokenCollection.fromPatterns(second, [/:?/,
|
|
40
|
+
const secondTokens = TokenCollection.fromPatterns(second, [/:?/, /\d*/, /\.?/, /\d*/]);
|
|
41
41
|
log('Second Part: "%s" => %O', secondTokens.value, secondTokens);
|
|
42
42
|
const res = secondTokens.eachCheck(datetimeTokenCheck.colon, datetimeTokenCheck.second, datetimeTokenCheck.decimalPointOrEnd, datetimeTokenCheck.secondFractionalPart);
|
|
43
43
|
if (!res.matched) {
|
|
@@ -10,29 +10,29 @@ export const checkLocalDateAndTimeString = () => function checkLocalDateAndTimeS
|
|
|
10
10
|
// YYYY
|
|
11
11
|
/[^-]*/,
|
|
12
12
|
// -
|
|
13
|
-
|
|
13
|
+
/\D?/,
|
|
14
14
|
// MM
|
|
15
15
|
/[^-]*/,
|
|
16
16
|
// -
|
|
17
|
-
|
|
17
|
+
/\D?/,
|
|
18
18
|
// DD
|
|
19
|
-
/[
|
|
19
|
+
/[^\sT]*/,
|
|
20
20
|
// T
|
|
21
|
-
|
|
21
|
+
/\D?/,
|
|
22
22
|
// hh
|
|
23
23
|
/[^:]*/,
|
|
24
24
|
// :
|
|
25
|
-
|
|
25
|
+
/\D?/,
|
|
26
26
|
// mm
|
|
27
27
|
/[^:]*/,
|
|
28
28
|
// :
|
|
29
|
-
|
|
29
|
+
/\D?/,
|
|
30
30
|
// ss
|
|
31
31
|
/[^.]*/,
|
|
32
32
|
// .
|
|
33
|
-
|
|
33
|
+
/\D?/,
|
|
34
34
|
// sss
|
|
35
|
-
|
|
35
|
+
/.\d*/,
|
|
36
36
|
]);
|
|
37
37
|
log('Local Date and Time: "%s" => %O', tokens.value, tokens);
|
|
38
38
|
const res = tokens.eachCheck(datetimeTokenCheck.year, datetimeTokenCheck.hyphen, datetimeTokenCheck.month, datetimeTokenCheck.hyphen, datetimeTokenCheck.date, datetimeTokenCheck.localDateTimeSeparator, datetimeTokenCheck.hour, datetimeTokenCheck.colon, datetimeTokenCheck.minute, datetimeTokenCheck.colonOrEnd, datetimeTokenCheck.second, datetimeTokenCheck.decimalPointOrEnd, datetimeTokenCheck.secondFractionalPart, datetimeTokenCheck.extra);
|
|
@@ -50,29 +50,29 @@ export const checkNormalizedLocalDateAndTimeString = () => function checkNormali
|
|
|
50
50
|
// YYYY
|
|
51
51
|
/[^-]*/,
|
|
52
52
|
// -
|
|
53
|
-
|
|
53
|
+
/\D?/,
|
|
54
54
|
// MM
|
|
55
55
|
/[^-]*/,
|
|
56
56
|
// -
|
|
57
|
-
|
|
57
|
+
/\D?/,
|
|
58
58
|
// DD
|
|
59
59
|
/[^T]*/,
|
|
60
60
|
// T
|
|
61
|
-
|
|
61
|
+
/\D?/,
|
|
62
62
|
// hh
|
|
63
63
|
/[^:]*/,
|
|
64
64
|
// :
|
|
65
|
-
|
|
65
|
+
/\D?/,
|
|
66
66
|
// mm
|
|
67
67
|
/[^:]*/,
|
|
68
68
|
// :
|
|
69
|
-
|
|
69
|
+
/\D?/,
|
|
70
70
|
// ss
|
|
71
71
|
/[^.]*/,
|
|
72
72
|
// .
|
|
73
|
-
|
|
73
|
+
/\D?/,
|
|
74
74
|
// sss
|
|
75
|
-
|
|
75
|
+
/.\d*/,
|
|
76
76
|
]);
|
|
77
77
|
log('Normalized Local Date and Time: "%s" => %O', tokens.value, tokens);
|
|
78
78
|
const res = tokens.eachCheck(datetimeTokenCheck.year, datetimeTokenCheck.hyphen, datetimeTokenCheck.month, datetimeTokenCheck.hyphen, datetimeTokenCheck.date, datetimeTokenCheck.normalizedlocalDateTimeSeparator, datetimeTokenCheck.hour, datetimeTokenCheck.colon, datetimeTokenCheck.minute, datetimeTokenCheck.colonOrEnd, datetimeTokenCheck.second, datetimeTokenCheck.decimalPointOrEnd, datetimeTokenCheck.secondFractionalPart, datetimeTokenCheck.extra);
|
|
@@ -86,7 +86,8 @@ export const checkNormalizedLocalDateAndTimeString = () => function checkNormali
|
|
|
86
86
|
* > (e.g. omitting the seconds component entirely
|
|
87
87
|
* > if the given time is zero seconds past the minute)
|
|
88
88
|
*/
|
|
89
|
-
const
|
|
89
|
+
const second = tokens[10];
|
|
90
|
+
const fp = tokens[12];
|
|
90
91
|
if (!second || !fp) {
|
|
91
92
|
log('Failed: %O', res);
|
|
92
93
|
return res;
|
|
@@ -6,7 +6,7 @@ import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export const checkMonthString = () => function checkMonthString(value) {
|
|
8
8
|
log('CHECK: month-string');
|
|
9
|
-
const tokens = TokenCollection.fromPatterns(value, [/[^-]*/,
|
|
9
|
+
const tokens = TokenCollection.fromPatterns(value, [/[^-]*/, /\D?/, /.\d*/]);
|
|
10
10
|
log('Month: "%s" => %O', tokens.value, tokens);
|
|
11
11
|
const res = tokens.eachCheck(datetimeTokenCheck.year, datetimeTokenCheck.hyphen, datetimeTokenCheck.month, datetimeTokenCheck.extra);
|
|
12
12
|
if (!res.matched) {
|
|
@@ -10,17 +10,17 @@ export const checkTimeString = () => function checkTimeString(value) {
|
|
|
10
10
|
// hh
|
|
11
11
|
/[^:]*/,
|
|
12
12
|
// :
|
|
13
|
-
|
|
13
|
+
/\D?/,
|
|
14
14
|
// mm
|
|
15
15
|
/[^:]*/,
|
|
16
16
|
// :
|
|
17
|
-
|
|
17
|
+
/\D?/,
|
|
18
18
|
// ss
|
|
19
19
|
/[^.]*/,
|
|
20
20
|
// .
|
|
21
|
-
|
|
21
|
+
/\D?/,
|
|
22
22
|
// sss
|
|
23
|
-
|
|
23
|
+
/.\d*/,
|
|
24
24
|
]);
|
|
25
25
|
log('Time: "%s" => %O', tokens.value, tokens);
|
|
26
26
|
const res = tokens.eachCheck(datetimeTokenCheck.hour, datetimeTokenCheck.colon, datetimeTokenCheck.minute, datetimeTokenCheck.colonOrEnd, datetimeTokenCheck.second, datetimeTokenCheck.decimalPointOrEnd, datetimeTokenCheck.secondFractionalPart);
|
|
@@ -13,13 +13,13 @@ export function parseTimeZone(zone) {
|
|
|
13
13
|
const value = typeof zone === 'string' ? zone : zone.value;
|
|
14
14
|
const zoneTokens = TokenCollection.fromPatterns(zone, [
|
|
15
15
|
// Z + -
|
|
16
|
-
|
|
16
|
+
/\D?/,
|
|
17
17
|
// hh
|
|
18
18
|
/[^:]{0,2}/,
|
|
19
19
|
// :
|
|
20
|
-
|
|
20
|
+
/\D?/,
|
|
21
21
|
// mm
|
|
22
|
-
|
|
22
|
+
/.\d*/,
|
|
23
23
|
]);
|
|
24
24
|
log('Time-zone Part: "%s" => %O', value, zoneTokens);
|
|
25
25
|
const res = zoneTokens.eachCheck((sign, tail) => {
|
|
@@ -33,7 +33,7 @@ export function parseTimeZone(zone) {
|
|
|
33
33
|
partName: 'time-zone',
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
if (sign.
|
|
36
|
+
if (sign.matches('Z')) {
|
|
37
37
|
if (tail.value) {
|
|
38
38
|
return (tail[0]?.unmatched({
|
|
39
39
|
reason: 'extra-token',
|
|
@@ -41,7 +41,7 @@ export function parseTimeZone(zone) {
|
|
|
41
41
|
}
|
|
42
42
|
return matched();
|
|
43
43
|
}
|
|
44
|
-
if (!sign.
|
|
44
|
+
if (!sign.matches(['+', '-'])) {
|
|
45
45
|
return sign.unmatched({
|
|
46
46
|
reason: 'unexpected-token',
|
|
47
47
|
expects: [
|
|
@@ -55,7 +55,7 @@ export function parseTimeZone(zone) {
|
|
|
55
55
|
if (!colon || !colon.value) {
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
|
-
if (!colon.
|
|
58
|
+
if (!colon.matches(':')) {
|
|
59
59
|
return colon.unmatched({
|
|
60
60
|
reason: 'unexpected-token',
|
|
61
61
|
expects: [{ type: 'const', value: ':' }],
|
|
@@ -12,9 +12,9 @@ export const checkWeekString = () => function checkWeekString(value) {
|
|
|
12
12
|
// -
|
|
13
13
|
/[^W]?/,
|
|
14
14
|
// W
|
|
15
|
-
|
|
15
|
+
/\D?/,
|
|
16
16
|
// ww
|
|
17
|
-
|
|
17
|
+
/.\d*/,
|
|
18
18
|
]);
|
|
19
19
|
log('Week: "%s" => %O', tokens.value, tokens);
|
|
20
20
|
const res = tokens.eachCheck(datetimeTokenCheck.year, datetimeTokenCheck.hyphen, datetimeTokenCheck.weekSign, datetimeTokenCheck.week, datetimeTokenCheck.extra);
|
|
@@ -10,9 +10,9 @@ export const checkYearlessDateString = () => function checkYearlessDateString(va
|
|
|
10
10
|
// MM
|
|
11
11
|
/[^-]*/,
|
|
12
12
|
// -
|
|
13
|
-
|
|
13
|
+
/\D?/,
|
|
14
14
|
// DD
|
|
15
|
-
|
|
15
|
+
/.\d*/,
|
|
16
16
|
]);
|
|
17
17
|
log('Yearless Date: "%s" => %O', tokens.value, tokens);
|
|
18
18
|
const res = tokens.eachCheck(datetimeTokenCheck.month, datetimeTokenCheck.hyphen, datetimeTokenCheck.date, datetimeTokenCheck.extra);
|
package/lib/whatwg/is-abs-url.js
CHANGED
|
@@ -16,14 +16,14 @@ export const isAbsURL = () => {
|
|
|
16
16
|
try {
|
|
17
17
|
new URL(value);
|
|
18
18
|
}
|
|
19
|
-
catch (
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error &&
|
|
21
|
+
typeof error === 'object' &&
|
|
22
|
+
'code' in error && // @ts-ignore
|
|
23
|
+
error.code === 'ERR_INVALID_URL') {
|
|
24
|
+
return false;
|
|
25
25
|
}
|
|
26
|
-
throw
|
|
26
|
+
throw error;
|
|
27
27
|
}
|
|
28
28
|
return true;
|
|
29
29
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/types",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-dev.28+0131de5e",
|
|
4
4
|
"description": "Type declaration and value checker",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -25,16 +25,15 @@
|
|
|
25
25
|
"schema": "ts-node './gen/types.ts'; json2ts './types.schema.json' > './src/types.schema.ts'; prettier './src/types.schema.ts' './types.schema.json' --write; eslint './src/types.schema.ts' --fix; tsc;"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@types/
|
|
29
|
-
"@types/
|
|
30
|
-
"@types/
|
|
31
|
-
"@types/whatwg-mimetype": "3.0.0",
|
|
28
|
+
"@types/css-tree": "^2.3.3",
|
|
29
|
+
"@types/debug": "^4.1.10",
|
|
30
|
+
"@types/whatwg-mimetype": "3.0.1",
|
|
32
31
|
"bcp-47": "^2.1.0",
|
|
33
32
|
"css-tree": "^2.3.1",
|
|
34
33
|
"debug": "^4.3.4",
|
|
35
34
|
"leven": "^4.0.0",
|
|
36
|
-
"type-fest": "^4.
|
|
35
|
+
"type-fest": "^4.5.0",
|
|
37
36
|
"whatwg-mimetype": "^3.0.0"
|
|
38
37
|
},
|
|
39
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "0131de5ea9dd6d3fd5472d7b414b66644c758881"
|
|
40
39
|
}
|