@html-eslint/eslint-plugin 0.26.0 → 0.27.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.
@@ -7,7 +7,12 @@ module.exports = {
7
7
  "@html-eslint/no-multiple-h1": "error",
8
8
  "@html-eslint/no-extra-spacing-attrs": "error",
9
9
  "@html-eslint/attrs-newline": "error",
10
- "@html-eslint/element-newline": "error",
10
+ "@html-eslint/element-newline": [
11
+ "error",
12
+ {
13
+ inline: [`$inline`],
14
+ },
15
+ ],
11
16
  "@html-eslint/no-duplicate-id": "error",
12
17
  "@html-eslint/indent": "error",
13
18
  "@html-eslint/require-li-container": "error",
@@ -3,13 +3,66 @@
3
3
  * @typedef { import("../types").ProgramNode } ProgramNode
4
4
  * @typedef { import("../types").TagNode } TagNode
5
5
  * @typedef { import("../types").BaseNode } BaseNode
6
+ * @typedef { import("../types").CommentNode } CommentNode
7
+ * @typedef { import("../types").DoctypeNode } DoctypeNode
8
+ * @typedef { import("../types").ScriptTagNode } ScriptTagNode
9
+ * @typedef { import("../types").StyleTagNode } StyleTagNode
10
+ * @typedef { import("../types").TextNode } TextNode
11
+ * @typedef { CommentNode | DoctypeNode | ScriptTagNode | StyleTagNode | TagNode | TextNode } NewlineNode
12
+ * @typedef {{
13
+ * childFirst: NewlineNode | null;
14
+ * childLast: NewlineNode | null;
15
+ * shouldBeNewline: boolean;
16
+ * }} NodeMeta
6
17
  */
7
18
 
8
19
  const { RULE_CATEGORY } = require("../constants");
9
20
 
10
21
  const MESSAGE_IDS = {
11
22
  EXPECT_NEW_LINE_AFTER: "expectAfter",
23
+ EXPECT_NEW_LINE_AFTER_OPEN: "expectAfterOpen",
12
24
  EXPECT_NEW_LINE_BEFORE: "expectBefore",
25
+ EXPECT_NEW_LINE_BEFORE_CLOSE: "expectBeforeClose",
26
+ };
27
+
28
+ /**
29
+ * @type {Object.<string, Array<string>>}
30
+ */
31
+ const PRESETS = {
32
+ // From https://developer.mozilla.org/en-US/docs/Web/HTML/Element#inline_text_semantics
33
+ $inline: `
34
+ a
35
+ abbr
36
+ b
37
+ bdi
38
+ bdo
39
+ br
40
+ cite
41
+ code
42
+ data
43
+ dfn
44
+ em
45
+ i
46
+ kbd
47
+ mark
48
+ q
49
+ rp
50
+ rt
51
+ ruby
52
+ s
53
+ samp
54
+ small
55
+ span
56
+ strong
57
+ sub
58
+ sup
59
+ time
60
+ u
61
+ var
62
+ wbr
63
+ `
64
+ .trim()
65
+ .split(`\n`),
13
66
  };
14
67
 
15
68
  /**
@@ -30,6 +83,13 @@ module.exports = {
30
83
  {
31
84
  type: "object",
32
85
  properties: {
86
+ inline: {
87
+ type: "array",
88
+ items: {
89
+ type: "string",
90
+ },
91
+ },
92
+
33
93
  skip: {
34
94
  type: "array",
35
95
  items: {
@@ -41,111 +101,214 @@ module.exports = {
41
101
  ],
42
102
  messages: {
43
103
  [MESSAGE_IDS.EXPECT_NEW_LINE_AFTER]:
44
- "There should be a linebreak after {{tag}}.",
104
+ "There should be a linebreak after {{tag}} element.",
105
+ [MESSAGE_IDS.EXPECT_NEW_LINE_AFTER_OPEN]:
106
+ "There should be a linebreak after {{tag}} open.",
45
107
  [MESSAGE_IDS.EXPECT_NEW_LINE_BEFORE]:
46
- "There should be a linebreak before {{tag}}.",
108
+ "There should be a linebreak before {{tag}} element.",
109
+ [MESSAGE_IDS.EXPECT_NEW_LINE_BEFORE_CLOSE]:
110
+ "There should be a linebreak before {{tag}} close.",
47
111
  },
48
112
  },
49
113
 
50
114
  create(context) {
51
- const option = context.options[0] || { skip: [] };
52
- const skipTags = option.skip;
53
- let skipTagCount = 0;
115
+ const option = context.options[0] || {};
116
+ const skipTags = option.skip || [];
117
+ const inlineTags = optionsOrPresets(option.inline || []);
118
+
54
119
  /**
55
- * @param {import("../types").ChildType<TagNode | ProgramNode>[]} siblings
120
+ * @param {Array<NewlineNode>} siblings
121
+ * @returns {NodeMeta} meta
56
122
  */
57
123
  function checkSiblings(siblings) {
58
- siblings
59
- .filter((node) => node.type !== "Text")
60
- .forEach((current, index, arr) => {
61
- const after = arr[index + 1];
62
- if (after) {
63
- if (isOnTheSameLine(current, after)) {
124
+ /**
125
+ * @type {NodeMeta}
126
+ */
127
+ const meta = {
128
+ childFirst: null,
129
+ childLast: null,
130
+ shouldBeNewline: false,
131
+ };
132
+
133
+ const nodesWithContent = [];
134
+ for (
135
+ let length = siblings.length, index = 0;
136
+ index < length;
137
+ index += 1
138
+ ) {
139
+ const node = siblings[index];
140
+
141
+ if (isEmptyText(node) === false) {
142
+ nodesWithContent.push(node);
143
+ }
144
+ }
145
+
146
+ for (
147
+ let length = nodesWithContent.length, index = 0;
148
+ index < length;
149
+ index += 1
150
+ ) {
151
+ const node = nodesWithContent[index];
152
+ const nodeNext = nodesWithContent[index + 1];
153
+
154
+ if (meta.childFirst === null) {
155
+ meta.childFirst = node;
156
+ }
157
+
158
+ meta.childLast = node;
159
+
160
+ const nodeShouldBeNewline = shouldBeNewline(node);
161
+
162
+ if (node.type === `Tag` && skipTags.includes(node.name) === false) {
163
+ const nodeMeta = checkSiblings(node.children);
164
+ const nodeChildShouldBeNewline = nodeMeta.shouldBeNewline;
165
+
166
+ if (nodeShouldBeNewline || nodeChildShouldBeNewline) {
167
+ meta.shouldBeNewline = true;
168
+ }
169
+
170
+ if (
171
+ nodeShouldBeNewline &&
172
+ nodeChildShouldBeNewline &&
173
+ nodeMeta.childFirst &&
174
+ nodeMeta.childLast
175
+ ) {
176
+ if (
177
+ node.openEnd.loc.end.line === nodeMeta.childFirst.loc.start.line
178
+ ) {
179
+ if (isNotNewlineStart(nodeMeta.childFirst)) {
180
+ context.report({
181
+ node: node,
182
+ messageId: MESSAGE_IDS.EXPECT_NEW_LINE_AFTER_OPEN,
183
+ data: { tag: label(node) },
184
+ fix(fixer) {
185
+ return fixer.insertTextAfter(node.openEnd, `\n`);
186
+ },
187
+ });
188
+ }
189
+ }
190
+
191
+ if (nodeMeta.childLast.loc.end.line === node.close.loc.start.line) {
192
+ if (isNotNewlineEnd(nodeMeta.childLast)) {
193
+ context.report({
194
+ node: node,
195
+ messageId: MESSAGE_IDS.EXPECT_NEW_LINE_BEFORE_CLOSE,
196
+ data: { tag: label(node, { isClose: true }) },
197
+ fix(fixer) {
198
+ return fixer.insertTextBefore(node.close, `\n`);
199
+ },
200
+ });
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ if (nodeNext && node.loc.end.line === nodeNext.loc.start.line) {
207
+ if (nodeShouldBeNewline) {
208
+ if (isNotNewlineStart(nodeNext)) {
64
209
  context.report({
65
- node: current,
210
+ node: nodeNext,
66
211
  messageId: MESSAGE_IDS.EXPECT_NEW_LINE_AFTER,
67
- // @ts-ignore
68
- data: { tag: `<${current.name}>` },
212
+ data: { tag: label(node) },
69
213
  fix(fixer) {
70
- return fixer.insertTextAfter(current, "\n");
214
+ return fixer.insertTextAfter(node, `\n`);
71
215
  },
72
216
  });
73
217
  }
218
+ } else if (shouldBeNewline(nodeNext)) {
219
+ if (isNotNewlineEnd(node)) {
220
+ context.report({
221
+ node: nodeNext,
222
+ messageId: MESSAGE_IDS.EXPECT_NEW_LINE_BEFORE,
223
+ data: { tag: label(nodeNext) },
224
+ fix(fixer) {
225
+ return fixer.insertTextBefore(nodeNext, `\n`);
226
+ },
227
+ });
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ return meta;
234
+ }
235
+
236
+ /**
237
+ * @param {NewlineNode} node
238
+ */
239
+ function isEmptyText(node) {
240
+ return node.type === `Text` && node.value.trim().length === 0;
241
+ }
242
+
243
+ /**
244
+ * @param {NewlineNode} node
245
+ */
246
+ function isNotNewlineEnd(node) {
247
+ return node.type !== `Text` || /\n\s*$/.test(node.value) === false;
248
+ }
249
+
250
+ /**
251
+ * @param {NewlineNode} node
252
+ */
253
+ function isNotNewlineStart(node) {
254
+ return node.type !== `Text` || /^\n/.test(node.value) === false;
255
+ }
256
+
257
+ /**
258
+ * @param {NewlineNode} node
259
+ * @param {{ isClose?: boolean }} options
260
+ */
261
+ function label(node, options = {}) {
262
+ const isClose = options.isClose || false;
263
+
264
+ switch (node.type) {
265
+ case `Tag`:
266
+ if (isClose) {
267
+ return `</${node.name}>`;
74
268
  }
75
- });
269
+ return `<${node.name}>`;
270
+ default:
271
+ return `<${node.type}>`;
272
+ }
76
273
  }
77
274
 
78
275
  /**
79
- * @param {TagNode} node
80
- * @param {import("../types").ChildType<TagNode>[]} children
276
+ * @param {Array<string>} options
81
277
  */
82
- function checkChild(node, children) {
83
- const targetChildren = children.filter((n) => n.type !== "Text");
84
- const first = targetChildren[0];
85
- const last = targetChildren[targetChildren.length - 1];
86
- if (first) {
87
- if (isOnTheSameLine(node.openEnd, first)) {
88
- context.report({
89
- node: node.openEnd,
90
- messageId: MESSAGE_IDS.EXPECT_NEW_LINE_AFTER,
91
- data: { tag: `<${node.name}>` },
92
- fix(fixer) {
93
- return fixer.insertTextAfter(node.openEnd, "\n");
94
- },
95
- });
278
+ function optionsOrPresets(options) {
279
+ const result = [];
280
+ for (const option of options) {
281
+ if (option in PRESETS) {
282
+ const preset = PRESETS[option];
283
+ result.push(...preset);
284
+ } else {
285
+ result.push(option);
96
286
  }
97
287
  }
288
+ return result;
289
+ }
98
290
 
99
- if (last) {
100
- if (node.close && isOnTheSameLine(node.close, last)) {
101
- context.report({
102
- node: node.close,
103
- messageId: MESSAGE_IDS.EXPECT_NEW_LINE_BEFORE,
104
- data: { tag: `</${node.name}>` },
105
- fix(fixer) {
106
- return fixer.insertTextBefore(node.close, "\n");
107
- },
108
- });
109
- }
291
+ /**
292
+ * @param {NewlineNode} node
293
+ */
294
+ function shouldBeNewline(node) {
295
+ switch (node.type) {
296
+ case `Comment`:
297
+ return /[\n\r]+/.test(node.value.value.trim());
298
+ case `Tag`:
299
+ return inlineTags.includes(node.name.toLowerCase()) === false;
300
+ case `Text`:
301
+ return /[\n\r]+/.test(node.value.trim());
302
+ default:
303
+ return true;
110
304
  }
111
305
  }
306
+
112
307
  return {
113
308
  Program(node) {
309
+ // @ts-ignore
114
310
  checkSiblings(node.body);
115
311
  },
116
- Tag(node) {
117
- if (skipTagCount > 0) {
118
- return;
119
- }
120
- if (skipTags.includes(node.name)) {
121
- skipTagCount++;
122
- return;
123
- }
124
- checkSiblings(node.children);
125
- checkChild(node, node.children);
126
- },
127
- /**
128
- * @param {TagNode} node
129
- * @returns
130
- */
131
- "Tag:exit"(node) {
132
- if (skipTags.includes(node.name)) {
133
- skipTagCount--;
134
- return;
135
- }
136
- },
137
312
  };
138
313
  },
139
314
  };
140
-
141
- /**
142
- * @param {BaseNode} nodeBefore
143
- * @param {BaseNode} nodeAfter
144
- * @returns
145
- */
146
- function isOnTheSameLine(nodeBefore, nodeAfter) {
147
- if (nodeBefore && nodeAfter) {
148
- return nodeBefore.loc.end.line === nodeAfter.loc.start.line;
149
- }
150
- return false;
151
- }
@@ -6,6 +6,7 @@ const noDuplicateId = require("./no-duplicate-id");
6
6
  const noInlineStyles = require("./no-inline-styles");
7
7
  const noMultipleH1 = require("./no-multiple-h1");
8
8
  const noExtraSpacingAttrs = require("./no-extra-spacing-attrs");
9
+ const noExtraSpacingText = require("./no-extra-spacing-text");
9
10
  const attrsNewline = require("./attrs-newline");
10
11
  const elementNewLine = require("./element-newline");
11
12
  const noSkipHeadingLevels = require("./no-skip-heading-levels");
@@ -46,6 +47,7 @@ module.exports = {
46
47
  "no-inline-styles": noInlineStyles,
47
48
  "no-multiple-h1": noMultipleH1,
48
49
  "no-extra-spacing-attrs": noExtraSpacingAttrs,
50
+ "no-extra-spacing-text": noExtraSpacingText,
49
51
  "attrs-newline": attrsNewline,
50
52
  "element-newline": elementNewLine,
51
53
  "no-skip-heading-levels": noSkipHeadingLevels,
@@ -21,6 +21,7 @@ const MESSAGE_IDS = {
21
21
  EXTRA_AFTER: "unexpectedAfter",
22
22
  EXTRA_BEFORE: "unexpectedBefore",
23
23
  EXTRA_BEFORE_CLOSE: "unexpectedBeforeClose",
24
+ EXTRA_IN_ASSIGNMENT: "unexpectedInAssignment",
24
25
  MISSING_BEFORE: "missingBefore",
25
26
  MISSING_BEFORE_SELF_CLOSE: "missingBeforeSelfClose",
26
27
  EXTRA_BEFORE_SELF_CLOSE: "unexpectedBeforeSelfClose",
@@ -47,6 +48,9 @@ module.exports = {
47
48
  {
48
49
  type: "object",
49
50
  properties: {
51
+ disallowInAssignment: {
52
+ type: "boolean",
53
+ },
50
54
  disallowMissing: {
51
55
  type: "boolean",
52
56
  },
@@ -64,6 +68,8 @@ module.exports = {
64
68
  [MESSAGE_IDS.EXTRA_AFTER]: "Unexpected space after attribute",
65
69
  [MESSAGE_IDS.EXTRA_BEFORE]: "Unexpected space before attribute",
66
70
  [MESSAGE_IDS.EXTRA_BEFORE_CLOSE]: "Unexpected space before closing",
71
+ [MESSAGE_IDS.EXTRA_IN_ASSIGNMENT]:
72
+ "Unexpected space in attribute assignment",
67
73
  [MESSAGE_IDS.MISSING_BEFORE_SELF_CLOSE]:
68
74
  "Missing space before self closing",
69
75
  [MESSAGE_IDS.EXTRA_BEFORE_SELF_CLOSE]:
@@ -82,6 +88,8 @@ module.exports = {
82
88
  .enforceBeforeSelfClose;
83
89
  const disallowMissing = !!(context.options[0] || {}).disallowMissing;
84
90
  const disallowTabs = !!(context.options[0] || {}).disallowTabs;
91
+ const disallowInAssignment = !!(context.options[0] || [])
92
+ .disallowInAssignment;
85
93
 
86
94
  const sourceCode = context.getSourceCode().text;
87
95
 
@@ -104,7 +112,10 @@ module.exports = {
104
112
  loc: getLocBetween(current, after),
105
113
  messageId: MESSAGE_IDS.EXTRA_BETWEEN,
106
114
  fix(fixer) {
107
- return fixer.removeRange([current.range[1] + 1, after.range[0]]);
115
+ return fixer.replaceTextRange(
116
+ [current.range[1], after.range[0]],
117
+ ` `
118
+ );
108
119
  },
109
120
  });
110
121
  } else if (disallowMissing && spacesBetween < 1) {
@@ -122,7 +133,7 @@ module.exports = {
122
133
  messageId: MESSAGE_IDS.EXTRA_TAB_BETWEEN,
123
134
  fix(fixer) {
124
135
  return fixer.replaceTextRange(
125
- [current.range[1], current.range[1] + 1],
136
+ [current.range[1], after.range[0]],
126
137
  ` `
127
138
  );
128
139
  },
@@ -184,6 +195,25 @@ module.exports = {
184
195
 
185
196
  if (node.attributes.length) {
186
197
  checkExtraSpaceBefore(node.openStart, node.attributes[0]);
198
+
199
+ for (const attr of node.attributes) {
200
+ if (attr.startWrapper && attr.value) {
201
+ if (
202
+ disallowInAssignment &&
203
+ attr.startWrapper.loc.start.column - attr.key.loc.end.column > 1
204
+ ) {
205
+ const start = attr.key.range[1];
206
+ const end = attr.startWrapper.range[0];
207
+ context.report({
208
+ node: attr,
209
+ messageId: MESSAGE_IDS.EXTRA_IN_ASSIGNMENT,
210
+ fix(fixer) {
211
+ return fixer.replaceTextRange([start, end], `=`);
212
+ },
213
+ });
214
+ }
215
+ }
216
+ }
187
217
  }
188
218
 
189
219
  if (node.openEnd) {
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @typedef { import("../types").RuleModule } RuleModule
3
+ * @typedef { import("../types").ProgramNode } ProgramNode
4
+ * @typedef { import("es-html-parser").CommentContentNode } CommentContentNode
5
+ * @typedef { import("../types").ContentNode } ContentNode
6
+ * @typedef { import("../types").TextNode } TextNode
7
+ */
8
+
9
+ const { RULE_CATEGORY } = require("../constants");
10
+
11
+ const MESSAGE_IDS = {
12
+ UNEXPECTED: "unexpected",
13
+ };
14
+
15
+ /**
16
+ * @type {RuleModule}
17
+ */
18
+ module.exports = {
19
+ meta: {
20
+ type: "code",
21
+
22
+ docs: {
23
+ description: "Disallow unnecessary consecutive spaces",
24
+ category: RULE_CATEGORY.BEST_PRACTICE,
25
+ recommended: false,
26
+ },
27
+
28
+ fixable: true,
29
+ schema: [
30
+ {
31
+ type: "object",
32
+ properties: {
33
+ skip: {
34
+ type: "array",
35
+ items: {
36
+ type: "string",
37
+ },
38
+ },
39
+ },
40
+ additionalProperties: false,
41
+ },
42
+ ],
43
+ messages: {
44
+ [MESSAGE_IDS.UNEXPECTED]:
45
+ "Tabs and/or multiple consecutive spaces not allowed here",
46
+ },
47
+ },
48
+
49
+ create(context) {
50
+ const options = context.options[0] || {};
51
+ const skipTags = options.skip || [];
52
+ const sourceCode = context.getSourceCode();
53
+
54
+ /**
55
+ * @param {Array<ContentNode>} siblings
56
+ */
57
+ function checkSiblings(siblings) {
58
+ for (
59
+ let length = siblings.length, index = 0;
60
+ index < length;
61
+ index += 1
62
+ ) {
63
+ const node = siblings[index];
64
+
65
+ if (node.type === `Tag` && skipTags.includes(node.name) === false) {
66
+ checkSiblings(node.children);
67
+ } else if (node.type === `Text`) {
68
+ stripConsecutiveSpaces(node);
69
+ } else if (node.type === `Comment`) {
70
+ stripConsecutiveSpaces(node.value);
71
+ }
72
+ }
73
+ }
74
+
75
+ return {
76
+ Program(node) {
77
+ // @ts-ignore
78
+ checkSiblings(node.body);
79
+ },
80
+ };
81
+
82
+ /**
83
+ * @param {TextNode | CommentContentNode} node
84
+ */
85
+ function stripConsecutiveSpaces(node) {
86
+ const text = node.value;
87
+ const matcher = /(^|[^\n \t])([ \t]+\n|\t[\t ]*|[ \t]{2,})/g;
88
+
89
+ // eslint-disable-next-line no-constant-condition
90
+ while (true) {
91
+ const offender = matcher.exec(text);
92
+ if (offender === null) {
93
+ break;
94
+ }
95
+
96
+ const space = offender[2];
97
+ const indexStart = node.range[0] + matcher.lastIndex - space.length;
98
+ const indexEnd = indexStart + space.length;
99
+
100
+ context.report({
101
+ node: node,
102
+ loc: {
103
+ start: sourceCode.getLocFromIndex(indexStart),
104
+ end: sourceCode.getLocFromIndex(indexEnd),
105
+ },
106
+ messageId: MESSAGE_IDS.UNEXPECTED,
107
+ fix(fixer) {
108
+ return fixer.replaceTextRange(
109
+ [indexStart, indexEnd],
110
+ space.endsWith(`\n`) ? `\n` : ` `
111
+ );
112
+ },
113
+ });
114
+ }
115
+ }
116
+ },
117
+ };
package/lib/types.d.ts CHANGED
@@ -267,3 +267,11 @@ export type ChildType<T extends BaseNode> = T extends ProgramNode
267
267
  : T extends TagNode
268
268
  ? T["children"][number]
269
269
  : never;
270
+
271
+ export type ContentNode =
272
+ | CommentNode
273
+ | DoctypeNode
274
+ | ScriptTagNode
275
+ | StyleTagNode
276
+ | TagNode
277
+ | TextNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@html-eslint/eslint-plugin",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "ESLint plugin for html",
5
5
  "author": "yeonjuan",
6
6
  "homepage": "https://github.com/yeonjuan/html-eslint#readme",
@@ -45,11 +45,11 @@
45
45
  "accessibility"
46
46
  ],
47
47
  "devDependencies": {
48
- "@html-eslint/parser": "^0.26.0",
48
+ "@html-eslint/parser": "^0.27.0",
49
49
  "@types/eslint": "^8.56.2",
50
50
  "@types/estree": "^0.0.47",
51
51
  "es-html-parser": "^0.0.8",
52
52
  "typescript": "^4.4.4"
53
53
  },
54
- "gitHead": "34d55c3b5be5a29cc416063b4b4375cb89b3a519"
54
+ "gitHead": "a7c09dfb3090bb779d6fe62fda814d4d7ca07d4a"
55
55
  }
@@ -6,7 +6,9 @@ export const rules: {
6
6
  "@html-eslint/no-multiple-h1": string;
7
7
  "@html-eslint/no-extra-spacing-attrs": string;
8
8
  "@html-eslint/attrs-newline": string;
9
- "@html-eslint/element-newline": string;
9
+ "@html-eslint/element-newline": (string | {
10
+ inline: string[];
11
+ })[];
10
12
  "@html-eslint/no-duplicate-id": string;
11
13
  "@html-eslint/indent": string;
12
14
  "@html-eslint/require-li-container": string;
@@ -4,4 +4,15 @@ export type RuleModule = import("../types").RuleModule;
4
4
  export type ProgramNode = import("../types").ProgramNode;
5
5
  export type TagNode = import("../types").TagNode;
6
6
  export type BaseNode = import("../types").BaseNode;
7
+ export type CommentNode = import("../types").CommentNode;
8
+ export type DoctypeNode = import("../types").DoctypeNode;
9
+ export type ScriptTagNode = import("../types").ScriptTagNode;
10
+ export type StyleTagNode = import("../types").StyleTagNode;
11
+ export type TextNode = import("../types").TextNode;
12
+ export type NewlineNode = CommentNode | DoctypeNode | ScriptTagNode | StyleTagNode | TagNode | TextNode;
13
+ export type NodeMeta = {
14
+ childFirst: NewlineNode | null;
15
+ childLast: NewlineNode | null;
16
+ shouldBeNewline: boolean;
17
+ };
7
18
  //# sourceMappingURL=element-newline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"element-newline.d.ts","sourceRoot":"","sources":["../../lib/rules/element-newline.js"],"names":[],"mappings":"wBAeU,UAAU;;yBAdN,OAAO,UAAU,EAAE,UAAU;0BAC7B,OAAO,UAAU,EAAE,WAAW;sBAC9B,OAAO,UAAU,EAAE,OAAO;uBAC1B,OAAO,UAAU,EAAE,QAAQ"}
1
+ {"version":3,"file":"element-newline.d.ts","sourceRoot":"","sources":["../../lib/rules/element-newline.js"],"names":[],"mappings":"wBAoEU,UAAU;;yBAnEN,OAAO,UAAU,EAAE,UAAU;0BAC7B,OAAO,UAAU,EAAE,WAAW;sBAC9B,OAAO,UAAU,EAAE,OAAO;uBAC1B,OAAO,UAAU,EAAE,QAAQ;0BAC3B,OAAO,UAAU,EAAE,WAAW;0BAC9B,OAAO,UAAU,EAAE,WAAW;4BAC9B,OAAO,UAAU,EAAE,aAAa;2BAChC,OAAO,UAAU,EAAE,YAAY;uBAC/B,OAAO,UAAU,EAAE,QAAQ;0BAC3B,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ;uBAC9E;IACZ,UAAc,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,SAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,eAAmB,EAAE,OAAO,CAAC;CAC1B"}
@@ -7,6 +7,7 @@ declare const _exports: {
7
7
  "no-inline-styles": import("../types").RuleModule;
8
8
  "no-multiple-h1": import("../types").RuleModule;
9
9
  "no-extra-spacing-attrs": import("../types").RuleModule;
10
+ "no-extra-spacing-text": import("../types").RuleModule;
10
11
  "attrs-newline": import("../types").RuleModule;
11
12
  "element-newline": import("../types").RuleModule;
12
13
  "no-skip-heading-levels": import("../types").RuleModule;
@@ -1 +1 @@
1
- {"version":3,"file":"no-extra-spacing-attrs.d.ts","sourceRoot":"","sources":["../../lib/rules/no-extra-spacing-attrs.js"],"names":[],"mappings":"wBAgCU,UAAU;;yBA/BN,OAAO,UAAU,EAAE,UAAU;4BAC7B,OAAO,UAAU,EAAE,aAAa;6BAChC,OAAO,UAAU,EAAE,cAAc;mCACjC,OAAO,UAAU,EAAE,oBAAoB;kCACvC,OAAO,UAAU,EAAE,mBAAmB;qCACtC,OAAO,UAAU,EAAE,sBAAsB;+BACzC,OAAO,UAAU,EAAE,gBAAgB;oCACnC,OAAO,UAAU,EAAE,qBAAqB;sBACxC,OAAO,UAAU,EAAE,OAAO;2BAC1B,OAAO,UAAU,EAAE,YAAY;4BAC/B,OAAO,UAAU,EAAE,aAAa;sBAChC,OAAO,UAAU,EAAE,OAAO"}
1
+ {"version":3,"file":"no-extra-spacing-attrs.d.ts","sourceRoot":"","sources":["../../lib/rules/no-extra-spacing-attrs.js"],"names":[],"mappings":"wBAiCU,UAAU;;yBAhCN,OAAO,UAAU,EAAE,UAAU;4BAC7B,OAAO,UAAU,EAAE,aAAa;6BAChC,OAAO,UAAU,EAAE,cAAc;mCACjC,OAAO,UAAU,EAAE,oBAAoB;kCACvC,OAAO,UAAU,EAAE,mBAAmB;qCACtC,OAAO,UAAU,EAAE,sBAAsB;+BACzC,OAAO,UAAU,EAAE,gBAAgB;oCACnC,OAAO,UAAU,EAAE,qBAAqB;sBACxC,OAAO,UAAU,EAAE,OAAO;2BAC1B,OAAO,UAAU,EAAE,YAAY;4BAC/B,OAAO,UAAU,EAAE,aAAa;sBAChC,OAAO,UAAU,EAAE,OAAO"}
@@ -0,0 +1,8 @@
1
+ declare const _exports: RuleModule;
2
+ export = _exports;
3
+ export type RuleModule = import("../types").RuleModule;
4
+ export type ProgramNode = import("../types").ProgramNode;
5
+ export type CommentContentNode = import("es-html-parser").CommentContentNode;
6
+ export type ContentNode = import("../types").ContentNode;
7
+ export type TextNode = import("../types").TextNode;
8
+ //# sourceMappingURL=no-extra-spacing-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-extra-spacing-text.d.ts","sourceRoot":"","sources":["../../lib/rules/no-extra-spacing-text.js"],"names":[],"mappings":"wBAeU,UAAU;;yBAdN,OAAO,UAAU,EAAE,UAAU;0BAC7B,OAAO,UAAU,EAAE,WAAW;iCAC9B,OAAO,gBAAgB,EAAE,kBAAkB;0BAC3C,OAAO,UAAU,EAAE,WAAW;uBAC9B,OAAO,UAAU,EAAE,QAAQ"}
@@ -13,7 +13,7 @@ export type Location = import("../../types").Location;
13
13
  * @param {string} key
14
14
  * @returns {AttributeNode | undefined}
15
15
  */
16
- declare function findAttr(node: import("../../types").TagNode | import("../../types").ScriptTagNode | import("../../types").StyleTagNode, key: string): import("../../types").AttributeNode | undefined;
16
+ declare function findAttr(node: import("../../types").ScriptTagNode | import("../../types").TagNode | import("../../types").StyleTagNode, key: string): import("../../types").AttributeNode | undefined;
17
17
  /**
18
18
  * Checks whether a node's all tokens are on the same line or not.
19
19
  * @param {AnyNode} node A node to check