htmljs-parser 3.3.6 → 5.0.1

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/README.md CHANGED
@@ -155,20 +155,29 @@ const parser = createParser({
155
155
  range.value; // Another range that includes only the value itself without the leading $ or surrounding braces (if applicable).
156
156
  },
157
157
 
158
+ /**
159
+ * Called when we're about to begin an HTML open tag (before the tag name).
160
+ * Note: This is only called for HTML mode tags and can be used to track if you are in concise mode.
161
+ *
162
+ * @example
163
+ * 1╭─ <div>Hi</div>
164
+ * ╰─ ╰─ openTagStart
165
+ */
166
+ onOpenTagStart(range) {}
167
+
158
168
  /**
159
169
  * Called when a tag name, which can include placeholders, has been parsed.
160
170
  *
161
171
  * @example
162
172
  * 1╭─ <div/>
163
- * ╰─ ╰─ tagName "div"
173
+ * ╰─ ╰─ openTagName "div"
164
174
  * 2╭─ <hello-${test}-again/>
165
- * │ │ │ ╰─ tagName.quasis[1] "-again"
166
- * │ │ ╰─ tagName.expressions[0] "${test}"
167
- * │ ├─ tagName.quasis[0] "hello-"
168
- * ╰─ ╰─ tagName "hello-${test}-again"
175
+ * │ │ │ ╰─ openTagName.quasis[1] "-again"
176
+ * │ │ ╰─ openTagName.expressions[0] "${test}"
177
+ * │ ├─ openTagName.quasis[0] "hello-"
178
+ * ╰─ ╰─ openTagName "hello-${test}-again"
169
179
  */
170
- onTagName(range) {
171
- range.concise; // true if this tag is a concise mode tag.
180
+ onOpenTagName(range) {
172
181
  range.quasis; // An array of ranges that indicate the string literal parts of the tag name.
173
182
  range.expressions; // A list of placeholder ranges (similar to whats emitted via onPlaceholder).
174
183
 
@@ -353,21 +362,38 @@ const parser = createParser({
353
362
  * ╰─ ╰─ openTagEnd ">"
354
363
  */
355
364
  onOpenTagEnd(range) {
356
- range.selfClosed; // true if this tag was self closed (onCloseTag would not be called if so).
365
+ range.selfClosed; // true if this tag was self closed (the onCloseTag* handlers will not be called if so).
357
366
  },
358
367
 
359
368
  /**
360
- * Called once the closing tag (or in concise mode an outdent or eof) is parsed.
369
+ * Called when we start parsing and html closing tag.
370
+ * Note this is not emitted for concise, selfClosed, void or statement tags.
371
+ *
372
+ * @example
373
+ * 1╭─ <div><span/></div>
374
+ * ╰─ ╰─ closeTagStart "</"
375
+ */
376
+ onCloseTagStart(range) {},
377
+
378
+ /**
379
+ * Called after the content within the brackets of an html closing tag has been parsed.
380
+ * Note this is not emitted for concise, selfClosed, void or statement tags.
381
+ *
382
+ * @example
383
+ * 1╭─ <div><span/></div>
384
+ * ╰─ ╰─ closeTagName "div"
385
+ */
386
+ onCloseTagName(range) {},
387
+
388
+ /**
389
+ * Called once the closing tag has finished parsing, or in concise mode we hit an outdent or eof.
361
390
  * Note this is not called for selfClosed, void or statement tags.
362
391
  *
363
392
  * @example
364
393
  * 1╭─ <div><span/></div>
365
- * │ │ ╰─ closeTag(div).value "div"
366
- * ╰─ ╰─ closeTag(div) "</div>"
394
+ * ╰─ ╰─ closeTagEnd ">"
367
395
  */
368
- onCloseTag(range) {
369
- range.value; // The raw content of the closing tag (undefined in concise mode).
370
- },
396
+ onCloseTagEnd(range) {},
371
397
  });
372
398
  ```
373
399
 
@@ -57,7 +57,7 @@ export declare class Parser {
57
57
  */
58
58
  beginHtmlBlock(delimiter: string | undefined, singleLine: boolean): void;
59
59
  emitError(range: number | Range, code: ErrorCode, message: string): void;
60
- closeTag(start: number, end: number, value: Range | undefined): void;
60
+ closeTagEnd(start: number, end: number, name: Range | undefined): void;
61
61
  consumeWhitespaceIfBefore(str: string, start?: number): boolean;
62
62
  getPreviousNonWhitespaceCharCode(start?: number): number;
63
63
  onlyWhitespaceRemainsOnLine(start?: number): boolean;
package/dist/index.js CHANGED
@@ -89,10 +89,10 @@ function getPos(lines, startLine, index) {
89
89
  };
90
90
  }
91
91
  function getLines(src) {
92
- const lines = [-1];
92
+ const lines = [0];
93
93
  for (let i = 0; i < src.length; i++) {
94
94
  if (src.charCodeAt(i) === 10 /* NEWLINE */) {
95
- lines.push(i);
95
+ lines.push(i + 1);
96
96
  }
97
97
  }
98
98
  return lines;
@@ -101,7 +101,7 @@ function htmlEOF() {
101
101
  this.endText();
102
102
  while (this.activeTag) {
103
103
  if (this.activeTag.concise) {
104
- this.closeTag(this.pos, this.pos, void 0);
104
+ this.closeTagEnd(this.pos, this.pos, void 0);
105
105
  } else {
106
106
  return this.emitError(this.activeTag, 22 /* MISSING_END_TAG */, 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag');
107
107
  }
@@ -231,17 +231,15 @@ var Parser = class {
231
231
  });
232
232
  this.pos = this.maxPos + 1;
233
233
  }
234
- closeTag(start, end, value) {
235
- var _a, _b;
234
+ closeTagEnd(start, end, name) {
235
+ var _a, _b, _c, _d;
236
236
  const { beginMixedMode, parentTag } = this.activeTag;
237
237
  if (beginMixedMode)
238
238
  this.endingMixedModeAtEOL = true;
239
239
  this.activeTag = parentTag;
240
- (_b = (_a = this.options).onCloseTag) == null ? void 0 : _b.call(_a, {
241
- start,
242
- end,
243
- value
244
- });
240
+ if (name)
241
+ (_b = (_a = this.options).onCloseTagName) == null ? void 0 : _b.call(_a, name);
242
+ (_d = (_c = this.options).onCloseTagEnd) == null ? void 0 : _d.call(_c, { start, end });
245
243
  }
246
244
  consumeWhitespaceIfBefore(str, start = 0) {
247
245
  const { pos, data } = this;
@@ -729,6 +727,7 @@ var CLOSE_TAG = {
729
727
  }
730
728
  };
731
729
  function checkForClosingTag(parser) {
730
+ var _a, _b;
732
731
  const curPos = parser.pos + 1;
733
732
  let match = !!parser.lookAheadFor("/>");
734
733
  let skip = 3;
@@ -745,6 +744,10 @@ function checkForClosingTag(parser) {
745
744
  }
746
745
  if (match) {
747
746
  parser.endText();
747
+ (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
748
+ start: curPos - 1,
749
+ end: curPos + 1
750
+ });
748
751
  if (ensureExpectedCloseTag(parser, {
749
752
  start: parser.pos,
750
753
  end: parser.pos += skip
@@ -778,7 +781,7 @@ function ensureExpectedCloseTag(parser, closeTag) {
778
781
  }
779
782
  }
780
783
  }
781
- parser.closeTag(closeTag.start, closeTag.end, closeTagNamePos);
784
+ parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
782
785
  return true;
783
786
  }
784
787
 
@@ -805,7 +808,7 @@ var CONCISE_HTML_CONTENT = {
805
808
  const indentStart = this.pos - curIndent - 1;
806
809
  let parentTag = this.activeTag;
807
810
  while (parentTag && parentTag.indent.length >= curIndent) {
808
- this.closeTag(indentStart, indentStart, void 0);
811
+ this.closeTagEnd(indentStart, indentStart, void 0);
809
812
  parentTag = this.activeTag;
810
813
  }
811
814
  if (!parentTag && curIndent) {
@@ -1210,6 +1213,7 @@ var HTML_CONTENT = {
1210
1213
  exit() {
1211
1214
  },
1212
1215
  char(code) {
1216
+ var _a, _b, _c, _d;
1213
1217
  if (code === 60 /* OPEN_ANGLE_BRACKET */) {
1214
1218
  if (states_exports.checkForCDATA(this))
1215
1219
  return;
@@ -1226,11 +1230,19 @@ var HTML_CONTENT = {
1226
1230
  this.enterState(states_exports.DECLARATION);
1227
1231
  this.pos++;
1228
1232
  } else if (nextCode === 47 /* FORWARD_SLASH */) {
1233
+ (_b = (_a = this.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
1234
+ start: this.pos,
1235
+ end: this.pos + 2
1236
+ });
1229
1237
  this.enterState(states_exports.CLOSE_TAG);
1230
1238
  this.pos++;
1231
1239
  } else if (nextCode === 62 /* CLOSE_ANGLE_BRACKET */ || nextCode === 60 /* OPEN_ANGLE_BRACKET */ || isWhitespaceCode(nextCode)) {
1232
1240
  this.startText();
1233
1241
  } else {
1242
+ (_d = (_c = this.options).onOpenTagStart) == null ? void 0 : _d.call(_c, {
1243
+ start: this.pos,
1244
+ end: this.pos + 1
1245
+ });
1234
1246
  this.enterState(states_exports.OPEN_TAG);
1235
1247
  }
1236
1248
  } else if (code === 36 /* DOLLAR */ && isWhitespaceCode(this.lookAtCharCodeAhead(1)) && isBeginningOfLine(this)) {
@@ -1632,12 +1644,11 @@ var TAG_NAME = {
1632
1644
  break;
1633
1645
  default: {
1634
1646
  const tag = this.activeTag;
1635
- const tagType = (_f = (_e = this.options).onTagName) == null ? void 0 : _f.call(_e, {
1647
+ const tagType = (_f = (_e = this.options).onOpenTagName) == null ? void 0 : _f.call(_e, {
1636
1648
  start,
1637
1649
  end,
1638
1650
  quasis,
1639
- expressions,
1640
- concise: this.isConcise
1651
+ expressions
1641
1652
  });
1642
1653
  tag.tagName = tagName;
1643
1654
  if (tagType) {
package/dist/index.mjs CHANGED
@@ -68,10 +68,10 @@ function getPos(lines, startLine, index) {
68
68
  };
69
69
  }
70
70
  function getLines(src) {
71
- const lines = [-1];
71
+ const lines = [0];
72
72
  for (let i = 0; i < src.length; i++) {
73
73
  if (src.charCodeAt(i) === 10 /* NEWLINE */) {
74
- lines.push(i);
74
+ lines.push(i + 1);
75
75
  }
76
76
  }
77
77
  return lines;
@@ -80,7 +80,7 @@ function htmlEOF() {
80
80
  this.endText();
81
81
  while (this.activeTag) {
82
82
  if (this.activeTag.concise) {
83
- this.closeTag(this.pos, this.pos, void 0);
83
+ this.closeTagEnd(this.pos, this.pos, void 0);
84
84
  } else {
85
85
  return this.emitError(this.activeTag, 22 /* MISSING_END_TAG */, 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag');
86
86
  }
@@ -210,17 +210,15 @@ var Parser = class {
210
210
  });
211
211
  this.pos = this.maxPos + 1;
212
212
  }
213
- closeTag(start, end, value) {
214
- var _a, _b;
213
+ closeTagEnd(start, end, name) {
214
+ var _a, _b, _c, _d;
215
215
  const { beginMixedMode, parentTag } = this.activeTag;
216
216
  if (beginMixedMode)
217
217
  this.endingMixedModeAtEOL = true;
218
218
  this.activeTag = parentTag;
219
- (_b = (_a = this.options).onCloseTag) == null ? void 0 : _b.call(_a, {
220
- start,
221
- end,
222
- value
223
- });
219
+ if (name)
220
+ (_b = (_a = this.options).onCloseTagName) == null ? void 0 : _b.call(_a, name);
221
+ (_d = (_c = this.options).onCloseTagEnd) == null ? void 0 : _d.call(_c, { start, end });
224
222
  }
225
223
  consumeWhitespaceIfBefore(str, start = 0) {
226
224
  const { pos, data } = this;
@@ -708,6 +706,7 @@ var CLOSE_TAG = {
708
706
  }
709
707
  };
710
708
  function checkForClosingTag(parser) {
709
+ var _a, _b;
711
710
  const curPos = parser.pos + 1;
712
711
  let match = !!parser.lookAheadFor("/>");
713
712
  let skip = 3;
@@ -724,6 +723,10 @@ function checkForClosingTag(parser) {
724
723
  }
725
724
  if (match) {
726
725
  parser.endText();
726
+ (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
727
+ start: curPos - 1,
728
+ end: curPos + 1
729
+ });
727
730
  if (ensureExpectedCloseTag(parser, {
728
731
  start: parser.pos,
729
732
  end: parser.pos += skip
@@ -757,7 +760,7 @@ function ensureExpectedCloseTag(parser, closeTag) {
757
760
  }
758
761
  }
759
762
  }
760
- parser.closeTag(closeTag.start, closeTag.end, closeTagNamePos);
763
+ parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
761
764
  return true;
762
765
  }
763
766
 
@@ -784,7 +787,7 @@ var CONCISE_HTML_CONTENT = {
784
787
  const indentStart = this.pos - curIndent - 1;
785
788
  let parentTag = this.activeTag;
786
789
  while (parentTag && parentTag.indent.length >= curIndent) {
787
- this.closeTag(indentStart, indentStart, void 0);
790
+ this.closeTagEnd(indentStart, indentStart, void 0);
788
791
  parentTag = this.activeTag;
789
792
  }
790
793
  if (!parentTag && curIndent) {
@@ -1189,6 +1192,7 @@ var HTML_CONTENT = {
1189
1192
  exit() {
1190
1193
  },
1191
1194
  char(code) {
1195
+ var _a, _b, _c, _d;
1192
1196
  if (code === 60 /* OPEN_ANGLE_BRACKET */) {
1193
1197
  if (states_exports.checkForCDATA(this))
1194
1198
  return;
@@ -1205,11 +1209,19 @@ var HTML_CONTENT = {
1205
1209
  this.enterState(states_exports.DECLARATION);
1206
1210
  this.pos++;
1207
1211
  } else if (nextCode === 47 /* FORWARD_SLASH */) {
1212
+ (_b = (_a = this.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
1213
+ start: this.pos,
1214
+ end: this.pos + 2
1215
+ });
1208
1216
  this.enterState(states_exports.CLOSE_TAG);
1209
1217
  this.pos++;
1210
1218
  } else if (nextCode === 62 /* CLOSE_ANGLE_BRACKET */ || nextCode === 60 /* OPEN_ANGLE_BRACKET */ || isWhitespaceCode(nextCode)) {
1211
1219
  this.startText();
1212
1220
  } else {
1221
+ (_d = (_c = this.options).onOpenTagStart) == null ? void 0 : _d.call(_c, {
1222
+ start: this.pos,
1223
+ end: this.pos + 1
1224
+ });
1213
1225
  this.enterState(states_exports.OPEN_TAG);
1214
1226
  }
1215
1227
  } else if (code === 36 /* DOLLAR */ && isWhitespaceCode(this.lookAtCharCodeAhead(1)) && isBeginningOfLine(this)) {
@@ -1611,12 +1623,11 @@ var TAG_NAME = {
1611
1623
  break;
1612
1624
  default: {
1613
1625
  const tag = this.activeTag;
1614
- const tagType = (_f = (_e = this.options).onTagName) == null ? void 0 : _f.call(_e, {
1626
+ const tagType = (_f = (_e = this.options).onOpenTagName) == null ? void 0 : _f.call(_e, {
1615
1627
  start,
1616
1628
  end,
1617
1629
  quasis,
1618
- expressions,
1619
- concise: this.isConcise
1630
+ expressions
1620
1631
  });
1621
1632
  tag.tagName = tagName;
1622
1633
  if (tagType) {
@@ -79,9 +79,6 @@ export declare namespace Ranges {
79
79
  interface Placeholder extends Value {
80
80
  escape: boolean;
81
81
  }
82
- interface TagName extends Template {
83
- concise: boolean;
84
- }
85
82
  interface AttrValue extends Value {
86
83
  bound: boolean;
87
84
  }
@@ -92,9 +89,6 @@ export declare namespace Ranges {
92
89
  interface OpenTagEnd extends Range {
93
90
  selfClosed: boolean;
94
91
  }
95
- interface CloseTag extends Range {
96
- value: Range | undefined;
97
- }
98
92
  }
99
93
  export declare enum ErrorCode {
100
94
  EXTRA_CLOSING_TAG = 0,
@@ -139,7 +133,8 @@ export interface ParserOptions {
139
133
  onDeclaration?(data: Ranges.Value): void;
140
134
  onDoctype?(data: Ranges.Value): void;
141
135
  onScriptlet?(data: Ranges.Scriptlet): void;
142
- onTagName?(data: Ranges.TagName): TagType | void;
136
+ onOpenTagStart?(data: Range): void;
137
+ onOpenTagName?(data: Ranges.Template): TagType | void;
143
138
  onTagShorthandId?(data: Ranges.Template): void;
144
139
  onTagShorthandClass?(data: Ranges.Template): void;
145
140
  onTagVar?(data: Ranges.Value): void;
@@ -151,5 +146,7 @@ export interface ParserOptions {
151
146
  onAttrMethod?(data: Ranges.AttrMethod): void;
152
147
  onAttrSpread?(data: Ranges.Value): void;
153
148
  onOpenTagEnd?(data: Ranges.OpenTagEnd): void;
154
- onCloseTag?(data: Ranges.CloseTag): void;
149
+ onCloseTagStart?(data: Range): void;
150
+ onCloseTagName?(data: Range): void;
151
+ onCloseTagEnd?(data: Range): void;
155
152
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "htmljs-parser",
3
3
  "description": "An HTML parser recognizes content and string placeholders and allows JavaScript expressions as attribute values",
4
- "version": "3.3.6",
4
+ "version": "5.0.1",
5
5
  "devDependencies": {
6
6
  "@changesets/changelog-github": "^0.4.4",
7
7
  "@changesets/cli": "^2.22.0",