@markuplint/astro-parser 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [5.5.0](https://github.com/markuplint/markuplint/compare/v5.4.0...v5.5.0) (2026-11-10)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **astro-parser:** render popover on a custom element as a boolean attribute ([7c0ba29](https://github.com/markuplint/markuplint/commit/7c0ba29da70a7e90fff84164867317d28e9ff3ea))
11
+
12
+ ### Features
13
+
14
+ * **astro-parser:** declare how Astro renders a literal written as code ([8989d17](https://github.com/markuplint/markuplint/commit/8989d179527a8d94e29ff4ed8bece36aafaa6315))
15
+
16
+
6
17
  # [5.4.0](https://github.com/markuplint/markuplint/compare/v5.3.0...v5.4.0) (2026-10-29)
7
18
 
8
19
  **Note:** Version bump only for package @markuplint/astro-parser
@@ -71,7 +71,8 @@ function extractAttrs(el) {
71
71
  }
72
72
  const value = attr.value.raw;
73
73
  if (attr.isDynamicValue) {
74
- const expression = value.trim();
74
+ // An expression that the parser kept apart from its quotes is `potentialValue`
75
+ const expression = (attr.potentialValue ?? value).trim();
75
76
  addAttr(attrs, { name: attr.nodeName, dynamic: true, ...(expression === '' ? {} : { expression }) });
76
77
  }
77
78
  else if (/^`.*`$/s.test(value)) {
@@ -0,0 +1,27 @@
1
+ import type { LiteralValueDeclaration } from '@markuplint/ml-ast';
2
+ /**
3
+ * How Astro renders a literal in `{…}` (`addAttribute` of `astro/runtime/server/render/util.ts`),
4
+ * where it differs from the default of `@markuplint/ml-core`. Astro has no spec package, so the
5
+ * parser says it. Names are in lower case.
6
+ *
7
+ * - A boolean attribute (`htmlBooleanAttributes`) is present for a truthy value, which is `""`: `disabled={""}`
8
+ * has no `disabled`. Any other value is a string (`title={true}` is `title="true"`, as the default says)
9
+ * - `download` and `popover` are present for `true` and absent for `false`; `hidden` is present for `true`,
10
+ * absent for `false`, and a number is a string (`hidden={0}` is `hidden="0"`)
11
+ * - A custom element takes every boolean as a string (`handleBooleanAttribute`): `disabled={false}` is
12
+ * `disabled="false"`, except `popover`, which is rendered as on any element (present for `true`, absent for
13
+ * `false`):
14
+ *
15
+ * > The Popover API only accepts "auto", "manual", or the attribute being absent.
16
+ *
17
+ * What it does not tell, which does not affect a rule:
18
+ *
19
+ * - `hidden` and `popover` take a string as it is (`hidden="until-found"`), which the default does too
20
+ * - `scoped` and `seamless`, obsolete attributes that Astro renders as boolean, are not in the spec
21
+ *
22
+ * @see https://docs.astro.build/en/reference/astro-syntax/#dynamic-attributes
23
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#addAttribute
24
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#htmlBooleanAttributes
25
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#handleBooleanAttribute
26
+ */
27
+ export declare const ASTRO_LITERAL_VALUES: LiteralValueDeclaration;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The rendering of the attribute that Astro does not render as a boolean, whose spec is Boolean: it
3
+ * is rendered as a string, with the empty string as its name alone (`addAttribute`).
4
+ */
5
+ const AS_STRING = { true: 'true', false: 'false', '0': '0', '""': '' };
6
+ /**
7
+ * The rendering of the attribute that Astro renders as a boolean and the spec does not know as one:
8
+ * present for a truthy value.
9
+ */
10
+ const AS_BOOLEAN = { true: '', false: null, '0': null, '""': null };
11
+ /**
12
+ * How Astro renders a literal in `{…}` (`addAttribute` of `astro/runtime/server/render/util.ts`),
13
+ * where it differs from the default of `@markuplint/ml-core`. Astro has no spec package, so the
14
+ * parser says it. Names are in lower case.
15
+ *
16
+ * - A boolean attribute (`htmlBooleanAttributes`) is present for a truthy value, which is `""`: `disabled={""}`
17
+ * has no `disabled`. Any other value is a string (`title={true}` is `title="true"`, as the default says)
18
+ * - `download` and `popover` are present for `true` and absent for `false`; `hidden` is present for `true`,
19
+ * absent for `false`, and a number is a string (`hidden={0}` is `hidden="0"`)
20
+ * - A custom element takes every boolean as a string (`handleBooleanAttribute`): `disabled={false}` is
21
+ * `disabled="false"`, except `popover`, which is rendered as on any element (present for `true`, absent for
22
+ * `false`):
23
+ *
24
+ * > The Popover API only accepts "auto", "manual", or the attribute being absent.
25
+ *
26
+ * What it does not tell, which does not affect a rule:
27
+ *
28
+ * - `hidden` and `popover` take a string as it is (`hidden="until-found"`), which the default does too
29
+ * - `scoped` and `seamless`, obsolete attributes that Astro renders as boolean, are not in the spec
30
+ *
31
+ * @see https://docs.astro.build/en/reference/astro-syntax/#dynamic-attributes
32
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#addAttribute
33
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#htmlBooleanAttributes
34
+ * @see https://github.com/withastro/astro/blob/main/packages/runtime/src/internal/server/render/util.ts#handleBooleanAttribute
35
+ */
36
+ export const ASTRO_LITERAL_VALUES = {
37
+ booleanAttrs: { '""': null },
38
+ attrs: {
39
+ download: { true: '', false: null },
40
+ popover: { true: '', false: null },
41
+ hidden: { '0': '0' },
42
+ // Booleans of Astro that the spec does not know as boolean
43
+ disablepictureinpicture: AS_BOOLEAN,
44
+ disableremoteplayback: AS_BOOLEAN,
45
+ // Boolean attributes of the spec that Astro does not render as boolean
46
+ alpha: AS_STRING,
47
+ focusgroupstart: AS_STRING,
48
+ headingreset: AS_STRING,
49
+ ismap: AS_STRING,
50
+ multiple: AS_STRING,
51
+ shadowrootclonable: AS_STRING,
52
+ shadowrootcustomelementregistry: AS_STRING,
53
+ shadowrootdelegatesfocus: AS_STRING,
54
+ shadowrootserializable: AS_STRING,
55
+ switch: AS_STRING,
56
+ },
57
+ customElements: {
58
+ booleanAttrs: AS_STRING,
59
+ attrs: {
60
+ hidden: { true: 'true', false: 'false', '0': '0' },
61
+ popover: { true: '', false: null },
62
+ download: { true: 'true', false: 'false' },
63
+ },
64
+ },
65
+ };
package/lib/parser.d.ts CHANGED
@@ -101,7 +101,7 @@ declare class AstroParser extends Parser<Node> {
101
101
  * > Variable names must be capitalized. For example, use `Element`, not `element`.
102
102
  * > Otherwise, Astro will try to render your variable name as a literal HTML tag.
103
103
  *
104
- * @see https://docs.astro.build/en/basics/astro-syntax/#dynamic-html
104
+ * @see https://docs.astro.build/en/reference/astro-syntax/#dynamic-tags
105
105
  * @param nodeName
106
106
  * @param defaultPattern
107
107
  */
package/lib/parser.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AttrState, Parser, ParserError, isPotentialCustomElementName } from '@markuplint/parser-utils';
2
2
  import { astroParse } from './astro-parser.js';
3
3
  import { detectBlockBehavior } from './detect-block-behavior.js';
4
+ import { ASTRO_LITERAL_VALUES } from './literal-values.js';
4
5
  import { extractSpreadAttribute } from './spread-attr.js';
5
6
  import { toNodes } from './to-nodes.js';
6
7
  /**
@@ -23,6 +24,9 @@ class AstroParser extends Parser {
23
24
  selfCloseType: 'html+xml',
24
25
  // Distinguishes components (`<MyComp>`) from HTML elements (`<div>`).
25
26
  tagNameCaseSensitive: true,
27
+ // A value in `{…}` is JavaScript
28
+ attrExpressionLanguage: 'javascript',
29
+ literalValues: ASTRO_LITERAL_VALUES,
26
30
  });
27
31
  }
28
32
  tokenize() {
@@ -303,7 +307,7 @@ class AstroParser extends Parser {
303
307
  * > Variable names must be capitalized. For example, use `Element`, not `element`.
304
308
  * > Otherwise, Astro will try to render your variable name as a literal HTML tag.
305
309
  *
306
- * @see https://docs.astro.build/en/basics/astro-syntax/#dynamic-html
310
+ * @see https://docs.astro.build/en/reference/astro-syntax/#dynamic-tags
307
311
  * @param nodeName
308
312
  * @param defaultPattern
309
313
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/astro-parser",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "astro parser for markuplint",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,9 +32,9 @@
32
32
  "clean": "tsc --build --clean tsconfig.build.json"
33
33
  },
34
34
  "dependencies": {
35
- "@markuplint/ml-ast": "5.3.0",
36
- "@markuplint/parser-utils": "5.4.0",
35
+ "@markuplint/ml-ast": "5.5.0",
36
+ "@markuplint/parser-utils": "5.5.0",
37
37
  "astro-eslint-parser": "^3.2.0"
38
38
  },
39
- "gitHead": "647f6fb5d5743f060678599c97e9c84b58970747"
39
+ "gitHead": "fedebcfd56eaec4642e68643b2f9e10750d810e1"
40
40
  }