@markuplint/ml-config 3.14.0 → 4.0.0-alpha.10
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/LICENSE +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.js +3 -6
- package/lib/merge-config.d.ts +1 -1
- package/lib/merge-config.js +27 -32
- package/lib/types.d.ts +129 -145
- package/lib/types.js +1 -2
- package/lib/utils.d.ts +3 -8
- package/lib/utils.js +16 -25
- package/package.json +12 -7
- package/test/merge-config.spec.js +0 -294
- package/test/utils.spec.js +0 -119
package/LICENSE
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './merge-config';
|
|
2
|
-
export * from './utils';
|
|
3
|
-
export * from './types';
|
|
1
|
+
export * from './merge-config.js';
|
|
2
|
+
export * from './utils.js';
|
|
3
|
+
export * from './types.js';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
tslib_1.__exportStar(require("./merge-config"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./utils"), exports);
|
|
6
|
-
tslib_1.__exportStar(require("./types"), exports);
|
|
1
|
+
export * from './merge-config.js';
|
|
2
|
+
export * from './utils.js';
|
|
3
|
+
export * from './types.js';
|
package/lib/merge-config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Config, AnyRule, AnyRuleV2 } from './types';
|
|
1
|
+
import type { Config, AnyRule, AnyRuleV2 } from './types.js';
|
|
2
2
|
import type { Nullable } from '@markuplint/shared';
|
|
3
3
|
export declare function mergeConfig(a: Config, b: Config): Config;
|
|
4
4
|
export declare function mergeRule(a: Nullable<AnyRule | AnyRuleV2>, b: AnyRule | AnyRuleV2): AnyRule;
|
package/lib/merge-config.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
|
|
6
|
-
const utils_1 = require("./utils");
|
|
7
|
-
function mergeConfig(a, b) {
|
|
1
|
+
import deepmerge from 'deepmerge';
|
|
2
|
+
import { deleteUndefProp, cleanOptions, isRuleConfigValue } from './utils.js';
|
|
3
|
+
export function mergeConfig(a, b) {
|
|
8
4
|
const config = {
|
|
9
5
|
...a,
|
|
10
6
|
...b,
|
|
@@ -22,61 +18,58 @@ function mergeConfig(a, b) {
|
|
|
22
18
|
// delete all
|
|
23
19
|
extends: undefined,
|
|
24
20
|
};
|
|
25
|
-
|
|
21
|
+
deleteUndefProp(config);
|
|
26
22
|
return config;
|
|
27
23
|
}
|
|
28
|
-
|
|
29
|
-
function mergeRule(a, b) {
|
|
30
|
-
var _a, _b, _c;
|
|
24
|
+
export function mergeRule(a, b) {
|
|
31
25
|
const oA = optimizeRule(a);
|
|
32
26
|
const oB = optimizeRule(b);
|
|
33
27
|
// Particular behavior:
|
|
34
28
|
// If the right-side value is false, return false.
|
|
35
29
|
// In short; The `false` makes the rule to be disabled absolutely.
|
|
36
|
-
if (oB === false || (!
|
|
30
|
+
if (oB === false || (!isRuleConfigValue(oB) && oB?.value === false)) {
|
|
37
31
|
return false;
|
|
38
32
|
}
|
|
39
33
|
if (oA === undefined) {
|
|
40
|
-
return oB
|
|
34
|
+
return oB ?? {};
|
|
41
35
|
}
|
|
42
36
|
if (oB === undefined) {
|
|
43
37
|
return oA;
|
|
44
38
|
}
|
|
45
|
-
if (
|
|
46
|
-
if (
|
|
39
|
+
if (isRuleConfigValue(oB)) {
|
|
40
|
+
if (isRuleConfigValue(oA)) {
|
|
47
41
|
if (Array.isArray(oA) && Array.isArray(oB)) {
|
|
48
42
|
return [...oA, ...oB];
|
|
49
43
|
}
|
|
50
44
|
return oB;
|
|
51
45
|
}
|
|
52
46
|
const value = Array.isArray(oA.value) && Array.isArray(oB) ? [...oA.value, ...oB] : oB;
|
|
53
|
-
const res =
|
|
54
|
-
|
|
47
|
+
const res = cleanOptions({ ...oA, value });
|
|
48
|
+
deleteUndefProp(res);
|
|
55
49
|
return res;
|
|
56
50
|
}
|
|
57
|
-
const severity =
|
|
58
|
-
const value =
|
|
59
|
-
const options = mergeObject(
|
|
60
|
-
const reason =
|
|
51
|
+
const severity = oB.severity ?? (isRuleConfigValue(oA) ? undefined : oA.severity);
|
|
52
|
+
const value = oB.value ?? (isRuleConfigValue(oA) ? oA : oA.value);
|
|
53
|
+
const options = mergeObject(isRuleConfigValue(oA) ? undefined : oA.options, oB.options);
|
|
54
|
+
const reason = oB.reason ?? (isRuleConfigValue(oA) ? undefined : oA.reason);
|
|
61
55
|
const res = {
|
|
62
56
|
severity,
|
|
63
57
|
value,
|
|
64
58
|
options,
|
|
65
59
|
reason,
|
|
66
60
|
};
|
|
67
|
-
|
|
61
|
+
deleteUndefProp(res);
|
|
68
62
|
return res;
|
|
69
63
|
}
|
|
70
|
-
exports.mergeRule = mergeRule;
|
|
71
64
|
function mergeObject(a, b) {
|
|
72
65
|
if (a == null) {
|
|
73
|
-
return b
|
|
66
|
+
return b ?? undefined;
|
|
74
67
|
}
|
|
75
68
|
if (b == null) {
|
|
76
|
-
return a
|
|
69
|
+
return a ?? undefined;
|
|
77
70
|
}
|
|
78
|
-
const res = (
|
|
79
|
-
|
|
71
|
+
const res = deepmerge(a, b);
|
|
72
|
+
deleteUndefProp(res);
|
|
80
73
|
return res;
|
|
81
74
|
}
|
|
82
75
|
function concatArray(a, b, uniquely = false, comparePropName) {
|
|
@@ -114,8 +107,10 @@ function concatArray(a, b, uniquely = false, comparePropName) {
|
|
|
114
107
|
}
|
|
115
108
|
newArray.splice(existedIndex, 1, merged);
|
|
116
109
|
}
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
111
|
+
a?.forEach(concat);
|
|
112
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
113
|
+
b?.forEach(concat);
|
|
119
114
|
return newArray.length === 0 ? undefined : newArray;
|
|
120
115
|
}
|
|
121
116
|
function getName(item, comparePropName) {
|
|
@@ -144,7 +139,7 @@ function mergeRules(a, b) {
|
|
|
144
139
|
res[key] = merged;
|
|
145
140
|
}
|
|
146
141
|
}
|
|
147
|
-
|
|
142
|
+
deleteUndefProp(res);
|
|
148
143
|
return Object.freeze(res);
|
|
149
144
|
}
|
|
150
145
|
function optimizeRules(rules) {
|
|
@@ -161,8 +156,8 @@ function optimizeRule(rule) {
|
|
|
161
156
|
if (rule === undefined) {
|
|
162
157
|
return;
|
|
163
158
|
}
|
|
164
|
-
if (
|
|
159
|
+
if (isRuleConfigValue(rule)) {
|
|
165
160
|
return rule;
|
|
166
161
|
}
|
|
167
|
-
return
|
|
162
|
+
return cleanOptions(rule);
|
|
168
163
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -3,201 +3,185 @@ import type { RegexSelector } from '@markuplint/selector';
|
|
|
3
3
|
import type { Nullable } from '@markuplint/shared';
|
|
4
4
|
export type { RegexSelector } from '@markuplint/selector';
|
|
5
5
|
export type Config = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
readonly $schema?: string;
|
|
7
|
+
readonly extends?: string | readonly string[];
|
|
8
|
+
readonly plugins?: readonly (PluginConfig | string)[];
|
|
9
|
+
readonly parser?: ParserConfig;
|
|
10
|
+
readonly parserOptions?: ParserOptions;
|
|
11
|
+
readonly specs?: SpecConfig;
|
|
12
|
+
readonly excludeFiles?: readonly string[];
|
|
13
|
+
readonly pretenders?: readonly Pretender[];
|
|
14
|
+
readonly rules?: Rules;
|
|
15
|
+
readonly nodeRules?: readonly NodeRule[];
|
|
16
|
+
readonly childNodeRules?: readonly ChildNodeRule[];
|
|
17
|
+
readonly overrides?: Readonly<Record<string, OverrideConfig>>;
|
|
18
18
|
};
|
|
19
19
|
export type PrimitiveScalar = string | number | boolean;
|
|
20
|
-
export type PlainData =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export type NonNullablePlainData =
|
|
27
|
-
| PrimitiveScalar
|
|
28
|
-
| readonly NonNullablePlainData[]
|
|
29
|
-
| {
|
|
30
|
-
readonly [key: string]: NonNullablePlainData;
|
|
31
|
-
};
|
|
20
|
+
export type PlainData = Nullable<PrimitiveScalar> | readonly PlainData[] | {
|
|
21
|
+
readonly [key: string]: PlainData | any;
|
|
22
|
+
};
|
|
23
|
+
export type NonNullablePlainData = PrimitiveScalar | readonly NonNullablePlainData[] | {
|
|
24
|
+
readonly [key: string]: NonNullablePlainData;
|
|
25
|
+
};
|
|
32
26
|
export type OverrideConfig = Omit<Config, '$schema' | 'extends' | 'overrides'>;
|
|
33
27
|
export type PluginConfig = {
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly settings: Readonly<Record<string, NonNullablePlainData>>;
|
|
36
30
|
};
|
|
37
31
|
export type ParserConfig = {
|
|
38
|
-
|
|
32
|
+
readonly [extensionPattern: string]: string;
|
|
39
33
|
};
|
|
40
34
|
export type SpecConfig = {
|
|
41
|
-
|
|
35
|
+
readonly [extensionPattern: string]: string;
|
|
42
36
|
};
|
|
43
37
|
export type Pretender = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Target node selectors
|
|
40
|
+
*/
|
|
41
|
+
readonly selector: string;
|
|
42
|
+
/**
|
|
43
|
+
* If it is a string, it is resolved as an element name.
|
|
44
|
+
* An element has the same attributes as the pretended custom element
|
|
45
|
+
* because attributes are just inherited.
|
|
46
|
+
*
|
|
47
|
+
* If it is an Object, It creates the element by that.
|
|
48
|
+
*/
|
|
49
|
+
readonly as: string | OriginalNode;
|
|
56
50
|
};
|
|
57
51
|
export type OriginalNode = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
*/
|
|
93
|
-
readonly aria?: PretenderARIA;
|
|
52
|
+
/**
|
|
53
|
+
* Element name
|
|
54
|
+
*/
|
|
55
|
+
readonly element: string;
|
|
56
|
+
/**
|
|
57
|
+
* Namespace
|
|
58
|
+
*
|
|
59
|
+
* Supports `"svg"` and `undefined` only.
|
|
60
|
+
* If it is `undefined`, the namespace is HTML.
|
|
61
|
+
*/
|
|
62
|
+
readonly namespace?: 'svg';
|
|
63
|
+
/**
|
|
64
|
+
* Attributes
|
|
65
|
+
*/
|
|
66
|
+
readonly attrs?: readonly {
|
|
67
|
+
/**
|
|
68
|
+
* Attribute name
|
|
69
|
+
*/
|
|
70
|
+
readonly name: string;
|
|
71
|
+
/**
|
|
72
|
+
* If it omits this property, the attribute is resolved as a boolean.
|
|
73
|
+
*/
|
|
74
|
+
readonly value?: string | {
|
|
75
|
+
readonly fromAttr: string;
|
|
76
|
+
};
|
|
77
|
+
}[];
|
|
78
|
+
/**
|
|
79
|
+
* To have attributes the defined element has.
|
|
80
|
+
*/
|
|
81
|
+
readonly inheritAttrs?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* ARIA properties
|
|
84
|
+
*/
|
|
85
|
+
readonly aria?: PretenderARIA;
|
|
94
86
|
};
|
|
95
87
|
/**
|
|
96
88
|
* Pretender Node ARIA properties
|
|
97
89
|
*/
|
|
98
90
|
export type PretenderARIA = {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
readonly fromAttr: string;
|
|
109
|
-
};
|
|
91
|
+
/**
|
|
92
|
+
* Accessible name
|
|
93
|
+
*
|
|
94
|
+
* - If it is `true`, it assumes the element has any text on its accessible name.
|
|
95
|
+
* - If it specifies `fromAttr` property, it assumes the accessible name refers to the value of the attribute.
|
|
96
|
+
*/
|
|
97
|
+
readonly name?: boolean | {
|
|
98
|
+
readonly fromAttr: string;
|
|
99
|
+
};
|
|
110
100
|
};
|
|
111
101
|
export type Rule<T extends RuleConfigValue, O extends PlainData = undefined> = RuleConfig<T, O> | Readonly<T> | boolean;
|
|
112
102
|
/**
|
|
113
103
|
* @deprecated
|
|
114
104
|
*/
|
|
115
|
-
export type RuleV2<T extends RuleConfigValue, O extends PlainData = undefined> =
|
|
116
|
-
| RuleConfigV2<T, O>
|
|
117
|
-
| Readonly<T>
|
|
118
|
-
| boolean;
|
|
105
|
+
export type RuleV2<T extends RuleConfigValue, O extends PlainData = undefined> = RuleConfigV2<T, O> | Readonly<T> | boolean;
|
|
119
106
|
export type AnyRule = Rule<RuleConfigValue, PlainData>;
|
|
120
107
|
/**
|
|
121
108
|
* @deprecated
|
|
122
109
|
*/
|
|
123
110
|
export type AnyRuleV2 = RuleV2<RuleConfigValue, PlainData>;
|
|
124
111
|
export type Rules = {
|
|
125
|
-
|
|
112
|
+
readonly [ruleName: string]: AnyRule;
|
|
126
113
|
};
|
|
127
114
|
export type RuleConfig<T extends RuleConfigValue, O extends PlainData = undefined> = {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
115
|
+
readonly severity?: Severity;
|
|
116
|
+
readonly value?: Readonly<T>;
|
|
117
|
+
readonly options?: Readonly<O>;
|
|
118
|
+
readonly reason?: string;
|
|
132
119
|
};
|
|
133
120
|
/**
|
|
134
121
|
* @deprecated
|
|
135
122
|
*/
|
|
136
123
|
export type RuleConfigV2<T extends RuleConfigValue, O extends PlainData = undefined> = {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
124
|
+
readonly severity?: Severity;
|
|
125
|
+
readonly value?: Readonly<T>;
|
|
126
|
+
readonly reason?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Old property
|
|
129
|
+
*
|
|
130
|
+
* @deprecated
|
|
131
|
+
* @see {this.options}
|
|
132
|
+
*/
|
|
133
|
+
readonly option?: Readonly<O>;
|
|
147
134
|
};
|
|
148
135
|
export type Severity = 'error' | 'warning' | 'info';
|
|
149
136
|
export type RuleConfigValue = PrimitiveScalar | readonly (PrimitiveScalar | Readonly<Record<string, any>>)[] | null;
|
|
150
137
|
export type NodeRule = {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
138
|
+
readonly selector?: string;
|
|
139
|
+
readonly regexSelector?: RegexSelector;
|
|
140
|
+
readonly categories?: readonly string[];
|
|
141
|
+
readonly roles?: readonly string[];
|
|
142
|
+
readonly obsolete?: boolean;
|
|
143
|
+
readonly rules?: Rules;
|
|
157
144
|
};
|
|
158
145
|
export type ChildNodeRule = {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
};
|
|
164
|
-
export type Report<T extends RuleConfigValue, O extends PlainData = undefined> =
|
|
165
|
-
| Report1<T, O>
|
|
166
|
-
| Report2
|
|
167
|
-
| (Report1<T, O> & Report2);
|
|
146
|
+
readonly selector?: string;
|
|
147
|
+
readonly regexSelector?: RegexSelector;
|
|
148
|
+
readonly inheritance?: boolean;
|
|
149
|
+
readonly rules?: Rules;
|
|
150
|
+
};
|
|
151
|
+
export type Report<T extends RuleConfigValue, O extends PlainData = undefined> = Report1<T, O> | Report2 | (Report1<T, O> & Report2);
|
|
168
152
|
export type Report1<T extends RuleConfigValue, O extends PlainData = undefined> = {
|
|
169
|
-
|
|
170
|
-
|
|
153
|
+
readonly message: string;
|
|
154
|
+
readonly scope: Scope<T, O>;
|
|
171
155
|
};
|
|
172
156
|
export type Report2 = {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
157
|
+
readonly message: string;
|
|
158
|
+
readonly line: number;
|
|
159
|
+
readonly col: number;
|
|
160
|
+
readonly raw: string;
|
|
177
161
|
};
|
|
178
162
|
export type Scope<T extends RuleConfigValue, O extends PlainData = undefined> = {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
163
|
+
readonly rule: RuleInfo<T, O>;
|
|
164
|
+
readonly startLine: number;
|
|
165
|
+
readonly startCol: number;
|
|
166
|
+
readonly raw: string;
|
|
183
167
|
};
|
|
184
168
|
export type Violation = {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
169
|
+
readonly ruleId: string;
|
|
170
|
+
readonly severity: Severity;
|
|
171
|
+
readonly message: string;
|
|
172
|
+
readonly reason?: string;
|
|
173
|
+
readonly line: number;
|
|
174
|
+
readonly col: number;
|
|
175
|
+
readonly raw: string;
|
|
192
176
|
};
|
|
193
177
|
export type RuleInfo<T extends RuleConfigValue, O extends PlainData = undefined> = {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
178
|
+
readonly disabled: boolean;
|
|
179
|
+
readonly severity: Severity;
|
|
180
|
+
readonly value: Readonly<T>;
|
|
181
|
+
readonly options: Readonly<O>;
|
|
182
|
+
readonly reason?: string;
|
|
199
183
|
};
|
|
200
184
|
export type GlobalRuleInfo<T extends RuleConfigValue, O extends PlainData = undefined> = RuleInfo<T, O> & {
|
|
201
|
-
|
|
202
|
-
|
|
185
|
+
nodeRules: RuleInfo<T, O>[];
|
|
186
|
+
childNodeRules: RuleInfo<T, O>[];
|
|
203
187
|
};
|
package/lib/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyRule, AnyRuleV2, PlainData, RuleConfig, RuleConfigV2, RuleConfigValue } from './types';
|
|
1
|
+
import type { AnyRule, AnyRuleV2, PlainData, RuleConfig, RuleConfigV2, RuleConfigValue } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Return undefined if the template doesn't include the variable that is set as a property in data.
|
|
4
4
|
* But return template string without changes if it doesn't have a variable.
|
|
@@ -7,13 +7,8 @@ import type { AnyRule, AnyRuleV2, PlainData, RuleConfig, RuleConfigV2, RuleConfi
|
|
|
7
7
|
* @param data Captured string for replacement
|
|
8
8
|
*/
|
|
9
9
|
export declare function provideValue(template: string, data: Readonly<Record<string, string>>): string | undefined;
|
|
10
|
-
export declare function exchangeValueOnRule(
|
|
11
|
-
|
|
12
|
-
data: Readonly<Record<string, string>>,
|
|
13
|
-
): AnyRule | undefined;
|
|
14
|
-
export declare function cleanOptions(
|
|
15
|
-
rule: RuleConfig<RuleConfigValue, PlainData> | RuleConfigV2<RuleConfigValue, PlainData>,
|
|
16
|
-
): RuleConfig<RuleConfigValue, PlainData>;
|
|
10
|
+
export declare function exchangeValueOnRule(rule: AnyRule | AnyRuleV2, data: Readonly<Record<string, string>>): AnyRule | undefined;
|
|
11
|
+
export declare function cleanOptions(rule: RuleConfig<RuleConfigValue, PlainData> | RuleConfigV2<RuleConfigValue, PlainData>): RuleConfig<RuleConfigValue, PlainData>;
|
|
17
12
|
export declare function isRuleConfigValue(v: any): v is RuleConfigValue;
|
|
18
13
|
/**
|
|
19
14
|
*
|
package/lib/utils.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const is_plain_object_1 = require("is-plain-object");
|
|
6
|
-
const mustache_1 = tslib_1.__importDefault(require("mustache"));
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { isPlainObject } from 'is-plain-object';
|
|
3
|
+
import mustache from 'mustache';
|
|
7
4
|
/**
|
|
8
5
|
* Return undefined if the template doesn't include the variable that is set as a property in data.
|
|
9
6
|
* But return template string without changes if it doesn't have a variable.
|
|
@@ -11,23 +8,21 @@ const mustache_1 = tslib_1.__importDefault(require("mustache"));
|
|
|
11
8
|
* @param template Mustache template string
|
|
12
9
|
* @param data Captured string for replacement
|
|
13
10
|
*/
|
|
14
|
-
function provideValue(template, data) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (ast.length === 1 && ((_a = ast[0]) === null || _a === void 0 ? void 0 : _a[0]) === 'text') {
|
|
11
|
+
export function provideValue(template, data) {
|
|
12
|
+
const ast = mustache.parse(template);
|
|
13
|
+
if (ast.length === 1 && ast[0]?.[0] === 'text') {
|
|
18
14
|
// It doesn't have a variable
|
|
19
15
|
return template;
|
|
20
16
|
}
|
|
21
|
-
const noDataResult =
|
|
22
|
-
const result =
|
|
17
|
+
const noDataResult = mustache.render(template, {});
|
|
18
|
+
const result = mustache.render(template, data);
|
|
23
19
|
// Assume variables are empty in the template if it matched.
|
|
24
20
|
if (noDataResult === result) {
|
|
25
21
|
return;
|
|
26
22
|
}
|
|
27
23
|
return result;
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
function exchangeValueOnRule(rule, data) {
|
|
25
|
+
export function exchangeValueOnRule(rule, data) {
|
|
31
26
|
if (isRuleConfigValue(rule)) {
|
|
32
27
|
return exchangeValue(rule, data);
|
|
33
28
|
}
|
|
@@ -54,14 +49,13 @@ function exchangeValueOnRule(rule, data) {
|
|
|
54
49
|
const exchangedValue = exchangeValue(result.reason, data);
|
|
55
50
|
result = {
|
|
56
51
|
...result,
|
|
57
|
-
reason: exchangedValue
|
|
52
|
+
reason: exchangedValue == null ? undefined : `${exchangedValue}`,
|
|
58
53
|
};
|
|
59
54
|
}
|
|
60
55
|
deleteUndefProp(result);
|
|
61
56
|
return result;
|
|
62
57
|
}
|
|
63
|
-
|
|
64
|
-
function cleanOptions(rule) {
|
|
58
|
+
export function cleanOptions(rule) {
|
|
65
59
|
const res = {
|
|
66
60
|
severity: rule.severity,
|
|
67
61
|
value: rule.value,
|
|
@@ -71,8 +65,7 @@ function cleanOptions(rule) {
|
|
|
71
65
|
deleteUndefProp(res);
|
|
72
66
|
return res;
|
|
73
67
|
}
|
|
74
|
-
|
|
75
|
-
function isRuleConfigValue(v) {
|
|
68
|
+
export function isRuleConfigValue(v) {
|
|
76
69
|
switch (typeof v) {
|
|
77
70
|
case 'string':
|
|
78
71
|
case 'number':
|
|
@@ -85,14 +78,13 @@ function isRuleConfigValue(v) {
|
|
|
85
78
|
}
|
|
86
79
|
return Array.isArray(v);
|
|
87
80
|
}
|
|
88
|
-
exports.isRuleConfigValue = isRuleConfigValue;
|
|
89
81
|
/**
|
|
90
82
|
*
|
|
91
83
|
* @param obj
|
|
92
84
|
* @returns
|
|
93
85
|
*/
|
|
94
|
-
function deleteUndefProp(obj) {
|
|
95
|
-
if (!
|
|
86
|
+
export function deleteUndefProp(obj) {
|
|
87
|
+
if (!isPlainObject(obj)) {
|
|
96
88
|
return;
|
|
97
89
|
}
|
|
98
90
|
for (const key in obj) {
|
|
@@ -101,7 +93,6 @@ function deleteUndefProp(obj) {
|
|
|
101
93
|
}
|
|
102
94
|
}
|
|
103
95
|
}
|
|
104
|
-
exports.deleteUndefProp = deleteUndefProp;
|
|
105
96
|
/**
|
|
106
97
|
* Return options from `options` or `option`
|
|
107
98
|
*
|
|
@@ -150,9 +141,9 @@ function exchangeOption(optionValue, data) {
|
|
|
150
141
|
return optionValue.map(v => exchangeOption(v, data));
|
|
151
142
|
}
|
|
152
143
|
const result = {};
|
|
153
|
-
Object.keys(optionValue)
|
|
144
|
+
for (const key of Object.keys(optionValue)) {
|
|
154
145
|
result[key] = exchangeOption(optionValue[key], data);
|
|
155
|
-
}
|
|
146
|
+
}
|
|
156
147
|
return result;
|
|
157
148
|
}
|
|
158
149
|
/**
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-alpha.10",
|
|
4
4
|
"description": "JSON Schema and TypeScript types of markuplint configure JSON",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"private": false,
|
|
9
|
-
"
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
10
15
|
"types": "lib/index.d.ts",
|
|
11
16
|
"publishConfig": {
|
|
12
17
|
"access": "public"
|
|
@@ -19,14 +24,14 @@
|
|
|
19
24
|
"clean": "tsc --build --clean"
|
|
20
25
|
},
|
|
21
26
|
"dependencies": {
|
|
22
|
-
"@markuplint/ml-ast": "
|
|
23
|
-
"@markuplint/selector": "
|
|
24
|
-
"@markuplint/shared": "
|
|
27
|
+
"@markuplint/ml-ast": "4.0.0-alpha.10",
|
|
28
|
+
"@markuplint/selector": "4.0.0-alpha.10",
|
|
29
|
+
"@markuplint/shared": "4.0.0-alpha.10",
|
|
25
30
|
"@types/mustache": "^4.2.5",
|
|
26
31
|
"deepmerge": "^4.3.1",
|
|
27
32
|
"is-plain-object": "^5.0.0",
|
|
28
33
|
"mustache": "^4.2.0",
|
|
29
|
-
"type-fest": "^4.
|
|
34
|
+
"type-fest": "^4.10.1"
|
|
30
35
|
},
|
|
31
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "b41153ea665aa8f091daf6114a06047f4ccb8350"
|
|
32
37
|
}
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
const { mergeConfig, mergeRule } = require('../lib/merge-config');
|
|
2
|
-
|
|
3
|
-
describe('mergeConfig', () => {
|
|
4
|
-
test('empty + empty', () => {
|
|
5
|
-
expect(mergeConfig({}, {})).toStrictEqual({});
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test('plugins + plugins', () => {
|
|
9
|
-
expect(
|
|
10
|
-
mergeConfig(
|
|
11
|
-
{
|
|
12
|
-
plugins: ['a', 'b', 'c'],
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
plugins: ['c', 'b', 'd'],
|
|
16
|
-
},
|
|
17
|
-
),
|
|
18
|
-
).toStrictEqual({
|
|
19
|
-
plugins: ['a', 'b', 'c', 'd'],
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('plugins + plugins (with options)', () => {
|
|
24
|
-
expect(
|
|
25
|
-
mergeConfig(
|
|
26
|
-
{
|
|
27
|
-
plugins: ['a', 'b', { name: 'c', settings: { foo: 'foo', bar: 'bar' } }],
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
plugins: ['c', 'b', 'd', { name: 'c', settings: { foo2: 'foo2', bar: 'bar2' } }],
|
|
31
|
-
},
|
|
32
|
-
),
|
|
33
|
-
).toStrictEqual({
|
|
34
|
-
plugins: [
|
|
35
|
-
'a',
|
|
36
|
-
'b',
|
|
37
|
-
{
|
|
38
|
-
name: 'c',
|
|
39
|
-
settings: {
|
|
40
|
-
bar: 'bar2',
|
|
41
|
-
foo: 'foo',
|
|
42
|
-
foo2: 'foo2',
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
'd',
|
|
46
|
-
],
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('parser + parser', () => {
|
|
51
|
-
expect(
|
|
52
|
-
mergeConfig(
|
|
53
|
-
{
|
|
54
|
-
parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
|
|
58
|
-
},
|
|
59
|
-
),
|
|
60
|
-
).toStrictEqual({
|
|
61
|
-
parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('parser + parser (2)', () => {
|
|
66
|
-
expect(
|
|
67
|
-
mergeConfig(
|
|
68
|
-
{
|
|
69
|
-
parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
parser: { '/\\.[jt]sx?$/i': '@markuplint/jsx-parser' },
|
|
73
|
-
},
|
|
74
|
-
),
|
|
75
|
-
).toStrictEqual({
|
|
76
|
-
parser: {
|
|
77
|
-
'/\\.vue$/i': '@markuplint/vue-parser',
|
|
78
|
-
'/\\.[jt]sx?$/i': '@markuplint/jsx-parser',
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test('overrides + overrides', () => {
|
|
84
|
-
expect(
|
|
85
|
-
mergeConfig(
|
|
86
|
-
{
|
|
87
|
-
overrides: {
|
|
88
|
-
a: {
|
|
89
|
-
rules: {
|
|
90
|
-
rule1: true,
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
overrides: {
|
|
97
|
-
a: {
|
|
98
|
-
rules: {
|
|
99
|
-
rule1: false,
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
b: {
|
|
103
|
-
rules: {
|
|
104
|
-
rule1: true,
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
),
|
|
110
|
-
).toStrictEqual({
|
|
111
|
-
overrides: {
|
|
112
|
-
a: {
|
|
113
|
-
rules: {
|
|
114
|
-
rule1: false,
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
b: {
|
|
118
|
-
rules: {
|
|
119
|
-
rule1: true,
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test('rules + rules', () => {
|
|
127
|
-
expect(
|
|
128
|
-
mergeConfig(
|
|
129
|
-
{
|
|
130
|
-
rules: {
|
|
131
|
-
a: {
|
|
132
|
-
option: {
|
|
133
|
-
ruleA: true,
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
rules: {
|
|
140
|
-
b: {
|
|
141
|
-
options: {
|
|
142
|
-
ruleB: true,
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
),
|
|
148
|
-
).toStrictEqual({
|
|
149
|
-
rules: {
|
|
150
|
-
a: {
|
|
151
|
-
options: {
|
|
152
|
-
ruleA: true,
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
b: {
|
|
156
|
-
options: {
|
|
157
|
-
ruleB: true,
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test('rules[rule].value + rules[rule].value', () => {
|
|
165
|
-
expect(
|
|
166
|
-
mergeConfig(
|
|
167
|
-
{
|
|
168
|
-
rules: {
|
|
169
|
-
ruleA: true,
|
|
170
|
-
ruleB: [],
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
rules: {
|
|
175
|
-
ruleA: {
|
|
176
|
-
options: {
|
|
177
|
-
optionName: true,
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
ruleB: {
|
|
181
|
-
options: {
|
|
182
|
-
optionName: true,
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
),
|
|
188
|
-
).toStrictEqual({
|
|
189
|
-
rules: {
|
|
190
|
-
ruleA: {
|
|
191
|
-
value: true,
|
|
192
|
-
options: {
|
|
193
|
-
optionName: true,
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
ruleB: {
|
|
197
|
-
value: [],
|
|
198
|
-
options: {
|
|
199
|
-
optionName: true,
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe('mergeRule', () => {
|
|
208
|
-
test('{value} + shorthand', () => {
|
|
209
|
-
expect(
|
|
210
|
-
mergeRule(
|
|
211
|
-
{
|
|
212
|
-
value: true,
|
|
213
|
-
},
|
|
214
|
-
{},
|
|
215
|
-
),
|
|
216
|
-
).toStrictEqual({
|
|
217
|
-
value: true,
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
test('{value} + shorthand (2)', () => {
|
|
222
|
-
expect(
|
|
223
|
-
mergeRule(
|
|
224
|
-
{
|
|
225
|
-
value: true,
|
|
226
|
-
},
|
|
227
|
-
false,
|
|
228
|
-
),
|
|
229
|
-
).toStrictEqual(false);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test('{value} + shorthand (3)', () => {
|
|
233
|
-
expect(
|
|
234
|
-
mergeRule(
|
|
235
|
-
{
|
|
236
|
-
value: false,
|
|
237
|
-
},
|
|
238
|
-
true,
|
|
239
|
-
),
|
|
240
|
-
).toStrictEqual({
|
|
241
|
-
value: true,
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test('{options} + {options}', () => {
|
|
246
|
-
expect(
|
|
247
|
-
mergeRule(
|
|
248
|
-
{
|
|
249
|
-
options: {
|
|
250
|
-
optional: 'OPTIONAL_VALUE',
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
options: {
|
|
255
|
-
optional: 'CHANGED_OPTIONAL_VALUE',
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
),
|
|
259
|
-
).toStrictEqual({
|
|
260
|
-
options: {
|
|
261
|
-
optional: 'CHANGED_OPTIONAL_VALUE',
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
test('{value} + empty', () => {
|
|
267
|
-
expect(
|
|
268
|
-
mergeRule(
|
|
269
|
-
{
|
|
270
|
-
value: [],
|
|
271
|
-
},
|
|
272
|
-
{},
|
|
273
|
-
),
|
|
274
|
-
).toStrictEqual({
|
|
275
|
-
value: [],
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
test('{value} + {options}', () => {
|
|
280
|
-
expect(
|
|
281
|
-
mergeRule(
|
|
282
|
-
{
|
|
283
|
-
value: [],
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
options: {},
|
|
287
|
-
},
|
|
288
|
-
),
|
|
289
|
-
).toStrictEqual({
|
|
290
|
-
value: [],
|
|
291
|
-
options: {},
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
});
|
package/test/utils.spec.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
const { exchangeValueOnRule, provideValue } = require('../lib/utils');
|
|
2
|
-
|
|
3
|
-
it('provideValue', () => {
|
|
4
|
-
expect(
|
|
5
|
-
provideValue('The name is {{ dataName }}', {
|
|
6
|
-
$0: 'data-hoge',
|
|
7
|
-
$1: 'hoge',
|
|
8
|
-
dataName: 'hoge',
|
|
9
|
-
}),
|
|
10
|
-
).toBe('The name is hoge');
|
|
11
|
-
|
|
12
|
-
expect(provideValue('The name is {{ dataName }}', {})).toBeUndefined();
|
|
13
|
-
|
|
14
|
-
expect(
|
|
15
|
-
provideValue('No variable', {
|
|
16
|
-
$0: 'data-hoge',
|
|
17
|
-
$1: 'hoge',
|
|
18
|
-
dataName: 'hoge',
|
|
19
|
-
}),
|
|
20
|
-
).toBe('No variable');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('exchangeValueOnRule', () => {
|
|
24
|
-
expect(
|
|
25
|
-
exchangeValueOnRule('The name is {{ dataName }}', {
|
|
26
|
-
$0: 'data-hoge',
|
|
27
|
-
$1: 'hoge',
|
|
28
|
-
dataName: 'hoge',
|
|
29
|
-
}),
|
|
30
|
-
).toBe('The name is hoge');
|
|
31
|
-
|
|
32
|
-
expect(
|
|
33
|
-
exchangeValueOnRule(
|
|
34
|
-
{
|
|
35
|
-
value: 'The name is {{ dataName }}',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
$0: 'data-hoge',
|
|
39
|
-
$1: 'hoge',
|
|
40
|
-
dataName: 'hoge',
|
|
41
|
-
},
|
|
42
|
-
),
|
|
43
|
-
).toStrictEqual({
|
|
44
|
-
value: 'The name is hoge',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
expect(
|
|
48
|
-
exchangeValueOnRule(
|
|
49
|
-
{
|
|
50
|
-
severity: 'error',
|
|
51
|
-
value: 'The name is {{ dataName }}',
|
|
52
|
-
reason: 'For {{ dataName }}',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
$0: 'data-hoge',
|
|
56
|
-
$1: 'hoge',
|
|
57
|
-
dataName: 'hoge',
|
|
58
|
-
},
|
|
59
|
-
),
|
|
60
|
-
).toStrictEqual({
|
|
61
|
-
severity: 'error',
|
|
62
|
-
value: 'The name is hoge',
|
|
63
|
-
reason: 'For hoge',
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
expect(
|
|
67
|
-
exchangeValueOnRule(
|
|
68
|
-
{
|
|
69
|
-
value: 'The name is {{ dataName }}',
|
|
70
|
-
option: {
|
|
71
|
-
propA: 'The name is {{ dataName }}',
|
|
72
|
-
propB: ['The name is {{ dataName }}'],
|
|
73
|
-
propC: {
|
|
74
|
-
prop: 'The name is {{ dataName }}',
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
dataName: 'hoge',
|
|
80
|
-
},
|
|
81
|
-
),
|
|
82
|
-
).toStrictEqual({
|
|
83
|
-
value: 'The name is hoge',
|
|
84
|
-
options: {
|
|
85
|
-
propA: 'The name is hoge',
|
|
86
|
-
propB: ['The name is hoge'],
|
|
87
|
-
propC: {
|
|
88
|
-
prop: 'The name is hoge',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(
|
|
94
|
-
exchangeValueOnRule(
|
|
95
|
-
{
|
|
96
|
-
value: 'The name is {{ dataName }}',
|
|
97
|
-
options: {
|
|
98
|
-
propA: 'The name is {{ dataName }}',
|
|
99
|
-
propB: ['The name is {{ dataName }}'],
|
|
100
|
-
propC: {
|
|
101
|
-
prop: 'The name is {{ dataName }}',
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
dataName: 'hoge',
|
|
107
|
-
},
|
|
108
|
-
),
|
|
109
|
-
).toStrictEqual({
|
|
110
|
-
value: 'The name is hoge',
|
|
111
|
-
options: {
|
|
112
|
-
propA: 'The name is hoge',
|
|
113
|
-
propB: ['The name is hoge'],
|
|
114
|
-
propC: {
|
|
115
|
-
prop: 'The name is hoge',
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
});
|