html-validate 6.3.1 → 6.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/dist/cjs/core.d.ts +102 -26
- package/dist/cjs/core.js +112 -49
- package/dist/cjs/core.js.map +1 -1
- package/dist/es/core.d.ts +102 -26
- package/dist/es/core.js +112 -49
- package/dist/es/core.js.map +1 -1
- package/package.json +21 -23
package/dist/es/core.d.ts
CHANGED
|
@@ -40,28 +40,95 @@ declare class EventHandler {
|
|
|
40
40
|
declare enum TokenType {
|
|
41
41
|
UNICODE_BOM = 1,
|
|
42
42
|
WHITESPACE = 2,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
interface Token {
|
|
43
|
+
DOCTYPE_OPEN = 3,
|
|
44
|
+
DOCTYPE_VALUE = 4,
|
|
45
|
+
DOCTYPE_CLOSE = 5,
|
|
46
|
+
TAG_OPEN = 6,
|
|
47
|
+
TAG_CLOSE = 7,
|
|
48
|
+
ATTR_NAME = 8,
|
|
49
|
+
ATTR_VALUE = 9,
|
|
50
|
+
TEXT = 10,
|
|
51
|
+
TEMPLATING = 11,
|
|
52
|
+
SCRIPT = 12,
|
|
53
|
+
STYLE = 13,
|
|
54
|
+
COMMENT = 14,
|
|
55
|
+
CONDITIONAL = 15,
|
|
56
|
+
DIRECTIVE = 16,
|
|
57
|
+
EOF = 17
|
|
58
|
+
}
|
|
59
|
+
interface BaseToken {
|
|
61
60
|
type: TokenType;
|
|
62
61
|
location: Location;
|
|
63
|
-
data?: any;
|
|
64
62
|
}
|
|
63
|
+
interface UnicodeBOMToken extends BaseToken {
|
|
64
|
+
type: TokenType.UNICODE_BOM;
|
|
65
|
+
data: [bom: string];
|
|
66
|
+
}
|
|
67
|
+
interface WhitespaceToken extends BaseToken {
|
|
68
|
+
type: TokenType.WHITESPACE;
|
|
69
|
+
data: [text: string];
|
|
70
|
+
}
|
|
71
|
+
interface DoctypeOpenToken extends BaseToken {
|
|
72
|
+
type: TokenType.DOCTYPE_OPEN;
|
|
73
|
+
data: [text: string, tag: string];
|
|
74
|
+
}
|
|
75
|
+
interface DoctypeValueToken extends BaseToken {
|
|
76
|
+
type: TokenType.DOCTYPE_VALUE;
|
|
77
|
+
data: [text: string];
|
|
78
|
+
}
|
|
79
|
+
interface DoctypeCloseToken extends BaseToken {
|
|
80
|
+
type: TokenType.DOCTYPE_CLOSE;
|
|
81
|
+
data: [text: ">"];
|
|
82
|
+
}
|
|
83
|
+
interface TagOpenToken extends BaseToken {
|
|
84
|
+
type: TokenType.TAG_OPEN;
|
|
85
|
+
data: [text: string, close: "/" | "", tag: string];
|
|
86
|
+
}
|
|
87
|
+
interface TagCloseToken extends BaseToken {
|
|
88
|
+
type: TokenType.TAG_CLOSE;
|
|
89
|
+
data: [text: ">" | "/>"];
|
|
90
|
+
}
|
|
91
|
+
interface AttrNameToken extends BaseToken {
|
|
92
|
+
type: TokenType.ATTR_NAME;
|
|
93
|
+
data: [text: string, name: string];
|
|
94
|
+
}
|
|
95
|
+
interface AttrValueToken extends BaseToken {
|
|
96
|
+
type: TokenType.ATTR_VALUE;
|
|
97
|
+
data: [text: string, delimiter: string, value: string, quote?: '"' | "'"];
|
|
98
|
+
}
|
|
99
|
+
interface TextToken extends BaseToken {
|
|
100
|
+
type: TokenType.TEXT;
|
|
101
|
+
data: [text: string];
|
|
102
|
+
}
|
|
103
|
+
interface TemplatingToken extends BaseToken {
|
|
104
|
+
type: TokenType.TEMPLATING;
|
|
105
|
+
data: [text: string];
|
|
106
|
+
}
|
|
107
|
+
interface ScriptToken extends BaseToken {
|
|
108
|
+
type: TokenType.SCRIPT;
|
|
109
|
+
data: [text: string];
|
|
110
|
+
}
|
|
111
|
+
interface StyleToken extends BaseToken {
|
|
112
|
+
type: TokenType.STYLE;
|
|
113
|
+
data: [text: string];
|
|
114
|
+
}
|
|
115
|
+
interface CommentToken extends BaseToken {
|
|
116
|
+
type: TokenType.COMMENT;
|
|
117
|
+
data: [text: string, comment: string];
|
|
118
|
+
}
|
|
119
|
+
interface ConditionalToken extends BaseToken {
|
|
120
|
+
type: TokenType.CONDITIONAL;
|
|
121
|
+
data: [text: string, condition: string];
|
|
122
|
+
}
|
|
123
|
+
interface DirectiveToken extends BaseToken {
|
|
124
|
+
type: TokenType.DIRECTIVE;
|
|
125
|
+
data: [text: string, begin: "[", action: string, rest: string, end: "]" | ""];
|
|
126
|
+
}
|
|
127
|
+
interface EOFToken extends BaseToken {
|
|
128
|
+
type: TokenType.EOF;
|
|
129
|
+
data: [];
|
|
130
|
+
}
|
|
131
|
+
declare type Token = UnicodeBOMToken | WhitespaceToken | DoctypeOpenToken | DoctypeValueToken | DoctypeCloseToken | TagOpenToken | TagCloseToken | AttrNameToken | AttrValueToken | TextToken | TemplatingToken | ScriptToken | StyleToken | CommentToken | ConditionalToken | DirectiveToken | EOFToken;
|
|
65
132
|
|
|
66
133
|
declare type TokenStream = IterableIterator<Token>;
|
|
67
134
|
|
|
@@ -502,6 +569,8 @@ interface ConditionalEvent extends Event {
|
|
|
502
569
|
location: Location;
|
|
503
570
|
/** Condition including markers. */
|
|
504
571
|
condition: string;
|
|
572
|
+
/** The element containing the conditional, if any. */
|
|
573
|
+
parent: HtmlElement | null;
|
|
505
574
|
}
|
|
506
575
|
/**
|
|
507
576
|
* Event emitted when html-validate directives `<!-- [html-validate-...] -->`
|
|
@@ -625,14 +694,14 @@ declare class Parser {
|
|
|
625
694
|
* stack when is allowed to omit.
|
|
626
695
|
*/
|
|
627
696
|
private closeOptional;
|
|
628
|
-
protected consumeTag(source: Source, startToken:
|
|
697
|
+
protected consumeTag(source: Source, startToken: TagOpenToken, tokenStream: TokenStream): void;
|
|
629
698
|
protected closeElement(source: Source, node: HtmlElement | null, active: HtmlElement, location: Location): void;
|
|
630
699
|
private processElement;
|
|
631
700
|
/**
|
|
632
701
|
* Discard tokens until the end tag for the foreign element is found.
|
|
633
702
|
*/
|
|
634
703
|
protected discardForeignBody(source: Source, foreignTagName: string, tokenStream: TokenStream, errorLocation: Location): void;
|
|
635
|
-
protected consumeAttribute(source: Source, node: HtmlElement, token:
|
|
704
|
+
protected consumeAttribute(source: Source, node: HtmlElement, token: AttrNameToken, next?: Token): void;
|
|
636
705
|
/**
|
|
637
706
|
* Takes attribute key token an returns location.
|
|
638
707
|
*/
|
|
@@ -650,17 +719,24 @@ declare class Parser {
|
|
|
650
719
|
* an aggregate location covering key, quotes if present and value.
|
|
651
720
|
*/
|
|
652
721
|
private getAttributeLocation;
|
|
653
|
-
protected consumeDirective(token:
|
|
722
|
+
protected consumeDirective(token: DirectiveToken): void;
|
|
723
|
+
/**
|
|
724
|
+
* Consumes conditional comment in tag form.
|
|
725
|
+
*
|
|
726
|
+
* See also the related [[consumeCommend]] method.
|
|
727
|
+
*/
|
|
728
|
+
protected consumeConditional(token: ConditionalToken): void;
|
|
654
729
|
/**
|
|
655
730
|
* Consumes comment token.
|
|
656
731
|
*
|
|
657
|
-
* Tries to find IE conditional comments and emits conditional token if
|
|
732
|
+
* Tries to find IE conditional comments and emits conditional token if
|
|
733
|
+
* found. See also the related [[consumeConditional]] method.
|
|
658
734
|
*/
|
|
659
|
-
protected consumeComment(token:
|
|
735
|
+
protected consumeComment(token: CommentToken): void;
|
|
660
736
|
/**
|
|
661
737
|
* Consumes doctype tokens. Emits doctype event.
|
|
662
738
|
*/
|
|
663
|
-
protected consumeDoctype(startToken:
|
|
739
|
+
protected consumeDoctype(startToken: DoctypeOpenToken, tokenStream: TokenStream): void;
|
|
664
740
|
/**
|
|
665
741
|
* Return a list of tokens found until the expected token was found.
|
|
666
742
|
*
|
|
@@ -1145,7 +1221,7 @@ declare class HtmlElement extends DOMNode {
|
|
|
1145
1221
|
/**
|
|
1146
1222
|
* @internal
|
|
1147
1223
|
*/
|
|
1148
|
-
static fromTokens(startToken:
|
|
1224
|
+
static fromTokens(startToken: TagOpenToken, endToken: TagCloseToken, parent: HtmlElement | null, metaTable: MetaTable | null): HtmlElement;
|
|
1149
1225
|
/**
|
|
1150
1226
|
* Returns annotated name if set or defaults to `<tagName>`.
|
|
1151
1227
|
*
|
package/dist/es/core.js
CHANGED
|
@@ -1476,8 +1476,8 @@ class DOMTokenList extends Array {
|
|
|
1476
1476
|
constructor(value, location) {
|
|
1477
1477
|
if (value && typeof value === "string") {
|
|
1478
1478
|
/* replace all whitespace with a single space for easier parsing */
|
|
1479
|
-
const
|
|
1480
|
-
const { tokens, locations } = parse(
|
|
1479
|
+
const normalized = value.replace(/[\t\r\n]/g, " ");
|
|
1480
|
+
const { tokens, locations } = parse(normalized, location);
|
|
1481
1481
|
super(...tokens);
|
|
1482
1482
|
this.locations = locations;
|
|
1483
1483
|
}
|
|
@@ -2945,7 +2945,7 @@ var TRANSFORMER_API;
|
|
|
2945
2945
|
/** @public */
|
|
2946
2946
|
const name = "html-validate";
|
|
2947
2947
|
/** @public */
|
|
2948
|
-
const version = "6.
|
|
2948
|
+
const version = "6.5.0";
|
|
2949
2949
|
/** @public */
|
|
2950
2950
|
const homepage = "https://html-validate.org";
|
|
2951
2951
|
/** @public */
|
|
@@ -2984,6 +2984,42 @@ function parseSeverity(value) {
|
|
|
2984
2984
|
}
|
|
2985
2985
|
}
|
|
2986
2986
|
|
|
2987
|
+
function escape(value) {
|
|
2988
|
+
return value.replace(/'/g, "\\'");
|
|
2989
|
+
}
|
|
2990
|
+
function format(value, quote = false) {
|
|
2991
|
+
if (value === null) {
|
|
2992
|
+
return "null";
|
|
2993
|
+
}
|
|
2994
|
+
if (typeof value === "number") {
|
|
2995
|
+
return value.toString();
|
|
2996
|
+
}
|
|
2997
|
+
if (typeof value === "string") {
|
|
2998
|
+
return quote ? `'${escape(value)}'` : value;
|
|
2999
|
+
}
|
|
3000
|
+
if (Array.isArray(value)) {
|
|
3001
|
+
const content = value.map((it) => format(it, true)).join(", ");
|
|
3002
|
+
return `[ ${content} ]`;
|
|
3003
|
+
}
|
|
3004
|
+
if (typeof value === "object") {
|
|
3005
|
+
const content = Object.entries(value)
|
|
3006
|
+
.map(([key, nested]) => `${key}: ${format(nested, true)}`)
|
|
3007
|
+
.join(", ");
|
|
3008
|
+
return `{ ${content} }`;
|
|
3009
|
+
}
|
|
3010
|
+
return String(value);
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Replaces placeholder `{{ ... }}` with values from given object.
|
|
3014
|
+
*
|
|
3015
|
+
* @internal
|
|
3016
|
+
*/
|
|
3017
|
+
function interpolate(text, data) {
|
|
3018
|
+
return text.replace(/{{\s*([^\s]+)\s*}}/g, (match, key) => {
|
|
3019
|
+
return typeof data[key] !== "undefined" ? format(data[key]) : match;
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
|
|
2987
3023
|
const remapEvents = {
|
|
2988
3024
|
"tag:open": "tag:start",
|
|
2989
3025
|
"tag:close": "tag:end",
|
|
@@ -3118,7 +3154,8 @@ class Rule {
|
|
|
3118
3154
|
report(node, message, location, context) {
|
|
3119
3155
|
if (this.isEnabled() && (!node || node.ruleEnabled(this.name))) {
|
|
3120
3156
|
const where = this.findLocation({ node, location, event: this.event });
|
|
3121
|
-
|
|
3157
|
+
const interpolated = interpolate(message, context !== null && context !== void 0 ? context : {});
|
|
3158
|
+
this.reporter.add(this, interpolated, this.severity, node, where, context);
|
|
3122
3159
|
}
|
|
3123
3160
|
}
|
|
3124
3161
|
findLocation(src) {
|
|
@@ -3225,7 +3262,8 @@ function ruleDocumentationUrl(filename) {
|
|
|
3225
3262
|
const p = path.parse(filename);
|
|
3226
3263
|
const root = path.join(distFolder, "rules");
|
|
3227
3264
|
const rel = path.relative(root, path.join(p.dir, p.name));
|
|
3228
|
-
|
|
3265
|
+
const normalized = rel.replace(/\\/g, "/");
|
|
3266
|
+
return `${homepage}/rules/${normalized}.html`;
|
|
3229
3267
|
}
|
|
3230
3268
|
|
|
3231
3269
|
const defaults$p = {
|
|
@@ -3642,22 +3680,21 @@ var TokenType;
|
|
|
3642
3680
|
(function (TokenType) {
|
|
3643
3681
|
TokenType[TokenType["UNICODE_BOM"] = 1] = "UNICODE_BOM";
|
|
3644
3682
|
TokenType[TokenType["WHITESPACE"] = 2] = "WHITESPACE";
|
|
3645
|
-
TokenType[TokenType["
|
|
3646
|
-
TokenType[TokenType["
|
|
3647
|
-
TokenType[TokenType["
|
|
3648
|
-
TokenType[TokenType["
|
|
3649
|
-
TokenType[TokenType["
|
|
3650
|
-
TokenType[TokenType["
|
|
3651
|
-
TokenType[TokenType["
|
|
3652
|
-
TokenType[TokenType["
|
|
3653
|
-
TokenType[TokenType["
|
|
3654
|
-
TokenType[TokenType["
|
|
3655
|
-
TokenType[TokenType["
|
|
3656
|
-
TokenType[TokenType["
|
|
3657
|
-
TokenType[TokenType["
|
|
3658
|
-
TokenType[TokenType["
|
|
3659
|
-
TokenType[TokenType["
|
|
3660
|
-
TokenType[TokenType["EOF"] = 18] = "EOF";
|
|
3683
|
+
TokenType[TokenType["DOCTYPE_OPEN"] = 3] = "DOCTYPE_OPEN";
|
|
3684
|
+
TokenType[TokenType["DOCTYPE_VALUE"] = 4] = "DOCTYPE_VALUE";
|
|
3685
|
+
TokenType[TokenType["DOCTYPE_CLOSE"] = 5] = "DOCTYPE_CLOSE";
|
|
3686
|
+
TokenType[TokenType["TAG_OPEN"] = 6] = "TAG_OPEN";
|
|
3687
|
+
TokenType[TokenType["TAG_CLOSE"] = 7] = "TAG_CLOSE";
|
|
3688
|
+
TokenType[TokenType["ATTR_NAME"] = 8] = "ATTR_NAME";
|
|
3689
|
+
TokenType[TokenType["ATTR_VALUE"] = 9] = "ATTR_VALUE";
|
|
3690
|
+
TokenType[TokenType["TEXT"] = 10] = "TEXT";
|
|
3691
|
+
TokenType[TokenType["TEMPLATING"] = 11] = "TEMPLATING";
|
|
3692
|
+
TokenType[TokenType["SCRIPT"] = 12] = "SCRIPT";
|
|
3693
|
+
TokenType[TokenType["STYLE"] = 13] = "STYLE";
|
|
3694
|
+
TokenType[TokenType["COMMENT"] = 14] = "COMMENT";
|
|
3695
|
+
TokenType[TokenType["CONDITIONAL"] = 15] = "CONDITIONAL";
|
|
3696
|
+
TokenType[TokenType["DIRECTIVE"] = 16] = "DIRECTIVE";
|
|
3697
|
+
TokenType[TokenType["EOF"] = 17] = "EOF";
|
|
3661
3698
|
})(TokenType || (TokenType = {}));
|
|
3662
3699
|
|
|
3663
3700
|
/* eslint-disable no-useless-escape */
|
|
@@ -3682,7 +3719,7 @@ const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
|
|
|
3682
3719
|
const MATCH_SCRIPT_END = /^<(\/)(script)/;
|
|
3683
3720
|
const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
|
|
3684
3721
|
const MATCH_STYLE_END = /^<(\/)(style)/;
|
|
3685
|
-
const MATCH_DIRECTIVE = /^<!--\s
|
|
3722
|
+
const MATCH_DIRECTIVE = /^<!--\s*(\[)html-validate-([a-z0-9-]+)\s*(.*?)(]?)\s*-->/;
|
|
3686
3723
|
const MATCH_COMMENT = /^<!--([^]*?)-->/;
|
|
3687
3724
|
const MATCH_CONDITIONAL = /^<!\[([^\]]*?)\]>/;
|
|
3688
3725
|
class InvalidTokenError extends Error {
|
|
@@ -3737,15 +3774,15 @@ class Lexer {
|
|
|
3737
3774
|
previousState = context.state;
|
|
3738
3775
|
previousLength = context.string.length;
|
|
3739
3776
|
}
|
|
3740
|
-
yield this.token(context, TokenType.EOF);
|
|
3777
|
+
yield this.token(context, TokenType.EOF, []);
|
|
3741
3778
|
}
|
|
3742
3779
|
token(context, type, data) {
|
|
3743
|
-
const size = data ? data[0].length : 0;
|
|
3780
|
+
const size = data.length > 0 ? data[0].length : 0;
|
|
3744
3781
|
const location = context.getLocation(size);
|
|
3745
3782
|
return {
|
|
3746
3783
|
type,
|
|
3747
3784
|
location,
|
|
3748
|
-
data:
|
|
3785
|
+
data: Array.from(data),
|
|
3749
3786
|
};
|
|
3750
3787
|
}
|
|
3751
3788
|
/* istanbul ignore next: used to provide a better error when an unhandled state happens */
|
|
@@ -3770,17 +3807,18 @@ class Lexer {
|
|
|
3770
3807
|
}
|
|
3771
3808
|
}
|
|
3772
3809
|
*match(context, tests, error) {
|
|
3773
|
-
let match = null;
|
|
3774
3810
|
const n = tests.length;
|
|
3775
3811
|
for (let i = 0; i < n; i++) {
|
|
3776
3812
|
const [regex, nextState, tokenType] = tests[i];
|
|
3777
|
-
|
|
3813
|
+
const match = regex ? context.string.match(regex) : [""];
|
|
3814
|
+
if (match) {
|
|
3778
3815
|
let token = null;
|
|
3779
3816
|
if (tokenType !== false) {
|
|
3780
|
-
|
|
3817
|
+
token = this.token(context, tokenType, match);
|
|
3818
|
+
yield token;
|
|
3781
3819
|
}
|
|
3782
3820
|
const state = this.evalNextState(nextState, token);
|
|
3783
|
-
context.consume(match
|
|
3821
|
+
context.consume(match, state);
|
|
3784
3822
|
this.enter(context, state, match);
|
|
3785
3823
|
return;
|
|
3786
3824
|
}
|
|
@@ -3827,18 +3865,19 @@ class Lexer {
|
|
|
3827
3865
|
*tokenizeTag(context) {
|
|
3828
3866
|
/* eslint-disable-next-line consistent-return -- exhaustive switch handled by typescript */
|
|
3829
3867
|
function nextState(token) {
|
|
3868
|
+
const tagCloseToken = token;
|
|
3830
3869
|
switch (context.contentModel) {
|
|
3831
3870
|
case ContentModel.TEXT:
|
|
3832
3871
|
return State.TEXT;
|
|
3833
3872
|
case ContentModel.SCRIPT:
|
|
3834
|
-
if (
|
|
3873
|
+
if (tagCloseToken && tagCloseToken.data[0][0] !== "/") {
|
|
3835
3874
|
return State.SCRIPT;
|
|
3836
3875
|
}
|
|
3837
3876
|
else {
|
|
3838
3877
|
return State.TEXT; /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
|
|
3839
3878
|
}
|
|
3840
3879
|
case ContentModel.STYLE:
|
|
3841
|
-
if (
|
|
3880
|
+
if (tagCloseToken && tagCloseToken.data[0][0] !== "/") {
|
|
3842
3881
|
return State.STYLE;
|
|
3843
3882
|
}
|
|
3844
3883
|
else {
|
|
@@ -5986,7 +6025,7 @@ class NoConditionalComment extends Rule {
|
|
|
5986
6025
|
}
|
|
5987
6026
|
setup() {
|
|
5988
6027
|
this.on("conditional", (event) => {
|
|
5989
|
-
this.report(
|
|
6028
|
+
this.report(event.parent, "Use of conditional comments are deprecated", event.location);
|
|
5990
6029
|
});
|
|
5991
6030
|
}
|
|
5992
6031
|
}
|
|
@@ -9759,7 +9798,9 @@ class ResolvedConfig {
|
|
|
9759
9798
|
* @returns A list of transformed sources ready for validation.
|
|
9760
9799
|
*/
|
|
9761
9800
|
transformFilename(filename) {
|
|
9762
|
-
const
|
|
9801
|
+
const stdin = 0;
|
|
9802
|
+
const src = filename !== "/dev/stdin" ? filename : stdin;
|
|
9803
|
+
const data = fs.readFileSync(src, { encoding: "utf8" });
|
|
9763
9804
|
const source = {
|
|
9764
9805
|
data,
|
|
9765
9806
|
filename,
|
|
@@ -10410,6 +10451,9 @@ class ParserError extends Error {
|
|
|
10410
10451
|
}
|
|
10411
10452
|
}
|
|
10412
10453
|
|
|
10454
|
+
function isAttrValueToken(token) {
|
|
10455
|
+
return Boolean(token && token.type === TokenType.ATTR_VALUE);
|
|
10456
|
+
}
|
|
10413
10457
|
/**
|
|
10414
10458
|
* Parse HTML document into a DOM tree.
|
|
10415
10459
|
*
|
|
@@ -10481,10 +10525,7 @@ class Parser {
|
|
|
10481
10525
|
this.consumeDirective(token);
|
|
10482
10526
|
break;
|
|
10483
10527
|
case TokenType.CONDITIONAL:
|
|
10484
|
-
this.
|
|
10485
|
-
condition: token.data[1],
|
|
10486
|
-
location: token.location,
|
|
10487
|
-
});
|
|
10528
|
+
this.consumeConditional(token);
|
|
10488
10529
|
break;
|
|
10489
10530
|
case TokenType.COMMENT:
|
|
10490
10531
|
this.consumeComment(token);
|
|
@@ -10494,7 +10535,7 @@ class Parser {
|
|
|
10494
10535
|
break;
|
|
10495
10536
|
case TokenType.TEXT:
|
|
10496
10537
|
case TokenType.TEMPLATING:
|
|
10497
|
-
this.appendText(token.data, token.location);
|
|
10538
|
+
this.appendText(token.data[0], token.location);
|
|
10498
10539
|
break;
|
|
10499
10540
|
case TokenType.EOF:
|
|
10500
10541
|
this.closeTree(source, token.location);
|
|
@@ -10689,15 +10730,15 @@ class Parser {
|
|
|
10689
10730
|
const keyLocation = this.getAttributeKeyLocation(token);
|
|
10690
10731
|
const valueLocation = this.getAttributeValueLocation(next);
|
|
10691
10732
|
const location = this.getAttributeLocation(token, next);
|
|
10692
|
-
const haveValue = next
|
|
10733
|
+
const haveValue = isAttrValueToken(next);
|
|
10693
10734
|
const attrData = {
|
|
10694
10735
|
key: token.data[1],
|
|
10695
10736
|
value: null,
|
|
10696
10737
|
quote: null,
|
|
10697
10738
|
};
|
|
10698
|
-
if (
|
|
10739
|
+
if (haveValue) {
|
|
10699
10740
|
const [, , value, quote] = next.data;
|
|
10700
|
-
attrData.value = value
|
|
10741
|
+
attrData.value = value;
|
|
10701
10742
|
attrData.quote = quote !== null && quote !== void 0 ? quote : null;
|
|
10702
10743
|
}
|
|
10703
10744
|
/* get callback to process attributes, default is to just return attribute
|
|
@@ -10776,12 +10817,16 @@ class Parser {
|
|
|
10776
10817
|
};
|
|
10777
10818
|
}
|
|
10778
10819
|
consumeDirective(token) {
|
|
10779
|
-
const directive = token.data
|
|
10780
|
-
|
|
10820
|
+
const [text, , action, directive, end] = token.data;
|
|
10821
|
+
if (end === "") {
|
|
10822
|
+
throw new Error(`Missing end bracket "]" on directive "${text}"`);
|
|
10823
|
+
}
|
|
10824
|
+
const match = directive.match(/^(.*?)(?:\s*(?:--|:)\s*(.*))?$/);
|
|
10825
|
+
/* istanbul ignore next: should not be possible, would be emitted as comment token */
|
|
10781
10826
|
if (!match) {
|
|
10782
|
-
throw new Error(`Failed to parse directive "${
|
|
10827
|
+
throw new Error(`Failed to parse directive "${text}"`);
|
|
10783
10828
|
}
|
|
10784
|
-
const [,
|
|
10829
|
+
const [, data, comment] = match;
|
|
10785
10830
|
this.trigger("directive", {
|
|
10786
10831
|
action,
|
|
10787
10832
|
data,
|
|
@@ -10789,17 +10834,33 @@ class Parser {
|
|
|
10789
10834
|
location: token.location,
|
|
10790
10835
|
});
|
|
10791
10836
|
}
|
|
10837
|
+
/**
|
|
10838
|
+
* Consumes conditional comment in tag form.
|
|
10839
|
+
*
|
|
10840
|
+
* See also the related [[consumeCommend]] method.
|
|
10841
|
+
*/
|
|
10842
|
+
consumeConditional(token) {
|
|
10843
|
+
const element = this.dom.getActive();
|
|
10844
|
+
this.trigger("conditional", {
|
|
10845
|
+
condition: token.data[1],
|
|
10846
|
+
location: token.location,
|
|
10847
|
+
parent: element,
|
|
10848
|
+
});
|
|
10849
|
+
}
|
|
10792
10850
|
/**
|
|
10793
10851
|
* Consumes comment token.
|
|
10794
10852
|
*
|
|
10795
|
-
* Tries to find IE conditional comments and emits conditional token if
|
|
10853
|
+
* Tries to find IE conditional comments and emits conditional token if
|
|
10854
|
+
* found. See also the related [[consumeConditional]] method.
|
|
10796
10855
|
*/
|
|
10797
10856
|
consumeComment(token) {
|
|
10798
10857
|
const comment = token.data[0];
|
|
10858
|
+
const element = this.dom.getActive();
|
|
10799
10859
|
for (const conditional of parseConditionalComment(comment, token.location)) {
|
|
10800
10860
|
this.trigger("conditional", {
|
|
10801
10861
|
condition: conditional.expression,
|
|
10802
10862
|
location: conditional.location,
|
|
10863
|
+
parent: element,
|
|
10803
10864
|
});
|
|
10804
10865
|
}
|
|
10805
10866
|
}
|
|
@@ -10808,7 +10869,8 @@ class Parser {
|
|
|
10808
10869
|
*/
|
|
10809
10870
|
consumeDoctype(startToken, tokenStream) {
|
|
10810
10871
|
const tokens = Array.from(this.consumeUntil(tokenStream, TokenType.DOCTYPE_CLOSE, startToken.location));
|
|
10811
|
-
|
|
10872
|
+
/* first token is the doctype, second is the closing ">" */
|
|
10873
|
+
const doctype = tokens[0];
|
|
10812
10874
|
const value = doctype.data[0];
|
|
10813
10875
|
this.dom.doctype = value;
|
|
10814
10876
|
this.trigger("doctype", {
|
|
@@ -10841,7 +10903,7 @@ class Parser {
|
|
|
10841
10903
|
this.trigger("token", {
|
|
10842
10904
|
location: token.location,
|
|
10843
10905
|
type: token.type,
|
|
10844
|
-
data:
|
|
10906
|
+
data: Array.from(token.data),
|
|
10845
10907
|
});
|
|
10846
10908
|
}
|
|
10847
10909
|
return it;
|
|
@@ -11101,11 +11163,12 @@ class Engine {
|
|
|
11101
11163
|
return lines;
|
|
11102
11164
|
}
|
|
11103
11165
|
dumpTokens(source) {
|
|
11166
|
+
var _a;
|
|
11104
11167
|
const lexer = new Lexer();
|
|
11105
11168
|
const lines = [];
|
|
11106
11169
|
for (const src of source) {
|
|
11107
11170
|
for (const token of lexer.tokenize(src)) {
|
|
11108
|
-
const data =
|
|
11171
|
+
const data = (_a = token.data[0]) !== null && _a !== void 0 ? _a : "";
|
|
11109
11172
|
lines.push({
|
|
11110
11173
|
token: TokenType[token.type],
|
|
11111
11174
|
data,
|