@markuplint/rules 3.10.0 → 3.11.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.
@@ -2,14 +2,14 @@ import type { Translator } from '@markuplint/i18n';
2
2
  import type { Attribute as AttrSpec, AttributeType } from '@markuplint/ml-spec';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
4
  type Invalid = {
5
- invalidType: 'non-existent' | 'invalid-value' | 'disallowed-attr';
6
- message: string;
7
- loc?: Loc;
5
+ invalidType: 'non-existent' | 'invalid-value' | 'disallowed-attr';
6
+ message: string;
7
+ loc?: Loc;
8
8
  };
9
9
  type Loc = {
10
- raw: string;
11
- line: number;
12
- col: number;
10
+ raw: string;
11
+ line: number;
12
+ col: number;
13
13
  };
14
14
  /**
15
15
  * Use in rules `invalid-attr` and `wai-aria`
@@ -19,17 +19,6 @@ type Loc = {
19
19
  * @param isCustomRule
20
20
  * @param spec
21
21
  */
22
- export declare function attrCheck(
23
- t: Translator,
24
- name: string,
25
- value: string,
26
- isCustomRule: boolean,
27
- spec?: AttrSpec,
28
- ): Invalid | false;
29
- export declare function valueCheck(
30
- t: Translator,
31
- name: string,
32
- value: string,
33
- type: ReadonlyDeep<AttributeType>,
34
- ): [string, Loc] | false;
22
+ export declare function attrCheck(t: Translator, name: string, value: string, isCustomRule: boolean, spec?: AttrSpec): Invalid | false;
23
+ export declare function valueCheck(t: Translator, name: string, value: string, type: ReadonlyDeep<AttributeType>): [string, Loc] | false;
35
24
  export {};
@@ -43,7 +43,7 @@ exports.default = (0, ml_core_1.createRule)({
43
43
  if (!('scope' in targetNode && 'line' in targetNode && targetNode.line != null)) {
44
44
  continue;
45
45
  }
46
- const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]+|x[0-9]);/gi, $0 => '*'.repeat($0.length));
46
+ const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]+|#x[0-9a-f]+);/gi, $0 => '*'.repeat($0.length));
47
47
  (0, ml_core_1.getLocationFromChars)(defaultChars, escapedText, targetNode.line, targetNode.col).forEach(location => {
48
48
  report({
49
49
  scope: targetNode.scope,
@@ -29,7 +29,7 @@ export declare function mergeHints(a: Readonly<Hints>, b: Readonly<Hints>): Part
29
29
  need?: string | undefined;
30
30
  }> | undefined;
31
31
  max?: number | undefined;
32
- not?: import("packages/@markuplint/ml-core/lib").DocumentType<import("./types").TagRule[], import("./types").Options> | import("packages/@markuplint/ml-core/lib/ml-dom/node/character-data").MLCharacterData<import("./types").TagRule[], import("./types").Options, import("packages/@markuplint/ml-ast/lib").MLASTAbstractNode> | import("packages/@markuplint/ml-core/lib").Element<import("./types").TagRule[], import("./types").Options> | import("packages/@markuplint/ml-core/lib").Block<import("./types").TagRule[], import("./types").Options> | undefined;
32
+ not?: ChildNode | undefined;
33
33
  transparent?: Element | undefined;
34
34
  }>;
35
35
  export declare function cleanObject<T extends Object>(object: T): Partial<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "3.10.0",
3
+ "version": "3.11.0",
4
4
  "description": "Built-in rules of markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -20,19 +20,19 @@
20
20
  "./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
21
21
  },
22
22
  "dependencies": {
23
- "@markuplint/html-spec": "3.9.0",
24
- "@markuplint/ml-core": "3.10.0",
25
- "@markuplint/ml-spec": "3.9.0",
26
- "@markuplint/selector": "3.9.0",
27
- "@markuplint/shared": "3.6.0",
28
- "@markuplint/types": "3.7.0",
29
- "@types/debug": "^4.1.7",
23
+ "@markuplint/html-spec": "3.10.0",
24
+ "@markuplint/ml-core": "3.11.0",
25
+ "@markuplint/ml-spec": "3.10.0",
26
+ "@markuplint/selector": "3.10.0",
27
+ "@markuplint/shared": "3.7.0",
28
+ "@markuplint/types": "3.8.0",
29
+ "@types/debug": "^4.1.8",
30
30
  "@ungap/structured-clone": "^1.2.0",
31
31
  "ansi-colors": "^4.1.3",
32
32
  "chrono-node": "^2.6.3",
33
33
  "debug": "^4.3.4",
34
- "tslib": "^2.5.0",
35
- "type-fest": "^3.10.0"
34
+ "tslib": "^2.5.3",
35
+ "type-fest": "^3.11.1"
36
36
  },
37
- "gitHead": "af370797bfc887e5a5a2ff57fbaa8392ac98ead2"
37
+ "gitHead": "9547b8dca20736a93e4d01af2d61bee314ba5718"
38
38
  }
@@ -55,3 +55,18 @@ test('in EJS', async () => {
55
55
  });
56
56
  expect(violations.length).toBe(0);
57
57
  });
58
+
59
+ describe('Issues', () => {
60
+ test('#1074', async () => {
61
+ const { violations } = await mlRuleTest(rule, '<span>&#9660;</span><span>&#x25BC;</span><span>&x25BC;</span>');
62
+ expect(violations).toStrictEqual([
63
+ {
64
+ severity: 'error',
65
+ message: 'Illegal characters must escape in character reference',
66
+ line: 1,
67
+ col: 48,
68
+ raw: '&',
69
+ },
70
+ ]);
71
+ });
72
+ });
@@ -33,16 +33,3 @@ test('deprecated', async () => {
33
33
  },
34
34
  ]);
35
35
  });
36
-
37
- test('svg', async () => {
38
- const { violations } = await mlRuleTest(rule, '<svg><altGlyph>text</altGlyph></svg>');
39
- expect(violations).toStrictEqual([
40
- {
41
- severity: 'error',
42
- message: 'The "altGlyph" element is obsolete',
43
- line: 1,
44
- col: 6,
45
- raw: '<altGlyph>',
46
- },
47
- ]);
48
- });
@@ -1368,4 +1368,28 @@ describe('Issues', () => {
1368
1368
  .violations,
1369
1369
  ).toStrictEqual([]);
1370
1370
  });
1371
+
1372
+ test('#1046', async () => {
1373
+ const sourceCode = '<span><div></div></span>';
1374
+ expect(
1375
+ (
1376
+ await mlRuleTest(rule, sourceCode, {
1377
+ rule: {
1378
+ severity: 'warning',
1379
+ },
1380
+ parser: {
1381
+ '.*': '@markuplint/jsx-parser',
1382
+ },
1383
+ })
1384
+ ).violations,
1385
+ ).toStrictEqual([
1386
+ {
1387
+ severity: 'warning',
1388
+ line: 1,
1389
+ col: 7,
1390
+ message: 'The "div" element is not allowed in the "span" element in this context',
1391
+ raw: '<div>',
1392
+ },
1393
+ ]);
1394
+ });
1371
1395
  });
@@ -443,4 +443,25 @@ describe('Issues', () => {
443
443
  expect((await mlRuleTest(rule, '<dialog></dialog>')).violations.length).toBe(1);
444
444
  expect((await mlRuleTest(rule, '<div role="dialog"></div>')).violations.length).toBe(1);
445
445
  });
446
+
447
+ test('#1018', async () => {
448
+ expect(
449
+ (
450
+ await mlRuleTest(rule, '<button><slot /></button>', {
451
+ parser: {
452
+ '.*': '@markuplint/svelte-parser',
453
+ },
454
+ })
455
+ ).violations.length,
456
+ ).toBe(0);
457
+ expect(
458
+ (
459
+ await mlRuleTest(rule, '<button></button>', {
460
+ parser: {
461
+ '.*': '@markuplint/svelte-parser',
462
+ },
463
+ })
464
+ ).violations.length,
465
+ ).toBe(1);
466
+ });
446
467
  });
@@ -1,15 +0,0 @@
1
- import type { Options } from '../types';
2
- import type { ElementChecker } from '@markuplint/ml-core';
3
- import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
4
- export declare const checkingRequiredProp: ElementChecker<
5
- boolean,
6
- Options,
7
- {
8
- role?:
9
- | (ARIARole & {
10
- isImplicit?: boolean;
11
- })
12
- | null;
13
- propSpecs: readonly ARIAProperty[];
14
- }
15
- >;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkingRequiredProp = void 0;
4
- const checkingRequiredProp = ({ el, role, propSpecs }) => t => {
5
- var _a;
6
- if (!role) {
7
- return;
8
- }
9
- if (role.isImplicit) {
10
- return;
11
- }
12
- const requiredProps = role.ownedProperties.filter(s => s.required).map(s => s.name);
13
- for (const requiredProp of requiredProps) {
14
- const has = el.attributes.some(attr => {
15
- const attrName = attr.name.toLowerCase();
16
- return attrName === requiredProp;
17
- });
18
- if (!has) {
19
- const propSpec = propSpecs.find(p => p.name === requiredProp);
20
- return {
21
- scope: el,
22
- message: t('{0:c} on {1}', t('Require {0}', t('the "{0*}" {1}', requiredProp, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`)), t('the "{0*}" {1}', role.name, 'role')),
23
- };
24
- }
25
- }
26
- };
27
- exports.checkingRequiredProp = checkingRequiredProp;
@@ -1,15 +0,0 @@
1
- import type { Options } from '../types';
2
- import type { ElementChecker } from '@markuplint/ml-core';
3
- import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
4
- export declare const checkingRequiredProp: ElementChecker<
5
- boolean,
6
- Options,
7
- {
8
- role?:
9
- | (ARIARole & {
10
- isImplicit?: boolean;
11
- })
12
- | null;
13
- propSpecs: readonly ARIAProperty[];
14
- }
15
- >;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkingRequiredProp = void 0;
4
- const checkingRequiredProp = ({ el, role, propSpecs }) => t => {
5
- var _a;
6
- if (!role) {
7
- return;
8
- }
9
- if (role.isImplicit) {
10
- return;
11
- }
12
- const requiredProps = role.ownedProperties.filter(s => s.required).map(s => s.name);
13
- for (const requiredProp of requiredProps) {
14
- const has = el.attributes.some(attr => {
15
- const attrName = attr.name.toLowerCase();
16
- return attrName === requiredProp;
17
- });
18
- if (!has) {
19
- const propSpec = propSpecs.find(p => p.name === requiredProp);
20
- return {
21
- scope: el,
22
- message: t('{0:c} on {1}', t('Require {0}', t('the "{0*}" {1}', requiredProp, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`)), t('the "{0*}" {1}', role.name, 'role')),
23
- };
24
- }
25
- }
26
- };
27
- exports.checkingRequiredProp = checkingRequiredProp;
@@ -1,15 +0,0 @@
1
- import type { Options } from '../types';
2
- import type { ElementChecker } from '@markuplint/ml-core';
3
- import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
4
- export declare const checkingUnadoptedExplicitRoles: ElementChecker<
5
- boolean,
6
- Options,
7
- {
8
- role?:
9
- | (ARIARole & {
10
- isImplicit?: boolean;
11
- })
12
- | null;
13
- propSpecs: readonly ARIAProperty[];
14
- }
15
- >;
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkingUnadoptedExplicitRoles = void 0;
4
- const checkingUnadoptedExplicitRoles = ({ el, role, propSpecs }) => t => {
5
- if (!role) {
6
- return;
7
- }
8
- if (role.name) {
9
- console.log(el.localName, role.name);
10
- return {
11
- scope: el,
12
- message: '',
13
- };
14
- }
15
- return;
16
- };
17
- exports.checkingUnadoptedExplicitRoles = checkingUnadoptedExplicitRoles;
@@ -1,2 +0,0 @@
1
- declare const _default: Readonly<import('@markuplint/ml-core').RuleSeed<boolean, null>>;
2
- export default _default;
package/lib/xxx/index.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const ml_core_1 = require("@markuplint/ml-core");
4
- exports.default = (0, ml_core_1.createRule)({
5
- defaultValue: true,
6
- defaultOptions: null,
7
- async verify({ document, report, t }) {
8
- // Element
9
- await document.walkOn("Element", (el) => {
10
- const raw = el.raw.trim();
11
- if (/./i.test(raw)) {
12
- report({
13
- scope: el,
14
- message: t("It is {0}", "issue"),
15
- });
16
- }
17
- });
18
- // Attribute
19
- await document.walkOn("Attr", (attr) => {
20
- var _a, _b, _c;
21
- if (/./i.test(attr.name)) {
22
- report({
23
- scope: attr,
24
- line: (_a = attr.nameNode) === null || _a === void 0 ? void 0 : _a.startLine,
25
- col: (_b = attr.nameNode) === null || _b === void 0 ? void 0 : _b.startCol,
26
- raw: (_c = attr.nameNode) === null || _c === void 0 ? void 0 : _c.raw,
27
- message: t("It is {0}", "issue"),
28
- });
29
- }
30
- });
31
- },
32
- });