@markuplint/ml-core 2.0.0-rc.0 → 2.0.0-rc.6

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.
@@ -36,4 +36,5 @@ export default class MLDOMAttribute extends MLDOMToken<MLASTHTMLAttr> {
36
36
  raw: string;
37
37
  };
38
38
  toString(withSpace?: boolean): string;
39
+ toNormalizeString(): string;
39
40
  }
@@ -69,5 +69,12 @@ class MLDOMAttribute extends token_1.default {
69
69
  toString(withSpace = true) {
70
70
  return (withSpace ? this.spacesBeforeName.raw : '') + this.raw;
71
71
  }
72
+ toNormalizeString() {
73
+ return (this.name.originRaw +
74
+ this.equal.originRaw +
75
+ this.startQuote.originRaw +
76
+ this.value.originRaw +
77
+ this.endQuote.originRaw);
78
+ }
72
79
  }
73
80
  exports.default = MLDOMAttribute;
@@ -1,7 +1,7 @@
1
1
  import type { Document } from '../';
2
2
  import type { RuleInfo } from '../../';
3
3
  import type { AnonymousNode, IMLDOMNode, NodeType } from '../types';
4
- import type { MLDOMElement, MLDOMOmittedElement } from './';
4
+ import type { MLDOMElement, MLDOMOmittedElement, MLDOMPreprocessorSpecificBlock } from './';
5
5
  import type { MLASTAbstructNode } from '@markuplint/ml-ast';
6
6
  import type { AnyRule, RuleConfigValue } from '@markuplint/ml-config';
7
7
  import MLDOMToken from './token';
@@ -11,13 +11,14 @@ export default abstract class MLDOMNode<T extends RuleConfigValue, O = null, A e
11
11
  readonly rules: Record<string, AnyRule>;
12
12
  protected _astToken: A;
13
13
  constructor(astNode: A, document: Document<T, O>);
14
- get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
14
+ get parentNode(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
15
15
  get prevNode(): AnonymousNode<T, O> | null;
16
16
  get nextNode(): AnonymousNode<T, O> | null;
17
- get syntaxicalParentNode(): MLDOMElement<T, O> | null;
17
+ get syntaxicalParentNode(): MLDOMElement<T, O> | MLDOMPreprocessorSpecificBlock<T, O> | null;
18
18
  get prevToken(): AnonymousNode<T, O> | null;
19
19
  get nodeStore(): import("../helper").NodeStore;
20
- toString(): string;
21
- is(type: NodeType): boolean;
22
20
  get rule(): RuleInfo<T, O>;
21
+ getParentElement(): MLDOMElement<T, O> | MLDOMOmittedElement<T, O> | null;
22
+ is(type: NodeType): boolean;
23
+ toString(): string;
23
24
  }
@@ -70,23 +70,34 @@ class MLDOMNode extends token_1.default {
70
70
  get nodeStore() {
71
71
  return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").nodeStore;
72
72
  }
73
- toString() {
74
- return this.raw;
75
- }
76
- is(type) {
77
- return this.type === type;
78
- }
79
73
  get rule() {
80
74
  if (!(0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule) {
81
75
  throw new Error('Invalid call.');
82
76
  }
83
77
  const name = (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.name;
84
78
  const rule = this.rules[name];
85
- if (rule == null) {
86
- throw new Error('Invalid call "rule" property.');
87
- }
88
79
  return (0, tslib_1.__classPrivateFieldGet)(this, _MLDOMNode_doc, "f").currentRule.optimizeOption(rule);
89
80
  }
81
+ getParentElement() {
82
+ let parent = this.parentNode;
83
+ if (!parent) {
84
+ return null;
85
+ }
86
+ while (parent) {
87
+ if (parent.type === 'PSBlock') {
88
+ parent = parent.parentNode;
89
+ continue;
90
+ }
91
+ return parent;
92
+ }
93
+ return null;
94
+ }
95
+ is(type) {
96
+ return this.type === type;
97
+ }
98
+ toString() {
99
+ return this.raw;
100
+ }
90
101
  }
91
102
  exports.default = MLDOMNode;
92
103
  _MLDOMNode_doc = new WeakMap(), _MLDOMNode_prevToken = new WeakMap();
@@ -20,4 +20,5 @@ export default class MLDOMPreprocessorSpecificAttribute extends MLDOMToken<MLAST
20
20
  raw: string;
21
21
  };
22
22
  toString(): string;
23
+ toNormalizeString(): string;
23
24
  }
@@ -30,5 +30,8 @@ class MLDOMPreprocessorSpecificAttribute extends token_1.default {
30
30
  toString() {
31
31
  return this.raw;
32
32
  }
33
+ toNormalizeString() {
34
+ return this.raw;
35
+ }
33
36
  }
34
37
  exports.default = MLDOMPreprocessorSpecificAttribute;
@@ -1,7 +1,8 @@
1
+ import type { Ruleset } from '..';
1
2
  import type Document from '../ml-dom/document';
2
3
  import type { RuleSeed } from './types';
3
4
  import type { LocaleSet } from '@markuplint/i18n';
4
- import type { RuleConfig, RuleConfigValue, RuleInfo, Severity, Violation } from '@markuplint/ml-config';
5
+ import type { GlobalRuleInfo, RuleConfig, RuleConfigValue, RuleInfo, Rules, Severity, Violation } from '@markuplint/ml-config';
5
6
  export declare class MLRule<T extends RuleConfigValue, O = null> {
6
7
  #private;
7
8
  readonly name: string;
@@ -22,6 +23,8 @@ export declare class MLRule<T extends RuleConfigValue, O = null> {
22
23
  name: string;
23
24
  });
24
25
  verify(document: Document<T, O>, locale: LocaleSet, globalRule: RuleInfo<T, O>, fix: boolean): Promise<Violation[]>;
25
- optimizeOption(configSettings: T | RuleConfig<T, O>): RuleInfo<T, O>;
26
+ getRuleInfo(ruleSet: Ruleset, ruleName: string): GlobalRuleInfo<T, O>;
27
+ _optimize(rules: Rules | undefined, ruleName: string): RuleInfo<T, O>;
28
+ optimizeOption(configSettings: T | RuleConfig<T, O> | undefined): RuleInfo<T, O>;
26
29
  }
27
30
  export declare type AnyMLRule = MLRule<RuleConfigValue, unknown>;
@@ -6,12 +6,13 @@ const tslib_1 = require("tslib");
6
6
  const ml_rule_context_1 = require("./ml-rule-context");
7
7
  class MLRule {
8
8
  constructor(o) {
9
+ var _a, _b;
9
10
  _MLRule_v.set(this, void 0);
10
11
  _MLRule_f.set(this, void 0);
11
12
  this.name = o.name;
12
13
  this.defaultServerity = o.defaultServerity || 'error';
13
- this.defaultValue = o.defaultValue;
14
- this.defaultOptions = o.defaultOptions;
14
+ this.defaultValue = (_a = o.defaultValue) !== null && _a !== void 0 ? _a : true;
15
+ this.defaultOptions = (_b = o.defaultOptions) !== null && _b !== void 0 ? _b : null;
15
16
  (0, tslib_1.__classPrivateFieldSet)(this, _MLRule_v, o.verify, "f");
16
17
  (0, tslib_1.__classPrivateFieldSet)(this, _MLRule_f, o.fix, "f");
17
18
  }
@@ -79,8 +80,21 @@ class MLRule {
79
80
  document.setRule(null);
80
81
  return violation;
81
82
  }
83
+ getRuleInfo(ruleSet, ruleName) {
84
+ const info = this._optimize(ruleSet.rules, ruleName);
85
+ return {
86
+ ...info,
87
+ nodeRules: ruleSet.nodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
88
+ childNodeRules: ruleSet.childNodeRules.map(r => this._optimize(r.rules, ruleName)).filter(r => !r.disabled),
89
+ };
90
+ }
91
+ _optimize(rules, ruleName) {
92
+ const rule = (rules && rules[ruleName]) || false;
93
+ const info = this.optimizeOption(rule);
94
+ return info;
95
+ }
82
96
  optimizeOption(configSettings) {
83
- if (typeof configSettings === 'boolean') {
97
+ if (configSettings === undefined || typeof configSettings === 'boolean') {
84
98
  return {
85
99
  disabled: !configSettings,
86
100
  severity: this.defaultServerity,
@@ -1,9 +1,9 @@
1
1
  import type { MLRuleContext } from './ml-rule-context';
2
2
  import type { RuleConfigValue, Severity } from '@markuplint/ml-config';
3
- export declare type RuleSeed<T extends RuleConfigValue, O = null> = {
3
+ export declare type RuleSeed<T extends RuleConfigValue = boolean, O = null> = {
4
4
  defaultServerity?: Severity;
5
- defaultValue: T;
6
- defaultOptions: O;
5
+ defaultValue?: T;
6
+ defaultOptions?: O;
7
7
  verify(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
8
8
  fix?(context: ReturnType<MLRuleContext<T, O>['provide']>): void | Promise<void>;
9
9
  };
@@ -1,54 +1,194 @@
1
1
  {
2
2
  "rules": {
3
3
  "attr-duplication": true,
4
+ "attr-equal-space-after": false,
5
+ "attr-equal-space-before": false,
6
+ "attr-spacing": false,
7
+ "attr-value-quotes": false,
8
+ "case-sensitive-attr-name": false,
9
+ "case-sensitive-tag-name": false,
4
10
  "character-reference": true,
11
+ "class-naming": false,
5
12
  "deprecated-attr": true,
6
13
  "deprecated-element": true,
14
+ "disallowed-element": ["hgroup"],
7
15
  "doctype": true,
16
+ "end-tag": false,
8
17
  "id-duplication": true,
18
+ "indentation": false,
19
+ "ineffective-attr": true,
20
+ "invalid-attr": {
21
+ "option": {
22
+ "attrs": {
23
+ "autofocus": {
24
+ "disallowed": true
25
+ },
26
+ "accesskey": {
27
+ "disallowed": true
28
+ },
29
+ "tabindex": {
30
+ "enum": ["-1", "0"]
31
+ }
32
+ }
33
+ }
34
+ },
35
+ "landmark-roles": true,
36
+ "no-boolean-attr-value": true,
37
+ "no-default-value": false,
38
+ "no-hard-code-id": false,
39
+ "no-refer-to-non-existent-id": true,
40
+ "no-use-event-handler-attr": false,
9
41
  "permitted-contents": true,
10
42
  "required-attr": true,
11
- "invalid-attr": true,
12
- "landmark-roles": true,
43
+ "required-element": false,
13
44
  "required-h1": true,
14
45
  "wai-aria": true
15
46
  },
16
47
  "nodeRules": [
17
48
  {
18
- "selector": "html",
49
+ "selector": ":where(html)",
19
50
  "rules": {
20
51
  "required-attr": ["lang"]
21
52
  }
22
53
  },
23
54
  {
24
- "selector": "script[src]",
55
+ "selector": ":where(head)",
56
+ "rules": {
57
+ "required-element": ["meta[charset=\"UTF-8\" i]"]
58
+ }
59
+ },
60
+ {
61
+ "selector": ":where(meta[property])",
62
+ "rules": {
63
+ "invalid-attr": {
64
+ "option": {
65
+ "attrs": {
66
+ "property": {
67
+ "pattern": "/^og:[a-z_]+/"
68
+ },
69
+ "content": {
70
+ "type": "NoEmptyAny"
71
+ }
72
+ }
73
+ }
74
+ },
75
+ "required-attr": false
76
+ }
77
+ },
78
+ {
79
+ "selector": ":where(meta[itemprop])",
80
+ "rules": {
81
+ "invalid-attr": {
82
+ "option": {
83
+ "attrs": {
84
+ "content": {
85
+ "type": "NoEmptyAny"
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ },
92
+ {
93
+ "selector": ":where(script[src])",
25
94
  "rules": {
26
95
  "required-attr": ["defer"]
27
96
  }
28
97
  },
29
98
  {
30
- "selector": "img",
99
+ "selector": "h1, h2, h3, h4, h5, h6",
100
+ "rules": {
101
+ "disallowed-element": {
102
+ "value": ["small"],
103
+ "reason": "The small element must not be used for subheadings. https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-small-element"
104
+ }
105
+ }
106
+ },
107
+ {
108
+ "selector": ":where(img)",
31
109
  "rules": {
32
- "required-attr": ["decoding", "width", "height", "alt"]
110
+ "required-attr": [
111
+ "width",
112
+ "height",
113
+ "alt",
114
+ {
115
+ "name": "decoding",
116
+ "value": "async"
117
+ }
118
+ ]
33
119
  }
34
120
  },
35
121
  {
36
- "selector": "iframe",
122
+ "selector": ":where(iframe)",
37
123
  "rules": {
38
- "required-attr": ["loading", "title"]
124
+ "required-attr": [
125
+ "title",
126
+ {
127
+ "name": "loading",
128
+ "value": "lazy"
129
+ }
130
+ ]
39
131
  }
40
132
  },
41
133
  {
42
- "selector": "a[target=_blank], area[target=_blank]",
134
+ "selector": ":where(a[target=_blank], area[target=_blank])",
43
135
  "rules": {
44
- "required-attr": ["rel"]
136
+ "required-attr": {
137
+ "value": [
138
+ {
139
+ "name": "rel",
140
+ "value": "/(?<![^\\s]+)noreferrer(?![^\\s]+)/"
141
+ }
142
+ ],
143
+ "reason": "The \"rel\" attribute should be required with \"noreferrer\" if the \"a\" element has the \"target=_black\""
144
+ }
45
145
  }
46
146
  },
47
147
  {
48
- "selector": "abbr",
148
+ "selector": ":where(abbr)",
49
149
  "rules": {
50
150
  "required-attr": ["title"]
51
151
  }
152
+ },
153
+ {
154
+ "selector": ":where(video, audio)",
155
+ "rules": {
156
+ "required-element": ["track"]
157
+ }
158
+ },
159
+ {
160
+ "selector": ":where(video[autoplay])",
161
+ "rules": {
162
+ "required-attr": ["muted"]
163
+ }
164
+ },
165
+ {
166
+ "selector": ":where(th, td)",
167
+ "rules": {
168
+ "invalid-attr": {
169
+ "option": {
170
+ "attrs": {
171
+ "span": {
172
+ "disallowed": false
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+ },
179
+ {
180
+ "selector": ":where(body :not(button))",
181
+ "rules": {
182
+ "invalid-attr": {
183
+ "option": {
184
+ "attrs": {
185
+ "onclick": {
186
+ "disallowed": false
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
52
192
  }
53
193
  ]
54
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/ml-core",
3
- "version": "2.0.0-rc.0",
3
+ "version": "2.0.0-rc.6",
4
4
  "description": "The core module of markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -17,17 +17,18 @@
17
17
  "clean": "tsc --build --clean"
18
18
  },
19
19
  "dependencies": {
20
- "@markuplint/i18n": "2.0.0-rc.0",
21
- "@markuplint/ml-ast": "2.0.0-rc.0",
22
- "@markuplint/ml-config": "2.0.0-rc.0",
23
- "@markuplint/ml-spec": "2.0.0-rc.0",
20
+ "@markuplint/i18n": "2.0.0-rc.5",
21
+ "@markuplint/ml-ast": "2.0.0-rc.6",
22
+ "@markuplint/ml-config": "2.0.0-rc.5",
23
+ "@markuplint/ml-spec": "2.0.0-rc.6",
24
+ "@markuplint/parser-utils": "2.0.0-rc.6",
24
25
  "debug": "^4.3.2",
25
26
  "postcss-selector-parser": "^6.0.6",
26
27
  "tslib": "^2.3.1"
27
28
  },
28
29
  "devDependencies": {
29
- "@markuplint/html-parser": "2.0.0-rc.0",
30
+ "@markuplint/html-parser": "2.0.0-rc.6",
30
31
  "@types/debug": "^4.1.7"
31
32
  },
32
- "gitHead": "67134f1addbdd271ad1d425de8f296d1875dbf25"
33
+ "gitHead": "7c93367a86f935f6b94780b1fa14f3293f900b87"
33
34
  }