@markuplint/types 5.0.0-rc.2 → 5.0.0-rc.5
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/CHANGELOG.md +38 -0
- package/README.md +83 -75
- package/lib/check-multi-types.d.ts +2 -9
- package/lib/check-multi-types.js +2 -9
- package/lib/css-defs.d.ts +0 -8
- package/lib/css-defs.js +0 -8
- package/lib/css-overrides.d.ts +2 -5
- package/lib/css-overrides.js +2 -5
- package/lib/css-syntax.d.ts +0 -11
- package/lib/css-syntax.js +6 -18
- package/lib/css-tokenizers.d.ts +0 -6
- package/lib/css-tokenizers.js +0 -6
- package/lib/debug.d.ts +0 -3
- package/lib/debug.js +0 -3
- package/lib/defs.d.ts +0 -8
- package/lib/defs.js +308 -37
- package/lib/directive.d.ts +0 -14
- package/lib/directive.js +0 -14
- package/lib/enum.d.ts +0 -11
- package/lib/enum.js +0 -11
- package/lib/keyword-type.d.ts +0 -13
- package/lib/keyword-type.js +0 -13
- package/lib/list.d.ts +0 -13
- package/lib/list.js +0 -13
- package/lib/match-result.d.ts +0 -21
- package/lib/match-result.js +0 -21
- package/lib/number.d.ts +0 -12
- package/lib/number.js +0 -12
- package/lib/primitive/is-float.d.ts +3 -4
- package/lib/primitive/is-float.js +3 -4
- package/lib/primitive/is-int.d.ts +0 -5
- package/lib/primitive/is-int.js +0 -5
- package/lib/primitive/is-non-zero-uint.d.ts +0 -6
- package/lib/primitive/is-non-zero-uint.js +0 -6
- package/lib/primitive/is-quantity.d.ts +0 -8
- package/lib/primitive/is-quantity.js +0 -8
- package/lib/primitive/is-uint.d.ts +0 -6
- package/lib/primitive/is-uint.js +0 -6
- package/lib/primitive/range.d.ts +0 -8
- package/lib/primitive/range.js +0 -8
- package/lib/primitive/split-unit.d.ts +0 -6
- package/lib/primitive/split-unit.js +0 -6
- package/lib/rfc/is-bcp-47.d.ts +24 -1
- package/lib/rfc/is-bcp-47.js +88 -3
- package/lib/token/token-collection.d.ts +1 -111
- package/lib/token/token-collection.js +0 -108
- package/lib/token/token.d.ts +1 -73
- package/lib/token/token.js +0 -72
- package/lib/token/types.d.ts +0 -9
- package/lib/types.schema.d.ts +1 -1
- package/lib/w3c/check-content-security-policy.d.ts +18 -0
- package/lib/w3c/check-content-security-policy.js +363 -0
- package/lib/w3c/check-serialized-permissions-policy.d.ts +0 -2
- package/lib/w3c/check-serialized-permissions-policy.js +0 -2
- package/lib/whatwg/check-autocomplete.d.ts +26 -9
- package/lib/whatwg/check-autocomplete.js +42 -15
- package/lib/whatwg/check-datetime/date-string-with-optional-time.d.ts +11 -0
- package/lib/whatwg/check-datetime/date-string-with-optional-time.js +16 -0
- package/lib/whatwg/check-datetime/date-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/date-string.js +0 -2
- package/lib/whatwg/check-datetime/datetime-tokens.d.ts +0 -13
- package/lib/whatwg/check-datetime/datetime-tokens.js +0 -16
- package/lib/whatwg/check-datetime/duration-string.d.ts +0 -4
- package/lib/whatwg/check-datetime/duration-string.js +0 -4
- package/lib/whatwg/check-datetime/global-date-and-time-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/global-date-and-time-string.js +4 -4
- package/lib/whatwg/check-datetime/index.d.ts +0 -5
- package/lib/whatwg/check-datetime/index.js +0 -5
- package/lib/whatwg/check-datetime/local-date-and-time-string.d.ts +0 -4
- package/lib/whatwg/check-datetime/local-date-and-time-string.js +0 -4
- package/lib/whatwg/check-datetime/month-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/month-string.js +0 -2
- package/lib/whatwg/check-datetime/time-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/time-string.js +0 -2
- package/lib/whatwg/check-datetime/time-zone-offset-string.d.ts +0 -8
- package/lib/whatwg/check-datetime/time-zone-offset-string.js +0 -8
- package/lib/whatwg/check-datetime/week-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/week-string.js +0 -2
- package/lib/whatwg/check-datetime/year-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/year-string.js +0 -2
- package/lib/whatwg/check-datetime/yearless-date-string.d.ts +0 -2
- package/lib/whatwg/check-datetime/yearless-date-string.js +0 -2
- package/lib/whatwg/check-email.js +0 -2
- package/lib/whatwg/check-http-equiv-content-type.d.ts +12 -0
- package/lib/whatwg/check-http-equiv-content-type.js +32 -0
- package/lib/whatwg/check-http-equiv-refresh.d.ts +21 -0
- package/lib/whatwg/check-http-equiv-refresh.js +106 -0
- package/lib/whatwg/check-media-query-list.d.ts +61 -0
- package/lib/whatwg/check-media-query-list.js +484 -0
- package/lib/whatwg/check-mime-type.d.ts +0 -4
- package/lib/whatwg/check-mime-type.js +55 -3
- package/lib/whatwg/check-simple-color.d.ts +2 -4
- package/lib/whatwg/check-simple-color.js +2 -4
- package/lib/whatwg/check-url.d.ts +15 -7
- package/lib/whatwg/check-url.js +333 -25
- package/lib/whatwg/is-abs-url.d.ts +0 -2
- package/lib/whatwg/is-abs-url.js +0 -2
- package/lib/whatwg/is-browser-context-name.d.ts +0 -2
- package/lib/whatwg/is-browser-context-name.js +0 -2
- package/lib/whatwg/is-itemprop-name.d.ts +0 -2
- package/lib/whatwg/is-itemprop-name.js +0 -2
- package/lib/whatwg/is-navigable-target-name.d.ts +0 -2
- package/lib/whatwg/is-navigable-target-name.js +0 -2
- package/package.json +6 -5
- package/types.schema.json +9 -0
- package/ARCHITECTURE.ja.md +0 -256
- package/ARCHITECTURE.md +0 -256
- package/SKILL.md +0 -100
- package/docs/check-pipeline.ja.md +0 -494
- package/docs/check-pipeline.md +0 -494
- package/docs/token-system.ja.md +0 -584
- package/docs/token-system.md +0 -584
- package/docs/type-system.ja.md +0 -623
- package/docs/type-system.md +0 -623
- package/docs/validators.ja.md +0 -536
- package/docs/validators.md +0 -536
|
@@ -4,8 +4,6 @@ import { TokenCollection } from '../../token/index.js';
|
|
|
4
4
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
5
5
|
import { parseTimeZone } from './time-zone-offset-string.js';
|
|
6
6
|
/**
|
|
7
|
-
* Validates a global date and time string (date + time + time-zone offset).
|
|
8
|
-
*
|
|
9
7
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#global-dates-and-times
|
|
10
8
|
*/
|
|
11
9
|
export const checkGlobalDateAndTimeString = () => function checkGlobalDateAndTimeString(value) {
|
|
@@ -29,8 +27,10 @@ export const checkGlobalDateAndTimeString = () => function checkGlobalDateAndTim
|
|
|
29
27
|
/\D?/,
|
|
30
28
|
// mm
|
|
31
29
|
/[^+:Z-]*/,
|
|
32
|
-
// :ss.sss
|
|
33
|
-
|
|
30
|
+
// :ss.sss — restricted to digits and the decimal point so that an
|
|
31
|
+
// invalid fraction separator (e.g. `,`) is left in the timezone
|
|
32
|
+
// segment, where `parseTimeZone` rejects it.
|
|
33
|
+
/(:[\d.]*)?/,
|
|
34
34
|
// time-zone
|
|
35
35
|
/.*/,
|
|
36
36
|
]);
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a datetime string against all WHATWG date and time formats.
|
|
4
|
-
*
|
|
5
|
-
* Tries each format (date, time, month, yearless date, local/global date-time,
|
|
6
|
-
* time-zone offset, week, year, and duration strings) and returns the best match.
|
|
7
|
-
*
|
|
8
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#dates-and-times
|
|
9
4
|
*/
|
|
10
5
|
export declare const checkDateTime: CustomSyntaxChecker;
|
|
@@ -24,11 +24,6 @@ const checks = [
|
|
|
24
24
|
checkDurationComponentListString(),
|
|
25
25
|
];
|
|
26
26
|
/**
|
|
27
|
-
* Validates a datetime string against all WHATWG date and time formats.
|
|
28
|
-
*
|
|
29
|
-
* Tries each format (date, time, month, yearless date, local/global date-time,
|
|
30
|
-
* time-zone offset, week, year, and duration strings) and returns the best match.
|
|
31
|
-
*
|
|
32
27
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#dates-and-times
|
|
33
28
|
*/
|
|
34
29
|
export const checkDateTime = () => value => {
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a local date and time string (date + `T` or space + time, no time-zone).
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkLocalDateAndTimeString: CustomSyntaxChecker;
|
|
8
6
|
/**
|
|
9
|
-
* Validates a normalized local date and time string (uses `T` separator only, omits zero seconds).
|
|
10
|
-
*
|
|
11
7
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
|
|
12
8
|
*/
|
|
13
9
|
export declare const checkNormalizedLocalDateAndTimeString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a local date and time string (date + `T` or space + time, no time-zone).
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
|
|
8
6
|
*/
|
|
9
7
|
export const checkLocalDateAndTimeString = () => function checkLocalDateAndTimeString(value) {
|
|
@@ -44,8 +42,6 @@ export const checkLocalDateAndTimeString = () => function checkLocalDateAndTimeS
|
|
|
44
42
|
return res;
|
|
45
43
|
};
|
|
46
44
|
/**
|
|
47
|
-
* Validates a normalized local date and time string (uses `T` separator only, omits zero seconds).
|
|
48
|
-
*
|
|
49
45
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
|
|
50
46
|
*/
|
|
51
47
|
export const checkNormalizedLocalDateAndTimeString = () => function checkNormalizedLocalDateAndTimeString(value) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a month string in the format `YYYY-MM`.
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkMonthString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a month string in the format `YYYY-MM`.
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
|
|
8
6
|
*/
|
|
9
7
|
export const checkMonthString = () => function checkMonthString(value) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a time string in the format `HH:MM[:SS[.sss]]`.
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#times
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkTimeString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a time string in the format `HH:MM[:SS[.sss]]`.
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#times
|
|
8
6
|
*/
|
|
9
7
|
export const checkTimeString = () => function checkTimeString(value) {
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import type { Token } from '../../token/index.js';
|
|
2
2
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Validates a time-zone offset string (`Z`, `+HH:MM`, or `-HH:MM`).
|
|
5
|
-
*
|
|
6
4
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#time-zones
|
|
7
5
|
*/
|
|
8
6
|
export declare const checkTimeZoneOffsetString: CustomSyntaxChecker;
|
|
9
|
-
/**
|
|
10
|
-
* Parses and validates a time-zone offset string (e.g., `Z`, `+09:00`, `-05:30`).
|
|
11
|
-
*
|
|
12
|
-
* @param zone - The time-zone string or token to validate
|
|
13
|
-
* @returns The validation result
|
|
14
|
-
*/
|
|
15
7
|
export declare function parseTimeZone(zone: string | Readonly<Token>): import("../../types.js").Result;
|
|
@@ -3,20 +3,12 @@ import { matched, unmatched } from '../../match-result.js';
|
|
|
3
3
|
import { TokenCollection } from '../../token/index.js';
|
|
4
4
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
5
5
|
/**
|
|
6
|
-
* Validates a time-zone offset string (`Z`, `+HH:MM`, or `-HH:MM`).
|
|
7
|
-
*
|
|
8
6
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#time-zones
|
|
9
7
|
*/
|
|
10
8
|
export const checkTimeZoneOffsetString = () => function checkTimeZoneOffsetString(value) {
|
|
11
9
|
log('CHECK: time-zone-offset-string');
|
|
12
10
|
return parseTimeZone(value);
|
|
13
11
|
};
|
|
14
|
-
/**
|
|
15
|
-
* Parses and validates a time-zone offset string (e.g., `Z`, `+09:00`, `-05:30`).
|
|
16
|
-
*
|
|
17
|
-
* @param zone - The time-zone string or token to validate
|
|
18
|
-
* @returns The validation result
|
|
19
|
-
*/
|
|
20
12
|
export function parseTimeZone(zone) {
|
|
21
13
|
const value = typeof zone === 'string' ? zone : zone.value;
|
|
22
14
|
const zoneTokens = TokenCollection.fromPatterns(zone, [
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a week string in the format `YYYY-Www`.
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#weeks
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkWeekString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a week string in the format `YYYY-Www`.
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#weeks
|
|
8
6
|
*/
|
|
9
7
|
export const checkWeekString = () => function checkWeekString(value) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a year string (four or more digits, greater than zero).
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkYearString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a year string (four or more digits, greater than zero).
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html
|
|
8
6
|
*/
|
|
9
7
|
export const checkYearString = () => function checkYearString(value) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { CustomSyntaxChecker } from '../../types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Validates a yearless date string in the format `MM-DD`.
|
|
4
|
-
*
|
|
5
3
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#yearless-dates
|
|
6
4
|
*/
|
|
7
5
|
export declare const checkYearlessDateString: CustomSyntaxChecker;
|
|
@@ -2,8 +2,6 @@ import { log } from '../../debug.js';
|
|
|
2
2
|
import { TokenCollection } from '../../token/index.js';
|
|
3
3
|
import { datetimeTokenCheck } from './datetime-tokens.js';
|
|
4
4
|
/**
|
|
5
|
-
* Validates a yearless date string in the format `MM-DD`.
|
|
6
|
-
*
|
|
7
5
|
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#yearless-dates
|
|
8
6
|
*/
|
|
9
7
|
export const checkYearlessDateString = () => function checkYearlessDateString(value) {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Checks whether a string is a valid email address per the HTML spec.
|
|
3
|
-
*
|
|
4
2
|
* The regex below is the **verbatim** pattern from the HTML Living Standard.
|
|
5
3
|
* It intentionally uses explicit ASCII ranges (`[a-zA-Z0-9]`) instead of `\w`
|
|
6
4
|
* because the spec restricts valid characters to ASCII only. `\w` is equivalent
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CustomSyntaxChecker } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates the `content` attribute value of `<meta http-equiv="content-type">`
|
|
4
|
+
* against the HTML Living Standard §4.2.5.2 "Encoding declaration" grammar:
|
|
5
|
+
*
|
|
6
|
+
* ASCII case-insensitive "text/html;"
|
|
7
|
+
* , optionally ASCII whitespace
|
|
8
|
+
* , "charset=utf-8"
|
|
9
|
+
*
|
|
10
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
|
|
11
|
+
*/
|
|
12
|
+
export declare const checkHTTPEquivContentType: CustomSyntaxChecker;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { log } from '../debug.js';
|
|
2
|
+
import { matched, unmatched } from '../match-result.js';
|
|
3
|
+
// HTML LS's Encoding declaration state requires the literal string
|
|
4
|
+
// "charset=utf-8" — not an arbitrary Encoding LS label. Unlike the
|
|
5
|
+
// `charset` content attribute (a plain `enum: ["utf-8"]` in
|
|
6
|
+
// spec.meta.jsonc), this value is free-form text, so the literal is
|
|
7
|
+
// enforced here via regex instead.
|
|
8
|
+
const CONTENT_TYPE_RE = /^text\/html;[\t\n\f\r ]*charset=utf-8$/i;
|
|
9
|
+
/**
|
|
10
|
+
* Validates the `content` attribute value of `<meta http-equiv="content-type">`
|
|
11
|
+
* against the HTML Living Standard §4.2.5.2 "Encoding declaration" grammar:
|
|
12
|
+
*
|
|
13
|
+
* ASCII case-insensitive "text/html;"
|
|
14
|
+
* , optionally ASCII whitespace
|
|
15
|
+
* , "charset=utf-8"
|
|
16
|
+
*
|
|
17
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
|
|
18
|
+
*/
|
|
19
|
+
export const checkHTTPEquivContentType = () => function checkHTTPEquivContentType(value) {
|
|
20
|
+
log('CHECK: meta http-equiv="content-type" content');
|
|
21
|
+
if (!CONTENT_TYPE_RE.test(value)) {
|
|
22
|
+
return unmatched(value, 'syntax-error', {
|
|
23
|
+
expects: [
|
|
24
|
+
{
|
|
25
|
+
type: 'format',
|
|
26
|
+
value: 'text/html; charset=<encoding>',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return matched();
|
|
32
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CustomSyntaxChecker } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates the `content` attribute value of `<meta http-equiv="refresh">`
|
|
4
|
+
* against the HTML Living Standard §4.2.5.3 "Refresh" conformance grammar.
|
|
5
|
+
*
|
|
6
|
+
* The grammar (distinct from the more lenient parse algorithm browsers use
|
|
7
|
+
* to execute the refresh):
|
|
8
|
+
*
|
|
9
|
+
* 1. Optionally, ASCII whitespace.
|
|
10
|
+
* 2. A valid non-negative integer.
|
|
11
|
+
* 3. Optionally:
|
|
12
|
+
* 1. Either a ";" (U+003B) or a "," (U+002C).
|
|
13
|
+
* 2. Optionally, ASCII whitespace.
|
|
14
|
+
* 3. Either:
|
|
15
|
+
* - An ASCII case-insensitive match for "URL", followed by "=",
|
|
16
|
+
* followed by a valid URL potentially surrounded by spaces.
|
|
17
|
+
* - A valid URL potentially surrounded by spaces.
|
|
18
|
+
*
|
|
19
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
|
|
20
|
+
*/
|
|
21
|
+
export declare const checkHTTPEquivRefresh: CustomSyntaxChecker;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { log } from '../debug.js';
|
|
2
|
+
import { matched, unmatched } from '../match-result.js';
|
|
3
|
+
import { checkURL } from './check-url.js';
|
|
4
|
+
// `ASCII whitespace` per Infra: TAB, LF, FF, CR, SPACE.
|
|
5
|
+
// https://infra.spec.whatwg.org/#ascii-whitespace
|
|
6
|
+
const ASCII_WHITESPACE = /[\t\n\f\r ]/;
|
|
7
|
+
// `ASCII digit` per Infra. `\d` happens to match the same set today in
|
|
8
|
+
// JavaScript regexes, but the HTML LS grammar is specific to U+0030–U+0039,
|
|
9
|
+
// so we pin the class to that range to protect against accidental Unicode
|
|
10
|
+
// broadening if the `u` flag or a future regex flavour drifts it.
|
|
11
|
+
// oxlint: use-the-regex-literal-shorthand warns on `[0-9]`; suppress here so
|
|
12
|
+
// the spec intent survives auto-fix passes.
|
|
13
|
+
// eslint-disable-next-line regexp/prefer-d
|
|
14
|
+
const ASCII_DIGIT = /[0-9]/;
|
|
15
|
+
function isAsciiWhitespace(ch) {
|
|
16
|
+
return ASCII_WHITESPACE.test(ch);
|
|
17
|
+
}
|
|
18
|
+
function isAsciiDigit(ch) {
|
|
19
|
+
return ASCII_DIGIT.test(ch);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validates the `content` attribute value of `<meta http-equiv="refresh">`
|
|
23
|
+
* against the HTML Living Standard §4.2.5.3 "Refresh" conformance grammar.
|
|
24
|
+
*
|
|
25
|
+
* The grammar (distinct from the more lenient parse algorithm browsers use
|
|
26
|
+
* to execute the refresh):
|
|
27
|
+
*
|
|
28
|
+
* 1. Optionally, ASCII whitespace.
|
|
29
|
+
* 2. A valid non-negative integer.
|
|
30
|
+
* 3. Optionally:
|
|
31
|
+
* 1. Either a ";" (U+003B) or a "," (U+002C).
|
|
32
|
+
* 2. Optionally, ASCII whitespace.
|
|
33
|
+
* 3. Either:
|
|
34
|
+
* - An ASCII case-insensitive match for "URL", followed by "=",
|
|
35
|
+
* followed by a valid URL potentially surrounded by spaces.
|
|
36
|
+
* - A valid URL potentially surrounded by spaces.
|
|
37
|
+
*
|
|
38
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
|
|
39
|
+
*/
|
|
40
|
+
export const checkHTTPEquivRefresh = () => function checkHTTPEquivRefresh(value) {
|
|
41
|
+
log('CHECK: meta http-equiv="refresh" content');
|
|
42
|
+
let i = 0;
|
|
43
|
+
const len = value.length;
|
|
44
|
+
// 1. Optional leading ASCII whitespace.
|
|
45
|
+
while (i < len && isAsciiWhitespace(value[i]))
|
|
46
|
+
i++;
|
|
47
|
+
// 2. Required: a valid non-negative integer.
|
|
48
|
+
const digitStart = i;
|
|
49
|
+
while (i < len && isAsciiDigit(value[i]))
|
|
50
|
+
i++;
|
|
51
|
+
if (digitStart === i) {
|
|
52
|
+
return unmatched(value, 'syntax-error', {
|
|
53
|
+
expects: [{ type: 'format', value: 'non-negative integer' }],
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// No clause-3 block: the remainder of the string must be empty.
|
|
57
|
+
if (i === len)
|
|
58
|
+
return matched();
|
|
59
|
+
// 3.1 Required separator ";" or ",". Whitespace alone does not open
|
|
60
|
+
// the optional clause — the conformance text names the punctuation
|
|
61
|
+
// explicitly, and refusing bare whitespace is how we catch the
|
|
62
|
+
// `refresh-missing-semicolon` fixture.
|
|
63
|
+
const sep = value[i];
|
|
64
|
+
if (sep !== ';' && sep !== ',') {
|
|
65
|
+
return unmatched(value, 'unexpected-token', {
|
|
66
|
+
expects: [
|
|
67
|
+
{ type: 'const', value: ';' },
|
|
68
|
+
{ type: 'const', value: ',' },
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
i++;
|
|
73
|
+
// 3.2 Optional ASCII whitespace.
|
|
74
|
+
while (i < len && isAsciiWhitespace(value[i]))
|
|
75
|
+
i++;
|
|
76
|
+
// 3.3 URL part — either "URL=<url>" (case-insensitive) or a bare URL.
|
|
77
|
+
if (i === len) {
|
|
78
|
+
// Clause 3 was opened by the separator but clause 3.3 is
|
|
79
|
+
// missing. A trailing `;` with nothing after breaks the grammar.
|
|
80
|
+
return unmatched(value, 'missing-token', {
|
|
81
|
+
expects: [{ type: 'common', value: 'URL' }],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const rest = value.slice(i);
|
|
85
|
+
let urlStr;
|
|
86
|
+
if (rest.length >= 4 && rest.slice(0, 3).toLowerCase() === 'url' && rest[3] === '=') {
|
|
87
|
+
urlStr = rest.slice(4);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Fall back to the bare-URL alternative. If the tail begins with
|
|
91
|
+
// something that looks like a keyword but is not "URL=" (e.g.,
|
|
92
|
+
// `href=...`), HTML LS still accepts it as long as the full tail
|
|
93
|
+
// parses as a valid URL — a relative-URL string with "=" in its
|
|
94
|
+
// path is legal per URL LS. That is why nu-validator's
|
|
95
|
+
// `refresh-invalid-keyword` over-detection is not a markuplint
|
|
96
|
+
// gap; see `snapshots/excluded-ids.json`.
|
|
97
|
+
urlStr = rest;
|
|
98
|
+
}
|
|
99
|
+
const urlResult = checkURL()(urlStr);
|
|
100
|
+
if (!urlResult.matched) {
|
|
101
|
+
return unmatched(value, urlResult.reason, {
|
|
102
|
+
expects: [{ type: 'common', value: 'URL' }],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return matched();
|
|
106
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { CustomSyntaxChecker } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates a `media` attribute value against the Media Queries Level 5
|
|
4
|
+
* grammar and authoring constraints.
|
|
5
|
+
*
|
|
6
|
+
* Catches three classes of conformance error that nu-validator reports but
|
|
7
|
+
* `whatwg-mimetype`-style checks do not:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Syntax errors** — unbalanced parens, stray semicolons inside `()`,
|
|
10
|
+
* unrecognised dimensions. Detected via `css-tree`'s `mediaQueryList`
|
|
11
|
+
* parser entry-point.
|
|
12
|
+
* 2. **Unknown / deprecated media types** — anything outside
|
|
13
|
+
* {`all`, `screen`, `print`} (e.g., `alla`, `notscreen`, `projection`).
|
|
14
|
+
* Per [Media Queries Level 5 §2.3](https://www.w3.org/TR/mediaqueries-5/#media-types),
|
|
15
|
+
* deprecated types are syntactically valid but author conformance
|
|
16
|
+
* forbids them.
|
|
17
|
+
* 3. **Deprecated media features** — `device-width` / `device-height` /
|
|
18
|
+
* `device-aspect-ratio` and their min-/max- variants. MDN's `@media`
|
|
19
|
+
* reference marks them as
|
|
20
|
+
* [deprecated since Media Queries Level 4](https://developer.mozilla.org/en-US/docs/Web/CSS/@media).
|
|
21
|
+
* 4. **Wrong-type feature values** — `(min-width: 400)` (unitless
|
|
22
|
+
* non-zero number for a `<length>` feature), `(min-width: 400dpi)`
|
|
23
|
+
* (resolution unit on a length feature), `(color: 1em)` (length
|
|
24
|
+
* on an integer feature). The matrix covers length / integer /
|
|
25
|
+
* resolution / ratio features per Media Queries Level 5 §4. Unknown
|
|
26
|
+
* features are passed through unchanged so forward-compat additions
|
|
27
|
+
* do not regress to errors.
|
|
28
|
+
*
|
|
29
|
+
* @see https://www.w3.org/TR/mediaqueries-5/
|
|
30
|
+
*/
|
|
31
|
+
export declare const checkMediaQueryList: CustomSyntaxChecker;
|
|
32
|
+
/**
|
|
33
|
+
* Exists so callers that embed a `<media-condition>` inside a larger grammar
|
|
34
|
+
* (`<source-size-list>` in `<sizes>`) can enforce the same forbidden-in-authoring
|
|
35
|
+
* rule that {@link checkMediaQueryList} applies to `<media-query-list>` values.
|
|
36
|
+
*
|
|
37
|
+
* @see https://www.w3.org/TR/mediaqueries-5/#general-enclosed — "Authors must
|
|
38
|
+
* not use `<general-enclosed>` in their stylesheets. It exists only for
|
|
39
|
+
* future-compatibility, so that new syntax additions do not invalidate too
|
|
40
|
+
* much of a `<media-condition>` in older user agents."
|
|
41
|
+
*
|
|
42
|
+
* Contract:
|
|
43
|
+
*
|
|
44
|
+
* - css-tree emits `GeneralEnclosed` only when the enclosed tokens fail
|
|
45
|
+
* `<media-feature>` grammar (`(min-width:)` empty value, `(123)` non-ident);
|
|
46
|
+
* well-formed `(<ident>: <value>)` shapes parse as `Feature`, so unknown
|
|
47
|
+
* feature names keep passing (forward-compatibility).
|
|
48
|
+
* - Returns `null` on any css-tree parse failure — the enclosing checker owns
|
|
49
|
+
* grammar-error reporting. Only a *successful* parse reaching the fallback
|
|
50
|
+
* surfaces here.
|
|
51
|
+
* - Programmer-error throws (`TypeError` etc.) bubble up; only Tier-3 css-tree
|
|
52
|
+
* `SyntaxError` shapes are swallowed via `isCssTreeParseError`.
|
|
53
|
+
*
|
|
54
|
+
* @param snippet raw parenthesised group extracted from the outer value
|
|
55
|
+
* @returns first match's `{ raw, offset }` (offset is 0-based within `snippet`
|
|
56
|
+
* — callers add their own outer offset when reporting), or `null` if none
|
|
57
|
+
*/
|
|
58
|
+
export declare function findGeneralEnclosed(snippet: string): {
|
|
59
|
+
readonly raw: string;
|
|
60
|
+
readonly offset: number;
|
|
61
|
+
} | null;
|