@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.
package/lib/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export { RuleInfo, RuleConfig, RuleConfigValue } from '@markuplint/ml-config';
2
+ export { getAttrSpecs } from '@markuplint/ml-spec';
2
3
  export * from './convert-ruleset';
3
4
  export * from './ml-core';
4
5
  export * from './ml-rule';
5
- export { default as MLParseError } from './ml-error/ml-parse-error';
6
6
  export { default as Ruleset } from './ruleset';
7
7
  export * from './ml-dom';
8
8
  export * from './plugin';
package/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enableDebug = exports.getIndent = exports.Ruleset = exports.MLParseError = void 0;
3
+ exports.enableDebug = exports.getIndent = exports.Ruleset = exports.getAttrSpecs = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ var ml_spec_1 = require("@markuplint/ml-spec");
6
+ Object.defineProperty(exports, "getAttrSpecs", { enumerable: true, get: function () { return ml_spec_1.getAttrSpecs; } });
5
7
  (0, tslib_1.__exportStar)(require("./convert-ruleset"), exports);
6
8
  (0, tslib_1.__exportStar)(require("./ml-core"), exports);
7
9
  (0, tslib_1.__exportStar)(require("./ml-rule"), exports);
8
- var ml_parse_error_1 = require("./ml-error/ml-parse-error");
9
- Object.defineProperty(exports, "MLParseError", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(ml_parse_error_1).default; } });
10
10
  var ruleset_1 = require("./ruleset");
11
11
  Object.defineProperty(exports, "Ruleset", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(ruleset_1).default; } });
12
12
  (0, tslib_1.__exportStar)(require("./ml-dom"), exports);
package/lib/ml-core.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { MLFabric } from './types';
2
2
  import type { RuleConfigValue, Violation } from '@markuplint/ml-config';
3
+ import { ParserError } from '@markuplint/parser-utils';
3
4
  import { Document } from './ml-dom';
4
- import MLParseError from './ml-error/ml-parse-error';
5
5
  export declare type MLCoreParams = {
6
6
  sourceCode: string;
7
7
  filename: string;
@@ -10,9 +10,10 @@ export declare type MLCoreParams = {
10
10
  export declare class MLCore {
11
11
  #private;
12
12
  constructor({ parser, sourceCode, ruleset, rules, locale, schemas, parserOptions, filename, debug }: MLCoreParams);
13
- get document(): MLParseError | Document<RuleConfigValue, unknown>;
13
+ get document(): ParserError | Document<RuleConfigValue, unknown>;
14
14
  verify(fix?: boolean): Promise<Violation[]>;
15
15
  setCode(sourceCode: string): void;
16
16
  update({ parser, ruleset, rules, locale, schemas, parserOptions }: Partial<MLFabric>): void;
17
+ private _parse;
17
18
  private _createDocument;
18
19
  }
package/lib/ml-core.js CHANGED
@@ -3,10 +3,9 @@ var _MLCore_filename, _MLCore_document, _MLCore_parser, _MLCore_sourceCode, _MLC
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.MLCore = void 0;
5
5
  const tslib_1 = require("tslib");
6
+ const parser_utils_1 = require("@markuplint/parser-utils");
6
7
  const debug_1 = require("./debug");
7
8
  const ml_dom_1 = require("./ml-dom");
8
- const ml_parse_error_1 = (0, tslib_1.__importDefault)(require("./ml-error/ml-parse-error"));
9
- const _1 = require(".");
10
9
  const resultLog = debug_1.log.extend('result');
11
10
  class MLCore {
12
11
  constructor({ parser, sourceCode, ruleset, rules, locale, schemas, parserOptions, filename, debug }) {
@@ -15,12 +14,15 @@ class MLCore {
15
14
  _MLCore_document.set(this, void 0);
16
15
  _MLCore_parser.set(this, void 0);
17
16
  _MLCore_sourceCode.set(this, void 0);
18
- _MLCore_ast.set(this, void 0);
17
+ _MLCore_ast.set(this, null);
19
18
  _MLCore_ruleset.set(this, void 0);
20
19
  _MLCore_locale.set(this, void 0);
21
20
  _MLCore_rules.set(this, void 0);
22
21
  _MLCore_schemas.set(this, void 0);
23
22
  _MLCore_ignoreFrontMatter.set(this, void 0);
23
+ if (debug) {
24
+ (0, debug_1.enableDebug)();
25
+ }
24
26
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_parser, parser, "f");
25
27
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_sourceCode, sourceCode, "f");
26
28
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ignoreFrontMatter, !!parserOptions.ignoreFrontMatter, "f");
@@ -31,12 +33,9 @@ class MLCore {
31
33
  }, "f");
32
34
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_locale, locale, "f");
33
35
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_schemas, schemas, "f");
34
- (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ast, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").parse((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_sourceCode, "f"), 0, 0, 0, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ignoreFrontMatter, "f")), "f");
35
36
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_filename, filename, "f");
36
37
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_rules, rules, "f");
37
- if (debug) {
38
- (0, _1.enableDebug)();
39
- }
38
+ this._parse();
40
39
  this._createDocument();
41
40
  }
42
41
  get document() {
@@ -45,7 +44,7 @@ class MLCore {
45
44
  async verify(fix = false) {
46
45
  (0, debug_1.log)('verify: start');
47
46
  const violations = [];
48
- if ((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_document, "f") instanceof ml_parse_error_1.default) {
47
+ if ((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_document, "f") instanceof parser_utils_1.ParserError) {
49
48
  violations.push({
50
49
  ruleId: 'parse-error',
51
50
  severity: 'error',
@@ -58,18 +57,18 @@ class MLCore {
58
57
  return violations;
59
58
  }
60
59
  for (const rule of (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_rules, "f")) {
61
- const ruleInfo = rule.optimizeOption((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f").rules[rule.name] || false);
62
- if (ruleInfo.disabled) {
60
+ const ruleInfo = rule.getRuleInfo((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f"), rule.name);
61
+ if (ruleInfo.disabled && ruleInfo.nodeRules.length === 0 && ruleInfo.childNodeRules.length === 0) {
63
62
  continue;
64
63
  }
65
64
  (0, debug_1.log)('%s Rule: verify', rule.name);
66
65
  const results = await rule.verify((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_document, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_locale, "f"), ruleInfo, fix).catch(e => {
67
- if (e instanceof ml_parse_error_1.default) {
66
+ if (e instanceof parser_utils_1.ParserError) {
68
67
  return e;
69
68
  }
70
69
  throw e;
71
70
  });
72
- if (results instanceof ml_parse_error_1.default) {
71
+ if (results instanceof parser_utils_1.ParserError) {
73
72
  (0, debug_1.log)('%s Rule: verify error %o', rule.name, results.message);
74
73
  violations.push({
75
74
  ruleId: 'parse-error',
@@ -85,24 +84,26 @@ class MLCore {
85
84
  }
86
85
  (0, debug_1.log)('%s Rule: verify end', rule.name);
87
86
  }
88
- const { e, w, i } = violations.reduce((c, v) => {
89
- if (v.severity === 'error')
90
- c.e += 1;
91
- if (v.severity === 'warning')
92
- c.w += 1;
93
- if (v.severity === 'info')
94
- c.i += 1;
95
- return c;
96
- }, { e: 0, w: 0, i: 0 });
97
- resultLog('Error: %d', e);
98
- resultLog('Warning: %d', w);
99
- resultLog('Info: %d', i);
87
+ if (resultLog.enabled) {
88
+ const { e, w, i } = violations.reduce((c, v) => {
89
+ if (v.severity === 'error')
90
+ c.e += 1;
91
+ if (v.severity === 'warning')
92
+ c.w += 1;
93
+ if (v.severity === 'info')
94
+ c.i += 1;
95
+ return c;
96
+ }, { e: 0, w: 0, i: 0 });
97
+ resultLog('Error: %d', e);
98
+ resultLog('Warning: %d', w);
99
+ resultLog('Info: %d', i);
100
+ }
100
101
  (0, debug_1.log)('verify: end');
101
102
  return violations;
102
103
  }
103
104
  setCode(sourceCode) {
104
105
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_sourceCode, sourceCode, "f");
105
- (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ast, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").parse((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_sourceCode, "f"), 0, 0, 0, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ignoreFrontMatter, "f")), "f");
106
+ this._parse();
106
107
  this._createDocument();
107
108
  }
108
109
  update({ parser, ruleset, rules, locale, schemas, parserOptions }) {
@@ -117,16 +118,38 @@ class MLCore {
117
118
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_locale, locale !== null && locale !== void 0 ? locale : (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_locale, "f"), "f");
118
119
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_schemas, schemas !== null && schemas !== void 0 ? schemas : (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_schemas, "f"), "f");
119
120
  if (parserOptions && parserOptions.ignoreFrontMatter !== (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ignoreFrontMatter, "f")) {
120
- (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ast, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").parse((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_sourceCode, "f"), 0, 0, 0, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ignoreFrontMatter, "f")), "f");
121
+ this._parse();
121
122
  }
122
123
  this._createDocument();
123
124
  }
125
+ _parse() {
126
+ try {
127
+ (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ast, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").parse((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_sourceCode, "f"), 0, 0, 0, (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ignoreFrontMatter, "f")), "f");
128
+ }
129
+ catch (err) {
130
+ (0, debug_1.log)('Caught the parse error: %O', err);
131
+ (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_ast, null, "f");
132
+ if (err instanceof parser_utils_1.ParserError) {
133
+ (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_document, err, "f");
134
+ }
135
+ else {
136
+ throw err;
137
+ }
138
+ }
139
+ }
124
140
  _createDocument() {
141
+ if (!(0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ast, "f")) {
142
+ return;
143
+ }
125
144
  try {
126
- (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_document, new ml_dom_1.Document((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ast, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_schemas, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_filename, "f")), "f");
145
+ (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_document, new ml_dom_1.Document((0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ast, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_ruleset, "f"), (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_schemas, "f"), {
146
+ filename: (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_filename, "f"),
147
+ tagNameCaseSensitive: (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").tagNameCaseSensitive,
148
+ endTag: (0, tslib_1.__classPrivateFieldGet)(this, _MLCore_parser, "f").endTag,
149
+ }), "f");
127
150
  }
128
151
  catch (err) {
129
- if (err instanceof ml_parse_error_1.default) {
152
+ if (err instanceof parser_utils_1.ParserError) {
130
153
  (0, tslib_1.__classPrivateFieldSet)(this, _MLCore_document, err, "f");
131
154
  }
132
155
  else {
@@ -29,6 +29,10 @@ export default class MLDOMDocument<T extends RuleConfigValue, O = null> {
29
29
  *
30
30
  */
31
31
  specs: Readonly<MLMLSpec>;
32
+ /**
33
+ *
34
+ */
35
+ readonly endTag: 'xml' | 'omittable' | 'never';
32
36
  /**
33
37
  *
34
38
  */
@@ -42,7 +46,11 @@ export default class MLDOMDocument<T extends RuleConfigValue, O = null> {
42
46
  * @param ast node list of markuplint AST
43
47
  * @param ruleset ruleset object
44
48
  */
45
- constructor(ast: MLASTDocument, ruleset: Ruleset, schemas: readonly [MLMLSpec, ...ExtendedSpec[]], filename?: string);
49
+ constructor(ast: MLASTDocument, ruleset: Ruleset, schemas: readonly [MLMLSpec, ...ExtendedSpec[]], options?: {
50
+ filename?: string;
51
+ tagNameCaseSensitive?: boolean;
52
+ endTag?: 'xml' | 'omittable' | 'never';
53
+ });
46
54
  get doctype(): MLDOMDoctype<T, O> | null;
47
55
  get tree(): AnonymousNode<T, O>[];
48
56
  walk(walker: Walker<T, O>): Promise<void>;
@@ -23,7 +23,8 @@ class MLDOMDocument {
23
23
  * @param ast node list of markuplint AST
24
24
  * @param ruleset ruleset object
25
25
  */
26
- constructor(ast, ruleset, schemas, filename) {
26
+ constructor(ast, ruleset, schemas, options) {
27
+ var _a;
27
28
  /**
28
29
  *
29
30
  */
@@ -35,7 +36,8 @@ class MLDOMDocument {
35
36
  _MLDOMDocument_filename.set(this, void 0);
36
37
  this.isFragment = ast.isFragment;
37
38
  this.specs = (0, ml_spec_1.getSpec)(schemas);
38
- (0, tslib_1.__classPrivateFieldSet)(this, _MLDOMDocument_filename, filename, "f");
39
+ this.endTag = (_a = options === null || options === void 0 ? void 0 : options.endTag) !== null && _a !== void 0 ? _a : 'omittable';
40
+ (0, tslib_1.__classPrivateFieldSet)(this, _MLDOMDocument_filename, options === null || options === void 0 ? void 0 : options.filename, "f");
39
41
  // console.log(ast.nodeList.map((n, i) => `${i}: ${n.uuid} "${n.raw.trim()}"(${n.type})`));
40
42
  this.nodeList = Object.freeze(ast.nodeList.map(astNode => {
41
43
  if (astNode.type === 'endtag') {
@@ -43,7 +45,7 @@ class MLDOMDocument {
43
45
  }
44
46
  return (0, helper_1.createNode)(astNode, this);
45
47
  }));
46
- this._ruleMapping(ruleset);
48
+ this._ruleMapping(ruleset, options === null || options === void 0 ? void 0 : options.tagNameCaseSensitive);
47
49
  }
48
50
  /**
49
51
  * It could be used in rule, make sure it is immutable
@@ -124,56 +126,63 @@ class MLDOMDocument {
124
126
  debugMap() {
125
127
  return (0, debug_2.nodeListToDebugMaps)(this.nodeList, true);
126
128
  }
127
- _ruleMapping(ruleset) {
129
+ _ruleMapping(ruleset, tagNameCaseSensitive) {
128
130
  docLog('Rule Mapping');
129
131
  const ruleMapper = new rule_mapper_1.RuleMapper(this.nodeList);
130
132
  // add rules to node
131
133
  for (const node of this.nodeList) {
132
- docLog('Add rules to node <%s%s>', node.type === 'ElementCloseTag' ? '/' : '', 'nodeName' in node ? node.nodeName : `#${node.type}`);
134
+ if (node.type === 'ElementCloseTag') {
135
+ continue;
136
+ }
137
+ if (docLog.enabled) {
138
+ docLog('Add rules to node <%s>', 'nodeName' in node ? node.nodeName : `#${node.type}`);
139
+ }
133
140
  // global rules
134
141
  Object.keys(ruleset.rules).forEach(ruleName => {
135
142
  const rule = ruleset.rules[ruleName];
136
143
  ruleMapper.set(node, ruleName, {
137
144
  from: 'rules',
138
- index: -1,
145
+ specificity: [0, 0, 0],
139
146
  rule,
140
147
  });
141
148
  });
142
- if (node.type !== 'Element' &&
143
- node.type !== 'OmittedElement' &&
144
- node.type !== 'ElementCloseTag' &&
145
- node.type !== 'Text') {
149
+ if (node.type !== 'Element' && node.type !== 'OmittedElement' && node.type !== 'Text') {
146
150
  continue;
147
151
  }
148
- const selectorTarget = node.type === 'Element' || node.type === 'OmittedElement'
149
- ? node
150
- : node.type === 'ElementCloseTag'
151
- ? node.startTag
152
- : null;
152
+ const selectorTarget = node.type === 'Element' || node.type === 'OmittedElement' ? node : null;
153
153
  // node specs and special rules for node by selector
154
154
  ruleset.nodeRules.forEach((nodeRule, i) => {
155
155
  if (!nodeRule.rules) {
156
156
  return;
157
157
  }
158
+ if (!selectorTarget) {
159
+ return;
160
+ }
158
161
  const selector = nodeRule.selector || nodeRule.regexSelector || nodeRule.tagName;
159
- const matched =
162
+ const matches =
160
163
  /**
161
164
  * Forward v1.x compatibility
162
165
  */
163
166
  nodeRule.tagName && /^#text$/i.test(nodeRule.tagName) && node.type === 'Text'
164
- ? { __node: '#text' }
167
+ ? {
168
+ matched: true,
169
+ selector: '#text',
170
+ specificity: [0, 0, 0],
171
+ }
165
172
  : /**
166
173
  * v2.0.0 or later
167
174
  */
168
- selectorTarget && (0, match_selector_1.matchSelector)(selectorTarget, selector);
169
- if (!matched) {
175
+ (0, match_selector_1.matchSelector)(selectorTarget, selector, tagNameCaseSensitive);
176
+ if (!matches.matched) {
170
177
  return;
171
178
  }
172
- docLog('Matched nodeRule: <%s%s>(%s)', node.type === 'ElementCloseTag' ? '/' : '', 'nodeName' in node ? node.nodeName : node.type, matched.__node || 'No Selector');
179
+ if (docLog.enabled) {
180
+ docLog('Matched nodeRule: <%s>(%s)', 'nodeName' in node ? node.nodeName : node.type, matches.selector || '*');
181
+ }
173
182
  const ruleList = Object.keys(nodeRule.rules);
174
183
  for (const ruleName of ruleList) {
175
184
  const rule = nodeRule.rules[ruleName];
176
- const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matched);
185
+ const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matches.data || {});
177
186
  if (convertedRule === undefined) {
178
187
  continue;
179
188
  }
@@ -182,7 +191,7 @@ class MLDOMDocument {
182
191
  ruleLog('↑ nodeRule (%s): %O', ruleName, mergedRule);
183
192
  ruleMapper.set(node, ruleName, {
184
193
  from: 'nodeRules',
185
- index: i,
194
+ specificity: matches.specificity,
186
195
  rule: mergedRule,
187
196
  });
188
197
  }
@@ -206,15 +215,17 @@ class MLDOMDocument {
206
215
  if (!selector) {
207
216
  return;
208
217
  }
209
- const matched = (0, match_selector_1.matchSelector)(selectorTarget, selector);
210
- if (!matched) {
218
+ const matches = (0, match_selector_1.matchSelector)(selectorTarget, selector, tagNameCaseSensitive);
219
+ if (!matches.matched) {
211
220
  return;
212
221
  }
213
- docLog('Matched childNodeRule: <%s%s>(%s), inheritance: %o', node.type === 'ElementCloseTag' ? '/' : '', selectorTarget.nodeName, matched.__node || 'No Selector', !!nodeRule.inheritance);
222
+ if (docLog.enabled) {
223
+ docLog('Matched childNodeRule: <%s>(%s), inheritance: %o', selectorTarget.nodeName, matches.selector || '*', !!nodeRule.inheritance);
224
+ }
214
225
  const targetDescendants = nodeRule.inheritance ? descendants : children;
215
226
  Object.keys(nodeRuleRules).forEach(ruleName => {
216
227
  const rule = nodeRuleRules[ruleName];
217
- const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matched);
228
+ const convertedRule = (0, ml_config_1.exchangeValueOnRule)(rule, matches.data || {});
218
229
  if (convertedRule === undefined) {
219
230
  return;
220
231
  }
@@ -224,7 +235,7 @@ class MLDOMDocument {
224
235
  targetDescendants.forEach(descendant => {
225
236
  ruleMapper.set(descendant, ruleName, {
226
237
  from: 'childNodeRules',
227
- index: i,
238
+ specificity: matches.specificity,
228
239
  rule: mergedRule,
229
240
  });
230
241
  });
@@ -1,5 +1,16 @@
1
1
  import type MLDOMAbstractElement from '../tokens/abstract-element';
2
+ import type { Specificity } from './selector';
2
3
  import type { RegexSelector } from '@markuplint/ml-config';
4
+ export declare type SelectorMatches = SelectorMatched | SelectorUnmatched;
5
+ declare type SelectorMatched = {
6
+ matched: true;
7
+ selector: string;
8
+ specificity: Specificity;
9
+ data?: Record<string, string>;
10
+ };
11
+ declare type SelectorUnmatched = {
12
+ matched: false;
13
+ };
3
14
  declare type TargetElement = MLDOMAbstractElement<any, any>;
4
- export declare function matchSelector(el: TargetElement, selector: string | RegexSelector | undefined): Record<string, string> | null;
15
+ export declare function matchSelector(el: TargetElement, selector: string | RegexSelector | undefined, tagNameCaseSensitive?: boolean): SelectorMatches;
5
16
  export {};