@markuplint/rules 3.6.1 → 3.7.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,6 +19,17 @@ type Loc = {
19
19
  * @param isCustomRule
20
20
  * @param spec
21
21
  */
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;
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;
24
35
  export {};
package/lib/helpers.d.ts CHANGED
@@ -3,7 +3,10 @@ import type { Translator } from '@markuplint/i18n';
3
3
  import type { PlainData } from '@markuplint/ml-config';
4
4
  import type { Element, RuleConfigValue, Document } from '@markuplint/ml-core';
5
5
  import type { Attribute } from '@markuplint/ml-spec';
6
- export declare function attrMatches<T extends RuleConfigValue, O extends PlainData>(node: Element<T, O>, condition: Attribute['condition']): boolean;
6
+ export declare function attrMatches<T extends RuleConfigValue, O extends PlainData>(
7
+ node: Element<T, O>,
8
+ condition: Attribute['condition'],
9
+ ): boolean;
7
10
  export declare function match(needle: string, pattern: string): boolean;
8
11
  /**
9
12
  * PotentialCustomElementName
@@ -21,27 +24,42 @@ export declare function match(needle: string, pattern: string): boolean;
21
24
  * Originally, it is not possible to define a name including ASCII upper alphas in the custom element, but it is not treated as illegal by the HTML parser.
22
25
  */
23
26
  export declare const rePCENChar: string;
24
- export declare function isValidAttr(t: Translator, name: string, value: string, isDynamicValue: boolean, node: Element<any, any>, attrSpecs: readonly Attribute[], log?: Log): false | {
25
- invalidType: "non-existent" | "invalid-value" | "disallowed-attr";
26
- message: string;
27
- loc?: {
28
- raw: string;
29
- line: number;
30
- col: number;
31
- } | undefined;
32
- };
27
+ export declare function isValidAttr(
28
+ t: Translator,
29
+ name: string,
30
+ value: string,
31
+ isDynamicValue: boolean,
32
+ node: Element<any, any>,
33
+ attrSpecs: readonly Attribute[],
34
+ log?: Log,
35
+ ):
36
+ | false
37
+ | {
38
+ invalidType: 'non-existent' | 'invalid-value' | 'disallowed-attr';
39
+ message: string;
40
+ loc?:
41
+ | {
42
+ raw: string;
43
+ line: number;
44
+ col: number;
45
+ }
46
+ | undefined;
47
+ };
33
48
  export declare function toNormalizedValue(value: string, spec: Attribute): string;
34
49
  export declare function accnameMayBeMutable(el: Element<any, any>, document: Document<any, any>): boolean;
35
- export declare function getOwnedLabel<V extends RuleConfigValue, O extends PlainData>(el: Element<V, O>, document: Document<V, O>): Element<V, O> | null;
50
+ export declare function getOwnedLabel<V extends RuleConfigValue, O extends PlainData>(
51
+ el: Element<V, O>,
52
+ document: Document<V, O>,
53
+ ): Element<V, O> | null;
36
54
  export declare class Collection<T> {
37
- #private;
38
- constructor(...items: readonly (T | null | undefined)[]);
39
- [Symbol.iterator](): Iterator<T>;
40
- add(...items: readonly (T | null | undefined)[]): void;
41
- toArray(): readonly T[];
55
+ #private;
56
+ constructor(...items: readonly (T | null | undefined)[]);
57
+ [Symbol.iterator](): Iterator<T>;
58
+ add(...items: readonly (T | null | undefined)[]): void;
59
+ toArray(): readonly T[];
42
60
  }
43
61
  type Writeable<T> = {
44
- -readonly [P in keyof T]: T[P];
62
+ -readonly [P in keyof T]: T[P];
45
63
  };
46
64
  export declare function deepCopy<T>(value: T): Writeable<T>;
47
65
  export {};
package/lib/index.d.ts CHANGED
@@ -1,175 +1,102 @@
1
1
  declare const rules: {
2
- readonly 'attr-duplication': Readonly<
3
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
4
- >;
5
- readonly 'attr-value-quotes': Readonly<
6
- import('@markuplint/ml-core').RuleSeed<import('./attr-value-quotes').Type, undefined>
7
- >;
8
- readonly 'case-sensitive-attr-name': Readonly<
9
- import('@markuplint/ml-core').RuleSeed<import('./case-sensitive-attr-name').Value, undefined>
10
- >;
11
- readonly 'case-sensitive-tag-name': Readonly<
12
- import('@markuplint/ml-core').RuleSeed<import('./case-sensitive-tag-name').Value, undefined>
13
- >;
14
- readonly 'character-reference': Readonly<
15
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
16
- >;
17
- readonly 'class-naming': Readonly<
18
- import('@markuplint/ml-core').RuleSeed<import('./class-naming').Value, undefined>
19
- >;
20
- readonly 'deprecated-attr': Readonly<
21
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
22
- >;
23
- readonly 'deprecated-element': Readonly<
24
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
25
- >;
26
- readonly 'disallowed-element': Readonly<import('@markuplint/ml-core').RuleSeed<string[], undefined>>;
27
- readonly doctype: Readonly<
28
- import('@markuplint/ml-core').RuleSeed<
29
- 'always',
30
- {
31
- denyObsoleteType: boolean;
32
- }
33
- >
34
- >;
35
- readonly 'end-tag': Readonly<import('@markuplint/ml-core').RuleSeed<boolean, undefined>>;
36
- readonly 'id-duplication': Readonly<
37
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
38
- >;
39
- readonly 'ineffective-attr': Readonly<
40
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
41
- >;
42
- readonly 'invalid-attr': Readonly<
43
- import('@markuplint/ml-core').RuleSeed<
44
- boolean,
45
- {
46
- attrs?:
47
- | Record<
48
- string,
49
- | {
50
- enum: [string, ...string[]];
51
- }
52
- | {
53
- pattern: string;
54
- }
55
- | {
56
- type: import('packages/@markuplint/ml-spec/lib').AttributeType;
57
- }
58
- | {
59
- disallowed: true;
60
- }
61
- >
62
- | undefined;
63
- ignoreAttrNamePrefix?: string | string[] | undefined;
64
- allowToAddPropertiesForPretender?: boolean | undefined;
65
- }
66
- >
67
- >;
68
- readonly 'label-has-control': Readonly<
69
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
70
- >;
71
- readonly 'landmark-roles': Readonly<
72
- import('@markuplint/ml-core').RuleSeed<
73
- boolean,
74
- {
75
- ignoreRoles: (
76
- | ('banner' | 'main' | 'complementary' | 'contentinfo')
77
- | 'form'
78
- | 'navigation'
79
- | 'region'
80
- )[];
81
- labelEachArea: boolean;
82
- }
83
- >
84
- >;
85
- readonly 'no-boolean-attr-value': Readonly<
86
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
87
- >;
88
- readonly 'no-default-value': Readonly<
89
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
90
- >;
91
- readonly 'no-empty-palpable-content': Readonly<
92
- import('@markuplint/ml-core').RuleSeed<
93
- boolean,
94
- {
95
- extendsExposableElements?: boolean | undefined;
96
- ignoreIfAriaBusy?: boolean | undefined;
97
- }
98
- >
99
- >;
100
- readonly 'no-hard-code-id': Readonly<
101
- import('@markuplint/ml-core').RuleSeed<import('@markuplint/ml-core').RuleConfigValue, undefined>
102
- >;
103
- readonly 'no-refer-to-non-existent-id': Readonly<
104
- import('@markuplint/ml-core').RuleSeed<
105
- import('@markuplint/ml-core').RuleConfigValue,
106
- {
107
- ariaVersion: import('packages/@markuplint/ml-spec/lib').ARIAVersion;
108
- fragmentRefersNameAttr: boolean;
109
- }
110
- >
111
- >;
112
- readonly 'no-use-event-handler-attr': Readonly<
113
- import('@markuplint/ml-core').RuleSeed<
114
- boolean,
115
- {
116
- ignore?: string | string[] | undefined;
117
- }
118
- >
119
- >;
120
- readonly 'permitted-contents': Readonly<
121
- import('@markuplint/ml-core').RuleSeed<
122
- import('./permitted-contents/types').TagRule[],
123
- import('./permitted-contents/types').Options
124
- >
125
- >;
126
- readonly 'placeholder-label-option': Readonly<import('@markuplint/ml-core').RuleSeed<boolean, undefined>>;
127
- readonly 'require-accessible-name': Readonly<
128
- import('@markuplint/ml-core').RuleSeed<
129
- boolean,
130
- {
131
- ariaVersion: import('packages/@markuplint/ml-spec/lib').ARIAVersion;
132
- }
133
- >
134
- >;
135
- readonly 'require-datetime': Readonly<
136
- import('@markuplint/ml-core').RuleSeed<
137
- boolean,
138
- {
139
- langs?: import('./require-datetime/types').Lang[] | undefined;
140
- }
141
- >
142
- >;
143
- readonly 'required-attr': Readonly<
144
- import('@markuplint/ml-core').RuleSeed<
145
- | string
146
- | (
147
- | string
148
- | {
149
- name: string;
150
- value: string | string[];
151
- }
152
- )[],
153
- undefined
154
- >
155
- >;
156
- readonly 'required-element': Readonly<
157
- import('@markuplint/ml-core').RuleSeed<
158
- string[],
159
- {
160
- ignoreHasMutableContents: boolean;
161
- }
162
- >
163
- >;
164
- readonly 'required-h1': Readonly<import('@markuplint/ml-core').RuleSeed<boolean, import('./required-h1').Options>>;
165
- readonly 'use-list': Readonly<
166
- import('@markuplint/ml-core').RuleSeed<
167
- readonly string[],
168
- {
169
- spaceNeededBullets?: string[] | undefined;
170
- }
171
- >
172
- >;
173
- readonly 'wai-aria': Readonly<import('@markuplint/ml-core').RuleSeed<boolean, import('./wai-aria/types').Options>>;
2
+ readonly 'attr-duplication': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
3
+ readonly 'attr-value-quotes': Readonly<import("@markuplint/ml-core").RuleSeed<import("./attr-value-quotes").Type, undefined>>;
4
+ readonly 'case-sensitive-attr-name': Readonly<import("@markuplint/ml-core").RuleSeed<import("./case-sensitive-attr-name").Value, undefined>>;
5
+ readonly 'case-sensitive-tag-name': Readonly<import("@markuplint/ml-core").RuleSeed<import("./case-sensitive-tag-name").Value, undefined>>;
6
+ readonly 'character-reference': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
7
+ readonly 'class-naming': Readonly<import("@markuplint/ml-core").RuleSeed<import("./class-naming").Value, undefined>>;
8
+ readonly 'deprecated-attr': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
9
+ readonly 'deprecated-element': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
10
+ readonly 'disallowed-element': Readonly<import("@markuplint/ml-core").RuleSeed<string[], undefined>>;
11
+ readonly doctype: Readonly<import("@markuplint/ml-core").RuleSeed<"always", {
12
+ denyObsoleteType: boolean;
13
+ }>>;
14
+ readonly 'end-tag': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
15
+ readonly 'id-duplication': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
16
+ readonly 'ineffective-attr': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
17
+ readonly 'invalid-attr': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
18
+ allowAttrs?: Record<string, {
19
+ enum: [string, ...string[]];
20
+ } | {
21
+ pattern: string;
22
+ } | {
23
+ type: import("packages/@markuplint/ml-spec/lib").AttributeType;
24
+ }> | (string | {
25
+ name: string;
26
+ value: ({
27
+ enum: [string, ...string[]];
28
+ } | {
29
+ pattern: string;
30
+ } | {
31
+ type: import("packages/@markuplint/ml-spec/lib").AttributeType;
32
+ }) | import("packages/@markuplint/ml-spec/lib").AttributeType;
33
+ })[] | undefined;
34
+ disallowAttrs?: Record<string, {
35
+ enum: [string, ...string[]];
36
+ } | {
37
+ pattern: string;
38
+ } | {
39
+ type: import("packages/@markuplint/ml-spec/lib").AttributeType;
40
+ }> | (string | {
41
+ name: string;
42
+ value: ({
43
+ enum: [string, ...string[]];
44
+ } | {
45
+ pattern: string;
46
+ } | {
47
+ type: import("packages/@markuplint/ml-spec/lib").AttributeType;
48
+ }) | import("packages/@markuplint/ml-spec/lib").AttributeType;
49
+ })[] | undefined;
50
+ ignoreAttrNamePrefix?: string | string[] | undefined;
51
+ allowToAddPropertiesForPretender?: boolean | undefined;
52
+ attrs?: Record<string, ({
53
+ enum: [string, ...string[]];
54
+ } | {
55
+ pattern: string;
56
+ } | {
57
+ type: import("packages/@markuplint/ml-spec/lib").AttributeType;
58
+ }) | {
59
+ disallowed: true;
60
+ }> | undefined;
61
+ }>>;
62
+ readonly 'label-has-control': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
63
+ readonly 'landmark-roles': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
64
+ ignoreRoles: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[];
65
+ labelEachArea: boolean;
66
+ }>>;
67
+ readonly 'no-boolean-attr-value': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
68
+ readonly 'no-default-value': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
69
+ readonly 'no-empty-palpable-content': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
70
+ extendsExposableElements?: boolean | undefined;
71
+ ignoreIfAriaBusy?: boolean | undefined;
72
+ }>>;
73
+ readonly 'no-hard-code-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
74
+ readonly 'no-refer-to-non-existent-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
75
+ ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
76
+ fragmentRefersNameAttr: boolean;
77
+ }>>;
78
+ readonly 'no-use-event-handler-attr': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
79
+ ignore?: string | string[] | undefined;
80
+ }>>;
81
+ readonly 'permitted-contents': Readonly<import("@markuplint/ml-core").RuleSeed<import("./permitted-contents/types").TagRule[], import("./permitted-contents/types").Options>>;
82
+ readonly 'placeholder-label-option': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
83
+ readonly 'require-accessible-name': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
84
+ ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
85
+ }>>;
86
+ readonly 'require-datetime': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
87
+ langs?: import("./require-datetime/types").Lang[] | undefined;
88
+ }>>;
89
+ readonly 'required-attr': Readonly<import("@markuplint/ml-core").RuleSeed<string | (string | {
90
+ name: string;
91
+ value: string | string[];
92
+ })[], undefined>>;
93
+ readonly 'required-element': Readonly<import("@markuplint/ml-core").RuleSeed<string[], {
94
+ ignoreHasMutableContents: boolean;
95
+ }>>;
96
+ readonly 'required-h1': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, import("./required-h1").Options>>;
97
+ readonly 'use-list': Readonly<import("@markuplint/ml-core").RuleSeed<readonly string[], {
98
+ spaceNeededBullets?: string[] | undefined;
99
+ }>>;
100
+ readonly 'wai-aria': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, import("./wai-aria/types").Options>>;
174
101
  };
175
102
  export default rules;
@@ -1,21 +1,37 @@
1
1
  import type { AttributeType } from '@markuplint/ml-spec';
2
2
  type Option = {
3
- attrs?: Record<string, Rule>;
4
- ignoreAttrNamePrefix?: string | string[];
5
- allowToAddPropertiesForPretender?: boolean;
3
+ /**
4
+ * @since 3.7.0
5
+ */
6
+ allowAttrs?: (string | Attr)[] | Record<string, ValueRule>;
7
+ /**
8
+ * @since 3.7.0
9
+ */
10
+ disallowAttrs?: (string | Attr)[] | Record<string, ValueRule>;
11
+ ignoreAttrNamePrefix?: string | string[];
12
+ allowToAddPropertiesForPretender?: boolean;
13
+ /**
14
+ * @deprecated Since version 3.7.0. Use `allowAttrs` or `disallowAttrs` instead.
15
+ * This option (`attr`) is now considered ambiguous and may lead to confusion.
16
+ * Please use the more explicit `allowAttrs` or `disallowAttrs` option
17
+ * to specify allowed attributes for the `invalid-attr` rule.
18
+ * @see {@link Option.allowAttrs}
19
+ * @see {@link Option.disallowAttrs}
20
+ */
21
+ attrs?: Record<string, ValueRule | {
22
+ disallowed: true;
23
+ }>;
6
24
  };
7
- type Rule =
8
- | {
9
- enum: [string, ...string[]];
10
- }
11
- | {
12
- pattern: string;
13
- }
14
- | {
15
- type: AttributeType;
16
- }
17
- | {
18
- disallowed: true;
19
- };
20
- declare const _default: Readonly<import('@markuplint/ml-core').RuleSeed<boolean, Option>>;
25
+ type Attr = {
26
+ name: string;
27
+ value: AttributeType | ValueRule;
28
+ };
29
+ type ValueRule = {
30
+ enum: [string, ...string[]];
31
+ } | {
32
+ pattern: string;
33
+ } | {
34
+ type: AttributeType;
35
+ };
36
+ declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
21
37
  export default _default;
@@ -9,7 +9,7 @@ exports.default = (0, ml_core_1.createRule)({
9
9
  defaultOptions: {},
10
10
  async verify({ document, report, t }) {
11
11
  await document.walkOn('Attr', attr => {
12
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
12
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
13
13
  // Default
14
14
  const allowToAddPropertiesForPretender = (_a = attr.rule.options.allowToAddPropertiesForPretender) !== null && _a !== void 0 ? _a : true;
15
15
  if (attr.isDirective) {
@@ -42,33 +42,126 @@ exports.default = (0, ml_core_1.createRule)({
42
42
  }
43
43
  }
44
44
  let invalid = false;
45
- const customRule = attr.rule.options.attrs ? attr.rule.options.attrs[name] : null;
46
- if (customRule) {
47
- if ('enum' in customRule) {
45
+ const allowAttrs = {};
46
+ const disallowAttrs = {};
47
+ if (attr.rule.options.allowAttrs) {
48
+ if (Array.isArray(attr.rule.options.allowAttrs)) {
49
+ for (const allowAttr of attr.rule.options.allowAttrs) {
50
+ if (typeof allowAttr === 'string') {
51
+ allowAttrs[allowAttr] = { type: 'Any' };
52
+ continue;
53
+ }
54
+ if (isValueRule(allowAttr.value)) {
55
+ allowAttrs[allowAttr.name] = allowAttr.value;
56
+ continue;
57
+ }
58
+ allowAttrs[allowAttr.name] = { type: allowAttr.value };
59
+ }
60
+ }
61
+ else {
62
+ for (const [attrName, valueRule] of Object.entries(attr.rule.options.allowAttrs)) {
63
+ allowAttrs[attrName] = valueRule;
64
+ }
65
+ }
66
+ }
67
+ if (attr.rule.options.disallowAttrs) {
68
+ if (Array.isArray(attr.rule.options.disallowAttrs)) {
69
+ for (const disallowAttr of attr.rule.options.disallowAttrs) {
70
+ if (typeof disallowAttr === 'string') {
71
+ disallowAttrs[disallowAttr] = { type: 'Any' };
72
+ continue;
73
+ }
74
+ if (isValueRule(disallowAttr.value)) {
75
+ disallowAttrs[disallowAttr.name] = disallowAttr.value;
76
+ continue;
77
+ }
78
+ disallowAttrs[disallowAttr.name] = { type: disallowAttr.value };
79
+ }
80
+ }
81
+ else {
82
+ for (const [attrName, valueRule] of Object.entries(attr.rule.options.disallowAttrs)) {
83
+ disallowAttrs[attrName] = valueRule;
84
+ }
85
+ }
86
+ }
87
+ if (attr.rule.options.attrs) {
88
+ for (const [attrName, valueRule] of Object.entries(attr.rule.options.attrs)) {
89
+ if ('disallowed' in valueRule) {
90
+ disallowAttrs[attrName] = { type: 'Any' };
91
+ }
92
+ else {
93
+ allowAttrs[attrName] = valueRule;
94
+ }
95
+ }
96
+ }
97
+ const allowValue = (_b = allowAttrs[name]) !== null && _b !== void 0 ? _b : null;
98
+ const disallowValue = (_c = disallowAttrs[name]) !== null && _c !== void 0 ? _c : null;
99
+ if (allowValue) {
100
+ if ('enum' in allowValue) {
48
101
  invalid = (0, attr_check_1.attrCheck)(t, name.toLowerCase(), value, true, {
49
102
  name,
50
103
  type: {
51
- enum: customRule.enum,
104
+ enum: allowValue.enum,
52
105
  },
53
106
  description: '',
54
107
  });
55
108
  }
56
- else if ('pattern' in customRule) {
57
- if (!(0, helpers_1.match)(value, customRule.pattern)) {
109
+ else if ('pattern' in allowValue) {
110
+ if (!(0, helpers_1.match)(value, allowValue.pattern)) {
111
+ invalid = {
112
+ invalidType: 'invalid-value',
113
+ message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), allowValue.pattern),
114
+ };
115
+ }
116
+ }
117
+ else if ('type' in allowValue) {
118
+ invalid = (0, attr_check_1.attrCheck)(t, name, value, true, { name, type: allowValue.type, description: '' });
119
+ }
120
+ }
121
+ else if (disallowValue) {
122
+ if ('enum' in disallowValue) {
123
+ const checkResult = (0, attr_check_1.attrCheck)(t, name.toLowerCase(), value, true, {
124
+ name,
125
+ type: {
126
+ enum: disallowValue.enum,
127
+ },
128
+ description: '',
129
+ });
130
+ if (checkResult === false) {
58
131
  invalid = {
59
132
  invalidType: 'invalid-value',
60
- message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), customRule.pattern),
133
+ message: t('{0} is disallowed to accept the following values: {1}', t('the "{0*}" {1}', name, 'attribute'), t(disallowValue.enum)),
61
134
  };
62
135
  }
63
136
  }
64
- else if ('type' in customRule) {
65
- invalid = (0, attr_check_1.attrCheck)(t, name, value, true, { name, type: customRule.type, description: '' });
137
+ else if ('pattern' in disallowValue) {
138
+ if ((0, helpers_1.match)(value, disallowValue.pattern)) {
139
+ invalid = {
140
+ invalidType: 'invalid-value',
141
+ message: t('{0} is matched with the below disallowed patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), disallowValue.pattern),
142
+ };
143
+ }
66
144
  }
67
- else if ('disallowed' in customRule && customRule.disallowed) {
68
- invalid = {
69
- invalidType: 'non-existent',
70
- message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
71
- };
145
+ else if ('type' in disallowValue) {
146
+ if (disallowValue.type === 'Any') {
147
+ invalid = {
148
+ invalidType: 'non-existent',
149
+ message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
150
+ };
151
+ }
152
+ else {
153
+ const checkResult = (0, attr_check_1.attrCheck)(t, name, value, true, {
154
+ name,
155
+ type: disallowValue.type,
156
+ description: '',
157
+ });
158
+ if (checkResult === false) {
159
+ invalid = {
160
+ invalidType: 'invalid-value',
161
+ message: t('{0} is disallowed', t('{0} of {1}', t('the {0}', 'type'), t('the "{0*}" {1}', name, 'attribute'))),
162
+ };
163
+ }
164
+ }
72
165
  }
73
166
  }
74
167
  else if (attr.ownerElement.elementType === 'html' && attrSpecs) {
@@ -91,16 +184,16 @@ exports.default = (0, ml_core_1.createRule)({
91
184
  report({
92
185
  scope: attr,
93
186
  message: invalid.message,
94
- line: ((_b = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startLine) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = invalid.loc) === null || _c === void 0 ? void 0 : _c.line) !== null && _d !== void 0 ? _d : 0),
187
+ line: ((_d = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startLine) !== null && _d !== void 0 ? _d : 0) + ((_f = (_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.line) !== null && _f !== void 0 ? _f : 0),
95
188
  col: invalid.loc && invalid.loc.line > 0
96
- ? ((_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.col) + 1
97
- : ((_f = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startCol) !== null && _f !== void 0 ? _f : 0) + ((_h = (_g = invalid.loc) === null || _g === void 0 ? void 0 : _g.col) !== null && _h !== void 0 ? _h : 0),
98
- raw: (_k = (_j = invalid.loc) === null || _j === void 0 ? void 0 : _j.raw) !== null && _k !== void 0 ? _k : value,
189
+ ? ((_g = invalid.loc) === null || _g === void 0 ? void 0 : _g.col) + 1
190
+ : ((_h = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startCol) !== null && _h !== void 0 ? _h : 0) + ((_k = (_j = invalid.loc) === null || _j === void 0 ? void 0 : _j.col) !== null && _k !== void 0 ? _k : 0),
191
+ raw: (_m = (_l = invalid.loc) === null || _l === void 0 ? void 0 : _l.raw) !== null && _m !== void 0 ? _m : value,
99
192
  });
100
193
  break;
101
194
  }
102
195
  case 'non-existent': {
103
- if (allowToAddPropertiesForPretender && ((_l = attr.ownerElement.pretenderContext) === null || _l === void 0 ? void 0 : _l.type) === 'origin') {
196
+ if (allowToAddPropertiesForPretender && ((_o = attr.ownerElement.pretenderContext) === null || _o === void 0 ? void 0 : _o.type) === 'origin') {
104
197
  return;
105
198
  }
106
199
  const spec = (0, ml_core_1.getSpec)(attr.ownerElement, document.specs.specs);
@@ -120,3 +213,29 @@ exports.default = (0, ml_core_1.createRule)({
120
213
  });
121
214
  },
122
215
  });
216
+ function isValueRule(
217
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
218
+ value) {
219
+ if (typeof value === 'string') {
220
+ return false;
221
+ }
222
+ if ('enum' in value) {
223
+ if (Object.keys(value).length > 1) {
224
+ return false;
225
+ }
226
+ return true;
227
+ }
228
+ if ('token' in value) {
229
+ return false;
230
+ }
231
+ if ('pattern' in value) {
232
+ return true;
233
+ }
234
+ if (value.type === 'integer' || value.type === 'float') {
235
+ return false;
236
+ }
237
+ if (Object.keys(value).length > 1) {
238
+ return false;
239
+ }
240
+ return true;
241
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "3.6.1",
3
+ "version": "3.7.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>",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@markuplint/html-spec": "3.6.1",
24
- "@markuplint/ml-core": "3.6.1",
24
+ "@markuplint/ml-core": "3.7.0",
25
25
  "@markuplint/ml-spec": "3.6.1",
26
26
  "@markuplint/selector": "3.6.1",
27
27
  "@markuplint/shared": "3.5.0",
@@ -36,5 +36,5 @@
36
36
  "@types/debug": "^4.1.7",
37
37
  "type-fest": "^3.6.1"
38
38
  },
39
- "gitHead": "3cdf5a088b2da03773d5d4461d0e65ec32290a00"
39
+ "gitHead": "884e8dbf60ec2a350761d5cda3cdc0725881b9dc"
40
40
  }