@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.
Files changed (116) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +83 -75
  3. package/lib/check-multi-types.d.ts +2 -9
  4. package/lib/check-multi-types.js +2 -9
  5. package/lib/css-defs.d.ts +0 -8
  6. package/lib/css-defs.js +0 -8
  7. package/lib/css-overrides.d.ts +2 -5
  8. package/lib/css-overrides.js +2 -5
  9. package/lib/css-syntax.d.ts +0 -11
  10. package/lib/css-syntax.js +6 -18
  11. package/lib/css-tokenizers.d.ts +0 -6
  12. package/lib/css-tokenizers.js +0 -6
  13. package/lib/debug.d.ts +0 -3
  14. package/lib/debug.js +0 -3
  15. package/lib/defs.d.ts +0 -8
  16. package/lib/defs.js +308 -37
  17. package/lib/directive.d.ts +0 -14
  18. package/lib/directive.js +0 -14
  19. package/lib/enum.d.ts +0 -11
  20. package/lib/enum.js +0 -11
  21. package/lib/keyword-type.d.ts +0 -13
  22. package/lib/keyword-type.js +0 -13
  23. package/lib/list.d.ts +0 -13
  24. package/lib/list.js +0 -13
  25. package/lib/match-result.d.ts +0 -21
  26. package/lib/match-result.js +0 -21
  27. package/lib/number.d.ts +0 -12
  28. package/lib/number.js +0 -12
  29. package/lib/primitive/is-float.d.ts +3 -4
  30. package/lib/primitive/is-float.js +3 -4
  31. package/lib/primitive/is-int.d.ts +0 -5
  32. package/lib/primitive/is-int.js +0 -5
  33. package/lib/primitive/is-non-zero-uint.d.ts +0 -6
  34. package/lib/primitive/is-non-zero-uint.js +0 -6
  35. package/lib/primitive/is-quantity.d.ts +0 -8
  36. package/lib/primitive/is-quantity.js +0 -8
  37. package/lib/primitive/is-uint.d.ts +0 -6
  38. package/lib/primitive/is-uint.js +0 -6
  39. package/lib/primitive/range.d.ts +0 -8
  40. package/lib/primitive/range.js +0 -8
  41. package/lib/primitive/split-unit.d.ts +0 -6
  42. package/lib/primitive/split-unit.js +0 -6
  43. package/lib/rfc/is-bcp-47.d.ts +24 -1
  44. package/lib/rfc/is-bcp-47.js +88 -3
  45. package/lib/token/token-collection.d.ts +1 -111
  46. package/lib/token/token-collection.js +0 -108
  47. package/lib/token/token.d.ts +1 -73
  48. package/lib/token/token.js +0 -72
  49. package/lib/token/types.d.ts +0 -9
  50. package/lib/types.schema.d.ts +1 -1
  51. package/lib/w3c/check-content-security-policy.d.ts +18 -0
  52. package/lib/w3c/check-content-security-policy.js +363 -0
  53. package/lib/w3c/check-serialized-permissions-policy.d.ts +0 -2
  54. package/lib/w3c/check-serialized-permissions-policy.js +0 -2
  55. package/lib/whatwg/check-autocomplete.d.ts +26 -9
  56. package/lib/whatwg/check-autocomplete.js +42 -15
  57. package/lib/whatwg/check-datetime/date-string-with-optional-time.d.ts +11 -0
  58. package/lib/whatwg/check-datetime/date-string-with-optional-time.js +16 -0
  59. package/lib/whatwg/check-datetime/date-string.d.ts +0 -2
  60. package/lib/whatwg/check-datetime/date-string.js +0 -2
  61. package/lib/whatwg/check-datetime/datetime-tokens.d.ts +0 -13
  62. package/lib/whatwg/check-datetime/datetime-tokens.js +0 -16
  63. package/lib/whatwg/check-datetime/duration-string.d.ts +0 -4
  64. package/lib/whatwg/check-datetime/duration-string.js +0 -4
  65. package/lib/whatwg/check-datetime/global-date-and-time-string.d.ts +0 -2
  66. package/lib/whatwg/check-datetime/global-date-and-time-string.js +4 -4
  67. package/lib/whatwg/check-datetime/index.d.ts +0 -5
  68. package/lib/whatwg/check-datetime/index.js +0 -5
  69. package/lib/whatwg/check-datetime/local-date-and-time-string.d.ts +0 -4
  70. package/lib/whatwg/check-datetime/local-date-and-time-string.js +0 -4
  71. package/lib/whatwg/check-datetime/month-string.d.ts +0 -2
  72. package/lib/whatwg/check-datetime/month-string.js +0 -2
  73. package/lib/whatwg/check-datetime/time-string.d.ts +0 -2
  74. package/lib/whatwg/check-datetime/time-string.js +0 -2
  75. package/lib/whatwg/check-datetime/time-zone-offset-string.d.ts +0 -8
  76. package/lib/whatwg/check-datetime/time-zone-offset-string.js +0 -8
  77. package/lib/whatwg/check-datetime/week-string.d.ts +0 -2
  78. package/lib/whatwg/check-datetime/week-string.js +0 -2
  79. package/lib/whatwg/check-datetime/year-string.d.ts +0 -2
  80. package/lib/whatwg/check-datetime/year-string.js +0 -2
  81. package/lib/whatwg/check-datetime/yearless-date-string.d.ts +0 -2
  82. package/lib/whatwg/check-datetime/yearless-date-string.js +0 -2
  83. package/lib/whatwg/check-email.js +0 -2
  84. package/lib/whatwg/check-http-equiv-content-type.d.ts +12 -0
  85. package/lib/whatwg/check-http-equiv-content-type.js +32 -0
  86. package/lib/whatwg/check-http-equiv-refresh.d.ts +21 -0
  87. package/lib/whatwg/check-http-equiv-refresh.js +106 -0
  88. package/lib/whatwg/check-media-query-list.d.ts +61 -0
  89. package/lib/whatwg/check-media-query-list.js +484 -0
  90. package/lib/whatwg/check-mime-type.d.ts +0 -4
  91. package/lib/whatwg/check-mime-type.js +55 -3
  92. package/lib/whatwg/check-simple-color.d.ts +2 -4
  93. package/lib/whatwg/check-simple-color.js +2 -4
  94. package/lib/whatwg/check-url.d.ts +15 -7
  95. package/lib/whatwg/check-url.js +333 -25
  96. package/lib/whatwg/is-abs-url.d.ts +0 -2
  97. package/lib/whatwg/is-abs-url.js +0 -2
  98. package/lib/whatwg/is-browser-context-name.d.ts +0 -2
  99. package/lib/whatwg/is-browser-context-name.js +0 -2
  100. package/lib/whatwg/is-itemprop-name.d.ts +0 -2
  101. package/lib/whatwg/is-itemprop-name.js +0 -2
  102. package/lib/whatwg/is-navigable-target-name.d.ts +0 -2
  103. package/lib/whatwg/is-navigable-target-name.js +0 -2
  104. package/package.json +6 -5
  105. package/types.schema.json +9 -0
  106. package/ARCHITECTURE.ja.md +0 -256
  107. package/ARCHITECTURE.md +0 -256
  108. package/SKILL.md +0 -100
  109. package/docs/check-pipeline.ja.md +0 -494
  110. package/docs/check-pipeline.md +0 -494
  111. package/docs/token-system.ja.md +0 -584
  112. package/docs/token-system.md +0 -584
  113. package/docs/type-system.ja.md +0 -623
  114. package/docs/type-system.md +0 -623
  115. package/docs/validators.ja.md +0 -536
  116. 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
- /(:[^+Z-]*)?/,
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;