@markuplint/pug-parser 5.3.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 +19 -0
- package/lib/literal-values.d.ts +28 -0
- package/lib/literal-values.js +37 -0
- package/lib/parser.js +16 -35
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
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
|
+
* **pug-parser:** count a leading BOM in the positions ([6d47ba9](https://github.com/markuplint/markuplint/commit/6d47ba911af99c3c4c7cc5848ef1b168f0719e33)), closes [#4488](https://github.com/markuplint/markuplint/issues/4488)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **pug-parser:** record every value after `=` as the code that it is ([58ae2d8](https://github.com/markuplint/markuplint/commit/58ae2d8a7866aee37a1932d51a05e4feead02435))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [5.4.0](https://github.com/markuplint/markuplint/compare/v5.3.0...v5.4.0) (2026-10-29)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package @markuplint/pug-parser
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
# [5.3.0](https://github.com/markuplint/markuplint/compare/v5.2.0...v5.3.0) (2026-10-21)
|
|
7
26
|
|
|
8
27
|
### Bug Fixes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LiteralValueDeclaration } from '@markuplint/ml-ast';
|
|
2
|
+
/**
|
|
3
|
+
* How Pug renders a literal in an attribute value (`pug_attr` of `pug-runtime`, which `pug-attrs` uses to
|
|
4
|
+
* fold a constant too), where it differs from the default of `@markuplint/ml-core`. Pug has no spec
|
|
5
|
+
* package, so the parser says it. Names are in lower case.
|
|
6
|
+
*
|
|
7
|
+
* Pug has no list of boolean attributes and decides by the value alone:
|
|
8
|
+
*
|
|
9
|
+
* - `true` is the attribute with its name as the value (`checked="checked"`, or `checked` under
|
|
10
|
+
* `doctype html`), whichever attribute it is, `data-x=true` included: it is `""` here, as the attribute
|
|
11
|
+
* is present
|
|
12
|
+
* - `false`, `null` and `undefined` remove the attribute
|
|
13
|
+
* - `class` and `style` are also removed for a falsy value, `""` and `0`
|
|
14
|
+
* - Any other value is written with `JSON.stringify`, so `0` is `"0"` on any attribute, a boolean attribute
|
|
15
|
+
* included (`disabled=0` is `disabled="0"`, which is present)
|
|
16
|
+
*
|
|
17
|
+
* What it does not tell, which does not affect a rule:
|
|
18
|
+
*
|
|
19
|
+
* - A boolean attribute has its name as the value (`disabled="disabled"`) unless `doctype html`
|
|
20
|
+
* - A string on a boolean attribute is `""` in the default, and Pug writes the string
|
|
21
|
+
* - A quoted attribute name (`'data-x'="y"`) and an unescaped one (`data-x!="y"`) are read as code
|
|
22
|
+
* whose value is not known
|
|
23
|
+
*
|
|
24
|
+
* @see https://pugjs.org/language/attributes.html#boolean-attributes
|
|
25
|
+
* @see https://pugjs.org/language/doctype.html#doctype-shortcuts
|
|
26
|
+
* @see https://github.com/pugjs/pug/blob/master/packages/pug-runtime/index.js#pug_attr
|
|
27
|
+
*/
|
|
28
|
+
export declare const PUG_LITERAL_VALUES: LiteralValueDeclaration;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How Pug renders a literal in an attribute value (`pug_attr` of `pug-runtime`, which `pug-attrs` uses to
|
|
3
|
+
* fold a constant too), where it differs from the default of `@markuplint/ml-core`. Pug has no spec
|
|
4
|
+
* package, so the parser says it. Names are in lower case.
|
|
5
|
+
*
|
|
6
|
+
* Pug has no list of boolean attributes and decides by the value alone:
|
|
7
|
+
*
|
|
8
|
+
* - `true` is the attribute with its name as the value (`checked="checked"`, or `checked` under
|
|
9
|
+
* `doctype html`), whichever attribute it is, `data-x=true` included: it is `""` here, as the attribute
|
|
10
|
+
* is present
|
|
11
|
+
* - `false`, `null` and `undefined` remove the attribute
|
|
12
|
+
* - `class` and `style` are also removed for a falsy value, `""` and `0`
|
|
13
|
+
* - Any other value is written with `JSON.stringify`, so `0` is `"0"` on any attribute, a boolean attribute
|
|
14
|
+
* included (`disabled=0` is `disabled="0"`, which is present)
|
|
15
|
+
*
|
|
16
|
+
* What it does not tell, which does not affect a rule:
|
|
17
|
+
*
|
|
18
|
+
* - A boolean attribute has its name as the value (`disabled="disabled"`) unless `doctype html`
|
|
19
|
+
* - A string on a boolean attribute is `""` in the default, and Pug writes the string
|
|
20
|
+
* - A quoted attribute name (`'data-x'="y"`) and an unescaped one (`data-x!="y"`) are read as code
|
|
21
|
+
* whose value is not known
|
|
22
|
+
*
|
|
23
|
+
* @see https://pugjs.org/language/attributes.html#boolean-attributes
|
|
24
|
+
* @see https://pugjs.org/language/doctype.html#doctype-shortcuts
|
|
25
|
+
* @see https://github.com/pugjs/pug/blob/master/packages/pug-runtime/index.js#pug_attr
|
|
26
|
+
*/
|
|
27
|
+
export const PUG_LITERAL_VALUES = {
|
|
28
|
+
booleanAttrs: { '""': '', '0': '0' },
|
|
29
|
+
ariaAttrs: { true: '', false: null },
|
|
30
|
+
dataAttrs: { true: '', false: null },
|
|
31
|
+
otherAttrs: { true: '', false: null },
|
|
32
|
+
attrs: {
|
|
33
|
+
class: { '""': null, '0': null },
|
|
34
|
+
style: { '""': null, '0': null },
|
|
35
|
+
hidden: { '0': '0' },
|
|
36
|
+
},
|
|
37
|
+
};
|
package/lib/parser.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HtmlParser } from '@markuplint/html-parser';
|
|
2
|
-
import { ParserError, Parser, AttrState,
|
|
2
|
+
import { ParserError, Parser, AttrState, getNamespace } from '@markuplint/parser-utils';
|
|
3
|
+
import { PUG_LITERAL_VALUES } from './literal-values.js';
|
|
3
4
|
import { pugParse } from './pug-parser/index.js';
|
|
4
5
|
class HtmlInPugParser extends HtmlParser {
|
|
5
6
|
constructor() {
|
|
@@ -32,6 +33,11 @@ class PugParser extends Parser {
|
|
|
32
33
|
super({
|
|
33
34
|
// Pug expresses nesting through indentation and never emits explicit closing tags.
|
|
34
35
|
endTagType: 'never',
|
|
36
|
+
// A value of `=` is JavaScript ("their values are just regular JavaScript")
|
|
37
|
+
attrExpressionLanguage: 'javascript',
|
|
38
|
+
literalValues: PUG_LITERAL_VALUES,
|
|
39
|
+
// pug-lexer strips a leading BOM itself, and a space in its place would be indentation
|
|
40
|
+
leadingBom: 'strip',
|
|
35
41
|
});
|
|
36
42
|
}
|
|
37
43
|
tokenize(options) {
|
|
@@ -301,41 +307,16 @@ class PugParser extends Parser {
|
|
|
301
307
|
potentialName: attr.name.raw.slice(0, -1),
|
|
302
308
|
});
|
|
303
309
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
valueType: 'number',
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
case 'Boolean': {
|
|
315
|
-
return {
|
|
316
|
-
...attr,
|
|
317
|
-
valueType: 'boolean',
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
case 'String':
|
|
321
|
-
case 'Template': {
|
|
322
|
-
const value = super.visitAttr(attr.value, {
|
|
323
|
-
startState: AttrState.BeforeValue,
|
|
324
|
-
noQuoteValueType: 'script',
|
|
325
|
-
});
|
|
326
|
-
if (value.type === 'spread') {
|
|
327
|
-
throw new ParserError('Unexpected attribute value', value);
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
...attr,
|
|
331
|
-
startQuote: value.startQuote,
|
|
332
|
-
value: value.value,
|
|
333
|
-
endQuote: value.endQuote,
|
|
334
|
-
...(attr.name.raw.endsWith('!') ? { valueType: 'code' } : {}),
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
}
|
|
310
|
+
// An attribute without a value (`disabled`) is `true` and is not written as code, while any value after
|
|
311
|
+
// `=` is JavaScript (the introduction of the page below, which has no heading to cite, says that the
|
|
312
|
+
// values of the attributes are regular JavaScript): whether it is a literal, and what Pug renders it
|
|
313
|
+
// as, is up to `@markuplint/ml-core`, which reads it as it reads the code of any language.
|
|
314
|
+
// @see https://pugjs.org/language/attributes.html
|
|
315
|
+
if (attr.equal.raw === '') {
|
|
316
|
+
return attr;
|
|
338
317
|
}
|
|
318
|
+
// The value is code. A literal that `@markuplint/ml-core` reads is a string there, and any other code
|
|
319
|
+
// (and an unescaped one, `href!="x"`) stays code.
|
|
339
320
|
return {
|
|
340
321
|
...attr,
|
|
341
322
|
isDynamicValue: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/pug-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.0",
|
|
4
4
|
"description": "Pug parser for markuplint",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@markuplint/html-parser": "5.
|
|
32
|
-
"@markuplint/ml-ast": "5.
|
|
33
|
-
"@markuplint/parser-utils": "5.
|
|
31
|
+
"@markuplint/html-parser": "5.5.0",
|
|
32
|
+
"@markuplint/ml-ast": "5.5.0",
|
|
33
|
+
"@markuplint/parser-utils": "5.5.0",
|
|
34
34
|
"pug-lexer": "^5.0.1",
|
|
35
35
|
"pug-parser": "^6.0.0"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "fedebcfd56eaec4642e68643b2f9e10750d810e1"
|
|
38
38
|
}
|