eslint-plugin-svg 0.0.1 → 0.0.3

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
@@ -57,6 +57,8 @@ export default [
57
57
  | [no-empty-text](https://eslint-plugin-svg.ntnyq.com/rules/no-empty-text) | Disallow empty text element | ✅ | | |
58
58
  | [no-empty-container](https://eslint-plugin-svg.ntnyq.com/rules/no-empty-container) | Disallow empty container element | ✅ | | |
59
59
  | [no-deprecated](https://eslint-plugin-svg.ntnyq.com/rules/no-deprecated) | Disallow deprecated elements | ✅ | | |
60
+ | [no-elements](https://eslint-plugin-svg.ntnyq.com/rules/no-elements) | Disallow elements by name | | | |
61
+ | [no-doctype](https://eslint-plugin-svg.ntnyq.com/rules/no-doctype) | Disallow doctype | ✅ | 🔧 | |
60
62
 
61
63
  ## License
62
64
 
package/dist/index.cjs CHANGED
@@ -70,6 +70,7 @@ var recommended = [
70
70
  // @keep-sorted
71
71
  rules: {
72
72
  "svg/no-deprecated": "error",
73
+ "svg/no-doctype": "error",
73
74
  "svg/no-empty-container": "error",
74
75
  "svg/no-empty-desc": "error",
75
76
  "svg/no-empty-text": "error",
@@ -83,7 +84,7 @@ var configs = {
83
84
 
84
85
  // package.json
85
86
  var name = "eslint-plugin-svg";
86
- var version = "0.0.1";
87
+ var version = "0.0.3";
87
88
 
88
89
  // src/meta.ts
89
90
  var meta = {
@@ -157,24 +158,24 @@ var import_utils = require("@ntnyq/utils");
157
158
  var docsUrl = "https://eslint-plugin-svg.ntnyq.com/rules/";
158
159
  function createRule({
159
160
  create,
160
- defaultOptions: defaultOptions3,
161
+ defaultOptions: defaultOptions4,
161
162
  meta: meta2
162
163
  }) {
163
164
  return {
164
165
  create: (context) => {
165
- const optionsCount = Math.max(context.options.length, defaultOptions3.length);
166
+ const optionsCount = Math.max(context.options.length, defaultOptions4.length);
166
167
  const optionsWithDefault = Array.from({ length: optionsCount }, (_, i) => {
167
- if (isObjectNotArray(context.options[i]) && isObjectNotArray(defaultOptions3[i])) {
168
- return deepMerge(defaultOptions3[i], context.options[i]);
168
+ if (isObjectNotArray(context.options[i]) && isObjectNotArray(defaultOptions4[i])) {
169
+ return deepMerge(defaultOptions4[i], context.options[i]);
169
170
  }
170
- return context.options[i] ?? defaultOptions3[i];
171
+ return context.options[i] ?? defaultOptions4[i];
171
172
  });
172
173
  return create(context, optionsWithDefault);
173
174
  },
174
- defaultOptions: defaultOptions3,
175
+ defaultOptions: defaultOptions4,
175
176
  meta: {
176
177
  ...meta2,
177
- defaultOptions: defaultOptions3
178
+ defaultOptions: defaultOptions4
178
179
  }
179
180
  };
180
181
  }
@@ -198,6 +199,11 @@ function RuleCreator(urlCreator) {
198
199
  }
199
200
  var createESLintRule = RuleCreator((ruleName) => `${docsUrl}${ruleName}.html`);
200
201
 
202
+ // src/utils/resolveOptions.ts
203
+ function resolveOptions(options) {
204
+ return options?.[0] || {};
205
+ }
206
+
201
207
  // src/rules/no-deprecated.ts
202
208
  var RULE_NAME = "no-deprecated";
203
209
  var defaultOptions = {};
@@ -230,7 +236,7 @@ var no_deprecated_default = createESLintRule({
230
236
  },
231
237
  defaultOptions: [defaultOptions],
232
238
  create(context) {
233
- const { allowElements = [] } = context.options?.[0] || {};
239
+ const { allowElements = [] } = resolveOptions(context.options);
234
240
  const deprecatedElements = new Set(
235
241
  DEPRECATED_ELEMENTS.filter((element) => !allowElements.includes(element))
236
242
  );
@@ -250,12 +256,94 @@ var no_deprecated_default = createESLintRule({
250
256
  }
251
257
  });
252
258
 
253
- // src/rules/no-empty-container.ts
254
- var import_utils3 = require("@ntnyq/utils");
255
- var RULE_NAME2 = "no-empty-container";
259
+ // src/rules/no-doctype.ts
260
+ var RULE_NAME2 = "no-doctype";
261
+ var no_doctype_default = createESLintRule({
262
+ name: RULE_NAME2,
263
+ meta: {
264
+ type: "suggestion",
265
+ docs: {
266
+ description: "disallow doctype",
267
+ recommended: true
268
+ },
269
+ fixable: "code",
270
+ schema: [],
271
+ messages: {
272
+ invalid: "Doctype is not allowed"
273
+ }
274
+ },
275
+ defaultOptions: [],
276
+ create(context) {
277
+ return {
278
+ Doctype(node) {
279
+ context.report({
280
+ node,
281
+ messageId: "invalid",
282
+ fix: (fixer) => fixer.remove(node)
283
+ });
284
+ }
285
+ };
286
+ }
287
+ });
288
+
289
+ // src/rules/no-elements.ts
290
+ var RULE_NAME3 = "no-elements";
256
291
  var defaultOptions2 = {};
292
+ var no_elements_default = createESLintRule({
293
+ name: RULE_NAME3,
294
+ meta: {
295
+ type: "suggestion",
296
+ docs: {
297
+ description: "disallow elements by name",
298
+ recommended: true
299
+ },
300
+ schema: [
301
+ {
302
+ type: "object",
303
+ properties: {
304
+ elements: {
305
+ type: "array",
306
+ description: "elements to be disallowed",
307
+ items: {
308
+ type: "string"
309
+ }
310
+ }
311
+ },
312
+ additionalProperties: false
313
+ }
314
+ ],
315
+ messages: {
316
+ invalid: `Element '{{name}}' is not allowed`
317
+ }
318
+ },
319
+ defaultOptions: [defaultOptions2],
320
+ create(context) {
321
+ const { elements = [] } = resolveOptions(context.options);
322
+ if (!elements.length) {
323
+ return {};
324
+ }
325
+ return {
326
+ Tag(node) {
327
+ if (elements.includes(node.name)) {
328
+ context.report({
329
+ node,
330
+ messageId: "invalid",
331
+ data: {
332
+ name: node.name
333
+ }
334
+ });
335
+ }
336
+ }
337
+ };
338
+ }
339
+ });
340
+
341
+ // src/rules/no-empty-container.ts
342
+ var import_utils5 = require("@ntnyq/utils");
343
+ var RULE_NAME4 = "no-empty-container";
344
+ var defaultOptions3 = {};
257
345
  var no_empty_container_default = createESLintRule({
258
- name: RULE_NAME2,
346
+ name: RULE_NAME4,
259
347
  meta: {
260
348
  type: "suggestion",
261
349
  docs: {
@@ -298,21 +386,28 @@ var no_empty_container_default = createESLintRule({
298
386
  invalid: `Container element '{{name}}' must not be empty`
299
387
  }
300
388
  },
301
- defaultOptions: [defaultOptions2],
389
+ defaultOptions: [defaultOptions3],
302
390
  create(context) {
303
391
  const {
304
- elements = CONTAINER_ELEMENTS,
392
+ elements = [],
305
393
  ignores = [],
306
394
  ignoreComments = true,
307
395
  ignoreWhitespace = true
308
- } = context.options?.[0] || {};
309
- const containerElements = new Set(elements.filter((v) => !ignores.includes(v)));
396
+ } = resolveOptions(context.options);
397
+ const containerElements = new Set(
398
+ [
399
+ // built-in container elements
400
+ ...CONTAINER_ELEMENTS,
401
+ // user defined container elements
402
+ ...elements
403
+ ].filter((v) => !ignores.includes(v))
404
+ );
310
405
  return {
311
406
  Tag(node) {
312
407
  if (!containerElements.has(node.name)) {
313
408
  return;
314
409
  }
315
- const children = node.children.filter((n) => !ignoreComments || n.type !== "Comment").filter((n) => !ignoreWhitespace || n.type !== "Text" || (0, import_utils3.isNonEmptyString)(n.value.trim()));
410
+ const children = node.children.filter((n) => !ignoreComments || n.type !== "Comment").filter((n) => !ignoreWhitespace || n.type !== "Text" || (0, import_utils5.isNonEmptyString)(n.value.trim()));
316
411
  if (children.length === 0) {
317
412
  context.report({
318
413
  node,
@@ -328,9 +423,9 @@ var no_empty_container_default = createESLintRule({
328
423
  });
329
424
 
330
425
  // src/rules/no-empty-desc.ts
331
- var RULE_NAME3 = "no-empty-desc";
426
+ var RULE_NAME5 = "no-empty-desc";
332
427
  var no_empty_desc_default = createESLintRule({
333
- name: RULE_NAME3,
428
+ name: RULE_NAME5,
334
429
  meta: {
335
430
  type: "suggestion",
336
431
  docs: {
@@ -369,9 +464,9 @@ var no_empty_desc_default = createESLintRule({
369
464
  });
370
465
 
371
466
  // src/rules/no-empty-text.ts
372
- var RULE_NAME4 = "no-empty-text";
467
+ var RULE_NAME6 = "no-empty-text";
373
468
  var no_empty_text_default = createESLintRule({
374
- name: RULE_NAME4,
469
+ name: RULE_NAME6,
375
470
  meta: {
376
471
  type: "suggestion",
377
472
  docs: {
@@ -410,9 +505,9 @@ var no_empty_text_default = createESLintRule({
410
505
  });
411
506
 
412
507
  // src/rules/no-empty-title.ts
413
- var RULE_NAME5 = "no-empty-title";
508
+ var RULE_NAME7 = "no-empty-title";
414
509
  var no_empty_title_default = createESLintRule({
415
- name: RULE_NAME5,
510
+ name: RULE_NAME7,
416
511
  meta: {
417
512
  type: "suggestion",
418
513
  docs: {
@@ -453,6 +548,8 @@ var no_empty_title_default = createESLintRule({
453
548
  // src/rules/index.ts
454
549
  var rules = {
455
550
  "no-deprecated": no_deprecated_default,
551
+ "no-doctype": no_doctype_default,
552
+ "no-elements": no_elements_default,
456
553
  "no-empty-container": no_empty_container_default,
457
554
  "no-empty-desc": no_empty_desc_default,
458
555
  "no-empty-text": no_empty_text_default,
package/dist/index.d.cts CHANGED
@@ -128,22 +128,16 @@ type ReportDescriptor<TMessageIds extends string> =
128
128
  ReportDescriptorWithSuggestion<TMessageIds> &
129
129
  (ReportDescriptorLocOnly | ReportDescriptorNodeOptionalLoc)
130
130
 
131
- type ReportDescriptorBase<TMessageIds extends string> = {
132
- readonly messageId: TMessageIds
133
- readonly data?: ReportDescriptorMessageData
134
- readonly fix?: Rule.ReportFixer
135
- }
136
-
137
131
  type ReportDescriptorLocOnly = {
138
132
  loc: Readonly<AST.Position> | Readonly<AST.SourceLocation>
139
133
  }
140
134
 
141
135
  type ReportDescriptorMessageData = Readonly<Record<string, unknown>>
136
+
142
137
  type ReportDescriptorNodeOptionalLoc = {
143
138
  readonly node: AST.AnyNode
144
139
  readonly loc?: Readonly<AST.Position> | Readonly<AST.SourceLocation>
145
140
  }
146
-
147
141
  interface ReportDescriptorWithSuggestion<TMessageIds extends string>
148
142
  extends ReportDescriptorBase<TMessageIds> {
149
143
  readonly suggest?: readonly Rule.SuggestionReportDescriptor[]
@@ -152,7 +146,7 @@ interface RuleContext<TMessageIds extends string, TOptions extends readonly unkn
152
146
  id: string
153
147
  options: TOptions
154
148
  parserPath: string
155
- settings: { yml?: YMLSettings; [name: string]: any }
149
+ settings: { svg?: SVGSettings; [name: string]: any }
156
150
  getAncestors(): AST.AnyNode[]
157
151
  getFilename(): string
158
152
  getSourceCode(): SourceCode
@@ -205,7 +199,7 @@ interface RuleModule<
205
199
  create(context: RuleContext<TMessageIds, TOptions>): RuleListener
206
200
  }
207
201
 
208
- type YMLSettings = { indent?: number }
202
+ type SVGSettings = { indent?: number }
209
203
  interface RuleMetaData<
210
204
  TMessageIds extends string,
211
205
  TDocs = unknown,
@@ -229,7 +223,38 @@ interface RuleMetaDataDocs {
229
223
  url?: string
230
224
  }
231
225
 
232
- type Options$1 = [
226
+ /**
227
+ * rule fixer
228
+ */
229
+ type Fix = {
230
+ range: AST.Range
231
+ text: string
232
+ }
233
+ type ReportDescriptorBase<TMessageIds extends string> = {
234
+ readonly messageId: TMessageIds
235
+ readonly data?: ReportDescriptorMessageData
236
+ readonly fix?: ReportFixer
237
+ }
238
+ type ReportFixer = (fixer: RuleFixer) => Fix | Fix[] | IterableIterator<Fix> | null
239
+ type RuleFixer = {
240
+ insertTextAfter(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
241
+
242
+ insertTextAfterRange(range: AST.Range, text: string): Fix
243
+
244
+ insertTextBefore(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
245
+
246
+ insertTextBeforeRange(range: AST.Range, text: string): Fix
247
+
248
+ remove(nodeOrToken: AST.AnyNode | AST.Token): Fix
249
+
250
+ removeRange(range: AST.Range): Fix
251
+
252
+ replaceText(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
253
+
254
+ replaceTextRange(range: AST.Range, text: string): Fix
255
+ }
256
+
257
+ type Options$2 = [
233
258
  {
234
259
  elements?: string[];
235
260
  ignores?: string[];
@@ -238,6 +263,12 @@ type Options$1 = [
238
263
  }
239
264
  ];
240
265
 
266
+ type Options$1 = [
267
+ {
268
+ elements?: string[];
269
+ }
270
+ ];
271
+
241
272
  type Options = [
242
273
  {
243
274
  allowElements?: string[];
@@ -246,7 +277,9 @@ type Options = [
246
277
 
247
278
  declare const rules: {
248
279
  'no-deprecated': RuleModule<"deprecatedElement", Options, unknown>;
249
- 'no-empty-container': RuleModule<"invalid", Options$1, unknown>;
280
+ 'no-doctype': RuleModule<"invalid", [], unknown>;
281
+ 'no-elements': RuleModule<"invalid", Options$1, unknown>;
282
+ 'no-empty-container': RuleModule<"invalid", Options$2, unknown>;
250
283
  'no-empty-desc': RuleModule<"invalid", [], unknown>;
251
284
  'no-empty-text': RuleModule<"invalid", [], unknown>;
252
285
  'no-empty-title': RuleModule<"invalid", [], unknown>;
package/dist/index.d.ts CHANGED
@@ -128,22 +128,16 @@ type ReportDescriptor<TMessageIds extends string> =
128
128
  ReportDescriptorWithSuggestion<TMessageIds> &
129
129
  (ReportDescriptorLocOnly | ReportDescriptorNodeOptionalLoc)
130
130
 
131
- type ReportDescriptorBase<TMessageIds extends string> = {
132
- readonly messageId: TMessageIds
133
- readonly data?: ReportDescriptorMessageData
134
- readonly fix?: Rule.ReportFixer
135
- }
136
-
137
131
  type ReportDescriptorLocOnly = {
138
132
  loc: Readonly<AST.Position> | Readonly<AST.SourceLocation>
139
133
  }
140
134
 
141
135
  type ReportDescriptorMessageData = Readonly<Record<string, unknown>>
136
+
142
137
  type ReportDescriptorNodeOptionalLoc = {
143
138
  readonly node: AST.AnyNode
144
139
  readonly loc?: Readonly<AST.Position> | Readonly<AST.SourceLocation>
145
140
  }
146
-
147
141
  interface ReportDescriptorWithSuggestion<TMessageIds extends string>
148
142
  extends ReportDescriptorBase<TMessageIds> {
149
143
  readonly suggest?: readonly Rule.SuggestionReportDescriptor[]
@@ -152,7 +146,7 @@ interface RuleContext<TMessageIds extends string, TOptions extends readonly unkn
152
146
  id: string
153
147
  options: TOptions
154
148
  parserPath: string
155
- settings: { yml?: YMLSettings; [name: string]: any }
149
+ settings: { svg?: SVGSettings; [name: string]: any }
156
150
  getAncestors(): AST.AnyNode[]
157
151
  getFilename(): string
158
152
  getSourceCode(): SourceCode
@@ -205,7 +199,7 @@ interface RuleModule<
205
199
  create(context: RuleContext<TMessageIds, TOptions>): RuleListener
206
200
  }
207
201
 
208
- type YMLSettings = { indent?: number }
202
+ type SVGSettings = { indent?: number }
209
203
  interface RuleMetaData<
210
204
  TMessageIds extends string,
211
205
  TDocs = unknown,
@@ -229,7 +223,38 @@ interface RuleMetaDataDocs {
229
223
  url?: string
230
224
  }
231
225
 
232
- type Options$1 = [
226
+ /**
227
+ * rule fixer
228
+ */
229
+ type Fix = {
230
+ range: AST.Range
231
+ text: string
232
+ }
233
+ type ReportDescriptorBase<TMessageIds extends string> = {
234
+ readonly messageId: TMessageIds
235
+ readonly data?: ReportDescriptorMessageData
236
+ readonly fix?: ReportFixer
237
+ }
238
+ type ReportFixer = (fixer: RuleFixer) => Fix | Fix[] | IterableIterator<Fix> | null
239
+ type RuleFixer = {
240
+ insertTextAfter(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
241
+
242
+ insertTextAfterRange(range: AST.Range, text: string): Fix
243
+
244
+ insertTextBefore(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
245
+
246
+ insertTextBeforeRange(range: AST.Range, text: string): Fix
247
+
248
+ remove(nodeOrToken: AST.AnyNode | AST.Token): Fix
249
+
250
+ removeRange(range: AST.Range): Fix
251
+
252
+ replaceText(nodeOrToken: AST.AnyNode | AST.Token, text: string): Fix
253
+
254
+ replaceTextRange(range: AST.Range, text: string): Fix
255
+ }
256
+
257
+ type Options$2 = [
233
258
  {
234
259
  elements?: string[];
235
260
  ignores?: string[];
@@ -238,6 +263,12 @@ type Options$1 = [
238
263
  }
239
264
  ];
240
265
 
266
+ type Options$1 = [
267
+ {
268
+ elements?: string[];
269
+ }
270
+ ];
271
+
241
272
  type Options = [
242
273
  {
243
274
  allowElements?: string[];
@@ -246,7 +277,9 @@ type Options = [
246
277
 
247
278
  declare const rules: {
248
279
  'no-deprecated': RuleModule<"deprecatedElement", Options, unknown>;
249
- 'no-empty-container': RuleModule<"invalid", Options$1, unknown>;
280
+ 'no-doctype': RuleModule<"invalid", [], unknown>;
281
+ 'no-elements': RuleModule<"invalid", Options$1, unknown>;
282
+ 'no-empty-container': RuleModule<"invalid", Options$2, unknown>;
250
283
  'no-empty-desc': RuleModule<"invalid", [], unknown>;
251
284
  'no-empty-text': RuleModule<"invalid", [], unknown>;
252
285
  'no-empty-title': RuleModule<"invalid", [], unknown>;
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ var recommended = [
28
28
  // @keep-sorted
29
29
  rules: {
30
30
  "svg/no-deprecated": "error",
31
+ "svg/no-doctype": "error",
31
32
  "svg/no-empty-container": "error",
32
33
  "svg/no-empty-desc": "error",
33
34
  "svg/no-empty-text": "error",
@@ -41,7 +42,7 @@ var configs = {
41
42
 
42
43
  // package.json
43
44
  var name = "eslint-plugin-svg";
44
- var version = "0.0.1";
45
+ var version = "0.0.3";
45
46
 
46
47
  // src/meta.ts
47
48
  var meta = {
@@ -115,24 +116,24 @@ import { camelCase, kebabCase, pascalCase, snakeCase, titleCase, trainCase } fro
115
116
  var docsUrl = "https://eslint-plugin-svg.ntnyq.com/rules/";
116
117
  function createRule({
117
118
  create,
118
- defaultOptions: defaultOptions3,
119
+ defaultOptions: defaultOptions4,
119
120
  meta: meta2
120
121
  }) {
121
122
  return {
122
123
  create: (context) => {
123
- const optionsCount = Math.max(context.options.length, defaultOptions3.length);
124
+ const optionsCount = Math.max(context.options.length, defaultOptions4.length);
124
125
  const optionsWithDefault = Array.from({ length: optionsCount }, (_, i) => {
125
- if (isObjectNotArray(context.options[i]) && isObjectNotArray(defaultOptions3[i])) {
126
- return deepMerge(defaultOptions3[i], context.options[i]);
126
+ if (isObjectNotArray(context.options[i]) && isObjectNotArray(defaultOptions4[i])) {
127
+ return deepMerge(defaultOptions4[i], context.options[i]);
127
128
  }
128
- return context.options[i] ?? defaultOptions3[i];
129
+ return context.options[i] ?? defaultOptions4[i];
129
130
  });
130
131
  return create(context, optionsWithDefault);
131
132
  },
132
- defaultOptions: defaultOptions3,
133
+ defaultOptions: defaultOptions4,
133
134
  meta: {
134
135
  ...meta2,
135
- defaultOptions: defaultOptions3
136
+ defaultOptions: defaultOptions4
136
137
  }
137
138
  };
138
139
  }
@@ -156,6 +157,11 @@ function RuleCreator(urlCreator) {
156
157
  }
157
158
  var createESLintRule = RuleCreator((ruleName) => `${docsUrl}${ruleName}.html`);
158
159
 
160
+ // src/utils/resolveOptions.ts
161
+ function resolveOptions(options) {
162
+ return options?.[0] || {};
163
+ }
164
+
159
165
  // src/rules/no-deprecated.ts
160
166
  var RULE_NAME = "no-deprecated";
161
167
  var defaultOptions = {};
@@ -188,7 +194,7 @@ var no_deprecated_default = createESLintRule({
188
194
  },
189
195
  defaultOptions: [defaultOptions],
190
196
  create(context) {
191
- const { allowElements = [] } = context.options?.[0] || {};
197
+ const { allowElements = [] } = resolveOptions(context.options);
192
198
  const deprecatedElements = new Set(
193
199
  DEPRECATED_ELEMENTS.filter((element) => !allowElements.includes(element))
194
200
  );
@@ -208,12 +214,94 @@ var no_deprecated_default = createESLintRule({
208
214
  }
209
215
  });
210
216
 
217
+ // src/rules/no-doctype.ts
218
+ var RULE_NAME2 = "no-doctype";
219
+ var no_doctype_default = createESLintRule({
220
+ name: RULE_NAME2,
221
+ meta: {
222
+ type: "suggestion",
223
+ docs: {
224
+ description: "disallow doctype",
225
+ recommended: true
226
+ },
227
+ fixable: "code",
228
+ schema: [],
229
+ messages: {
230
+ invalid: "Doctype is not allowed"
231
+ }
232
+ },
233
+ defaultOptions: [],
234
+ create(context) {
235
+ return {
236
+ Doctype(node) {
237
+ context.report({
238
+ node,
239
+ messageId: "invalid",
240
+ fix: (fixer) => fixer.remove(node)
241
+ });
242
+ }
243
+ };
244
+ }
245
+ });
246
+
247
+ // src/rules/no-elements.ts
248
+ var RULE_NAME3 = "no-elements";
249
+ var defaultOptions2 = {};
250
+ var no_elements_default = createESLintRule({
251
+ name: RULE_NAME3,
252
+ meta: {
253
+ type: "suggestion",
254
+ docs: {
255
+ description: "disallow elements by name",
256
+ recommended: true
257
+ },
258
+ schema: [
259
+ {
260
+ type: "object",
261
+ properties: {
262
+ elements: {
263
+ type: "array",
264
+ description: "elements to be disallowed",
265
+ items: {
266
+ type: "string"
267
+ }
268
+ }
269
+ },
270
+ additionalProperties: false
271
+ }
272
+ ],
273
+ messages: {
274
+ invalid: `Element '{{name}}' is not allowed`
275
+ }
276
+ },
277
+ defaultOptions: [defaultOptions2],
278
+ create(context) {
279
+ const { elements = [] } = resolveOptions(context.options);
280
+ if (!elements.length) {
281
+ return {};
282
+ }
283
+ return {
284
+ Tag(node) {
285
+ if (elements.includes(node.name)) {
286
+ context.report({
287
+ node,
288
+ messageId: "invalid",
289
+ data: {
290
+ name: node.name
291
+ }
292
+ });
293
+ }
294
+ }
295
+ };
296
+ }
297
+ });
298
+
211
299
  // src/rules/no-empty-container.ts
212
300
  import { isNonEmptyString } from "@ntnyq/utils";
213
- var RULE_NAME2 = "no-empty-container";
214
- var defaultOptions2 = {};
301
+ var RULE_NAME4 = "no-empty-container";
302
+ var defaultOptions3 = {};
215
303
  var no_empty_container_default = createESLintRule({
216
- name: RULE_NAME2,
304
+ name: RULE_NAME4,
217
305
  meta: {
218
306
  type: "suggestion",
219
307
  docs: {
@@ -256,15 +344,22 @@ var no_empty_container_default = createESLintRule({
256
344
  invalid: `Container element '{{name}}' must not be empty`
257
345
  }
258
346
  },
259
- defaultOptions: [defaultOptions2],
347
+ defaultOptions: [defaultOptions3],
260
348
  create(context) {
261
349
  const {
262
- elements = CONTAINER_ELEMENTS,
350
+ elements = [],
263
351
  ignores = [],
264
352
  ignoreComments = true,
265
353
  ignoreWhitespace = true
266
- } = context.options?.[0] || {};
267
- const containerElements = new Set(elements.filter((v) => !ignores.includes(v)));
354
+ } = resolveOptions(context.options);
355
+ const containerElements = new Set(
356
+ [
357
+ // built-in container elements
358
+ ...CONTAINER_ELEMENTS,
359
+ // user defined container elements
360
+ ...elements
361
+ ].filter((v) => !ignores.includes(v))
362
+ );
268
363
  return {
269
364
  Tag(node) {
270
365
  if (!containerElements.has(node.name)) {
@@ -286,9 +381,9 @@ var no_empty_container_default = createESLintRule({
286
381
  });
287
382
 
288
383
  // src/rules/no-empty-desc.ts
289
- var RULE_NAME3 = "no-empty-desc";
384
+ var RULE_NAME5 = "no-empty-desc";
290
385
  var no_empty_desc_default = createESLintRule({
291
- name: RULE_NAME3,
386
+ name: RULE_NAME5,
292
387
  meta: {
293
388
  type: "suggestion",
294
389
  docs: {
@@ -327,9 +422,9 @@ var no_empty_desc_default = createESLintRule({
327
422
  });
328
423
 
329
424
  // src/rules/no-empty-text.ts
330
- var RULE_NAME4 = "no-empty-text";
425
+ var RULE_NAME6 = "no-empty-text";
331
426
  var no_empty_text_default = createESLintRule({
332
- name: RULE_NAME4,
427
+ name: RULE_NAME6,
333
428
  meta: {
334
429
  type: "suggestion",
335
430
  docs: {
@@ -368,9 +463,9 @@ var no_empty_text_default = createESLintRule({
368
463
  });
369
464
 
370
465
  // src/rules/no-empty-title.ts
371
- var RULE_NAME5 = "no-empty-title";
466
+ var RULE_NAME7 = "no-empty-title";
372
467
  var no_empty_title_default = createESLintRule({
373
- name: RULE_NAME5,
468
+ name: RULE_NAME7,
374
469
  meta: {
375
470
  type: "suggestion",
376
471
  docs: {
@@ -411,6 +506,8 @@ var no_empty_title_default = createESLintRule({
411
506
  // src/rules/index.ts
412
507
  var rules = {
413
508
  "no-deprecated": no_deprecated_default,
509
+ "no-doctype": no_doctype_default,
510
+ "no-elements": no_elements_default,
414
511
  "no-empty-container": no_empty_container_default,
415
512
  "no-empty-desc": no_empty_desc_default,
416
513
  "no-empty-text": no_empty_text_default,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-svg",
3
3
  "type": "module",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "description": "Rules for consistent, readable and valid SVG files.",
6
6
  "keywords": [
7
7
  "eslint",
@@ -41,14 +41,14 @@
41
41
  "eslint": "^9.5.0"
42
42
  },
43
43
  "dependencies": {
44
- "@ntnyq/utils": "^0.4.2",
44
+ "@ntnyq/utils": "^0.4.5",
45
45
  "@types/json-schema": "^7.0.15",
46
- "svg-eslint-parser": "^0.0.0"
46
+ "svg-eslint-parser": "^0.0.2"
47
47
  },
48
48
  "devDependencies": {
49
- "@ntnyq/eslint-config": "^3.10.4",
50
- "@ntnyq/prettier-config": "^1.22.0",
51
- "@types/node": "^22.10.2",
49
+ "@ntnyq/eslint-config": "^3.11.0",
50
+ "@ntnyq/prettier-config": "^1.22.1",
51
+ "@types/node": "^22.10.5",
52
52
  "@vitest/coverage-v8": "^3.0.0-beta.3",
53
53
  "bumpp": "^9.9.2",
54
54
  "eslint": "^9.17.0",