@markuplint/ml-config 3.9.0 → 3.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- 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>>;
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
- | Nullable<PrimitiveScalar>
22
- | readonly PlainData[]
23
- | {
24
- readonly [key: string]: PlainData | any;
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
- readonly name: string;
35
- readonly settings: Readonly<Record<string, NonNullablePlainData>>;
28
+ readonly name: string;
29
+ readonly settings: Readonly<Record<string, NonNullablePlainData>>;
36
30
  };
37
31
  export type ParserConfig = {
38
- readonly [extensionPattern: string]: string;
32
+ readonly [extensionPattern: string]: string;
39
33
  };
40
34
  export type SpecConfig = {
41
- readonly [extensionPattern: string]: string;
35
+ readonly [extensionPattern: string]: string;
42
36
  };
43
37
  export type Pretender = {
44
- /**
45
- * Target node selectors
46
- */
47
- readonly selector: string;
48
- /**
49
- * If it is a string, it is resolved as an element name.
50
- * An element has the same attributes as the pretended custom element
51
- * because attributes are just inherited.
52
- *
53
- * If it is an Object, It creates the element by that.
54
- */
55
- readonly as: string | OriginalNode;
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
- * Element name
60
- */
61
- readonly element: string;
62
- /**
63
- * Namespace
64
- *
65
- * Supports `"svg"` and `undefined` only.
66
- * If it is `undefined`, the namespace is HTML.
67
- */
68
- readonly namespace?: 'svg';
69
- /**
70
- * Attributes
71
- */
72
- readonly attrs?: readonly {
73
- /**
74
- * Attribute name
75
- */
76
- readonly name: string;
77
- /**
78
- * If it omits this property, the attribute is resolved as a boolean.
79
- */
80
- readonly value?:
81
- | string
82
- | {
83
- readonly fromAttr: string;
84
- };
85
- }[];
86
- /**
87
- * To have attributes the defined element has.
88
- */
89
- readonly inheritAttrs?: boolean;
90
- /**
91
- * ARIA properties
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
- * Accessible name
101
- *
102
- * - If it is `true`, it assumes the element has any text on its accessible name.
103
- * - If it specifies `fromAttr` property, it assumes the accessible name refers to the value of the attribute.
104
- */
105
- readonly name?:
106
- | boolean
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
- readonly [ruleName: string]: AnyRule;
112
+ readonly [ruleName: string]: AnyRule;
126
113
  };
127
114
  export type RuleConfig<T extends RuleConfigValue, O extends PlainData = undefined> = {
128
- readonly severity?: Severity;
129
- readonly value?: Readonly<T>;
130
- readonly options?: Readonly<O>;
131
- readonly reason?: string;
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
- readonly severity?: Severity;
138
- readonly value?: Readonly<T>;
139
- readonly reason?: string;
140
- /**
141
- * Old property
142
- *
143
- * @deprecated
144
- * @see {this.options}
145
- */
146
- readonly option?: Readonly<O>;
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
- readonly selector?: string;
152
- readonly regexSelector?: RegexSelector;
153
- readonly categories?: readonly string[];
154
- readonly roles?: readonly string[];
155
- readonly obsolete?: boolean;
156
- readonly rules?: Rules;
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
- readonly selector?: string;
160
- readonly regexSelector?: RegexSelector;
161
- readonly inheritance?: boolean;
162
- readonly rules?: Rules;
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
- readonly message: string;
170
- readonly scope: Scope<T, O>;
153
+ readonly message: string;
154
+ readonly scope: Scope<T, O>;
171
155
  };
172
156
  export type Report2 = {
173
- readonly message: string;
174
- readonly line: number;
175
- readonly col: number;
176
- readonly raw: string;
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
- readonly rule: RuleInfo<T, O>;
180
- readonly startLine: number;
181
- readonly startCol: number;
182
- readonly raw: string;
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
- readonly ruleId: string;
186
- readonly severity: Severity;
187
- readonly message: string;
188
- readonly reason?: string;
189
- readonly line: number;
190
- readonly col: number;
191
- readonly raw: string;
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
- readonly disabled: boolean;
195
- readonly severity: Severity;
196
- readonly value: Readonly<T>;
197
- readonly options: Readonly<O>;
198
- readonly reason?: string;
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
- nodeRules: RuleInfo<T, O>[];
202
- childNodeRules: RuleInfo<T, O>[];
185
+ nodeRules: RuleInfo<T, O>[];
186
+ childNodeRules: RuleInfo<T, O>[];
203
187
  };
package/lib/utils.d.ts CHANGED
@@ -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
- rule: AnyRule | AnyRuleV2,
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/ml-config",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
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>",
@@ -19,14 +19,14 @@
19
19
  "clean": "tsc --build --clean"
20
20
  },
21
21
  "dependencies": {
22
- "@markuplint/ml-ast": "3.1.0",
23
- "@markuplint/selector": "3.9.0",
24
- "@markuplint/shared": "3.6.0",
22
+ "@markuplint/ml-ast": "3.2.0",
23
+ "@markuplint/selector": "3.11.0",
24
+ "@markuplint/shared": "3.8.0",
25
25
  "@types/mustache": "^4.2.2",
26
26
  "deepmerge": "^4.3.1",
27
27
  "is-plain-object": "^5.0.0",
28
28
  "mustache": "^4.2.0",
29
- "type-fest": "^3.10.0"
29
+ "type-fest": "^3.12.0"
30
30
  },
31
- "gitHead": "af370797bfc887e5a5a2ff57fbaa8392ac98ead2"
31
+ "gitHead": "4ab20276db48a6acb29a923ea8666890ca853442"
32
32
  }
@@ -1,233 +1,294 @@
1
1
  const { mergeConfig, mergeRule } = require('../lib/merge-config');
2
2
 
3
- it('test', () => {
4
- expect(mergeConfig({}, {})).toStrictEqual({});
5
- });
6
-
7
- it('test', () => {
8
- expect(
9
- mergeConfig(
10
- {
11
- plugins: ['a', 'b', 'c'],
12
- },
13
- {
14
- plugins: ['c', 'b', 'd'],
15
- },
16
- ),
17
- ).toStrictEqual({
18
- plugins: ['a', 'b', 'c', 'd'],
3
+ describe('mergeConfig', () => {
4
+ test('empty + empty', () => {
5
+ expect(mergeConfig({}, {})).toStrictEqual({});
19
6
  });
20
- });
21
7
 
22
- it('test', () => {
23
- expect(
24
- mergeConfig(
25
- {
26
- plugins: ['a', 'b', { name: 'c', settings: { foo: 'foo', bar: 'bar' } }],
27
- },
28
- {
29
- plugins: ['c', 'b', 'd', { name: 'c', settings: { foo2: 'foo2', bar: 'bar2' } }],
30
- },
31
- ),
32
- ).toStrictEqual({
33
- plugins: [
34
- 'a',
35
- 'b',
36
- {
37
- name: 'c',
38
- settings: {
39
- bar: 'bar2',
40
- foo: 'foo',
41
- foo2: 'foo2',
8
+ test('plugins + plugins', () => {
9
+ expect(
10
+ mergeConfig(
11
+ {
12
+ plugins: ['a', 'b', 'c'],
42
13
  },
43
- },
44
- 'd',
45
- ],
46
- });
47
- });
48
-
49
- it('test', () => {
50
- expect(
51
- mergeConfig(
52
- {
53
- parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
54
- },
55
- {
56
- parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
57
- },
58
- ),
59
- ).toStrictEqual({
60
- parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
14
+ {
15
+ plugins: ['c', 'b', 'd'],
16
+ },
17
+ ),
18
+ ).toStrictEqual({
19
+ plugins: ['a', 'b', 'c', 'd'],
20
+ });
61
21
  });
62
- });
63
22
 
64
- it('test', () => {
65
- expect(
66
- mergeConfig(
67
- {
68
- parser: { '/\\.vue$/i': '@markuplint/vue-parser' },
69
- },
70
- {
71
- parser: { '/\\.[jt]sx?$/i': '@markuplint/jsx-parser' },
72
- },
73
- ),
74
- ).toStrictEqual({
75
- parser: {
76
- '/\\.vue$/i': '@markuplint/vue-parser',
77
- '/\\.[jt]sx?$/i': '@markuplint/jsx-parser',
78
- },
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
+ });
79
48
  });
80
- });
81
49
 
82
- it('test', () => {
83
- expect(
84
- mergeRule(
85
- {
86
- value: true,
87
- },
88
- {},
89
- ),
90
- ).toStrictEqual({
91
- value: true,
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
+ });
92
63
  });
93
64
 
94
- expect(
95
- mergeRule(
96
- {
97
- value: true,
98
- },
99
- false,
100
- ),
101
- ).toStrictEqual(false);
102
-
103
- expect(
104
- mergeRule(
105
- {
106
- value: false,
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',
107
79
  },
108
- true,
109
- ),
110
- ).toStrictEqual({
111
- value: true,
80
+ });
112
81
  });
113
82
 
114
- expect(
115
- mergeRule(
116
- {
117
- options: {
118
- optional: 'OPTIONAL_VALUE',
83
+ test('overrides + overrides', () => {
84
+ expect(
85
+ mergeConfig(
86
+ {
87
+ overrides: {
88
+ a: {
89
+ rules: {
90
+ rule1: true,
91
+ },
92
+ },
93
+ },
119
94
  },
120
- },
121
- {
122
- options: {
123
- optional: 'CHANGED_OPTIONAL_VALUE',
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
+ },
124
121
  },
125
122
  },
126
- ),
127
- ).toStrictEqual({
128
- options: {
129
- optional: 'CHANGED_OPTIONAL_VALUE',
130
- },
123
+ });
131
124
  });
132
125
 
133
- expect(
134
- mergeRule(
135
- {
136
- option: {
137
- optional: 'OPTIONAL_VALUE',
126
+ test('rules + rules', () => {
127
+ expect(
128
+ mergeConfig(
129
+ {
130
+ rules: {
131
+ a: {
132
+ option: {
133
+ ruleA: true,
134
+ },
135
+ },
136
+ },
138
137
  },
139
- },
140
- {
141
- option: {
142
- optional: 'CHANGED_OPTIONAL_VALUE',
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
+ },
143
159
  },
144
160
  },
145
- ),
146
- ).toStrictEqual({
147
- options: {
148
- optional: 'CHANGED_OPTIONAL_VALUE',
149
- },
161
+ });
150
162
  });
151
- });
152
163
 
153
- it('test', () => {
154
- expect(
155
- mergeConfig(
156
- {
157
- overrides: {
158
- a: {
159
- rules: {
160
- rule1: true,
161
- },
164
+ test('rules[rule].value + rules[rule].value', () => {
165
+ expect(
166
+ mergeConfig(
167
+ {
168
+ rules: {
169
+ ruleA: true,
170
+ ruleB: [],
162
171
  },
163
172
  },
164
- },
165
- {
166
- overrides: {
167
- a: {
168
- rules: {
169
- rule1: false,
173
+ {
174
+ rules: {
175
+ ruleA: {
176
+ options: {
177
+ optionName: true,
178
+ },
170
179
  },
171
- },
172
- b: {
173
- rules: {
174
- rule1: true,
180
+ ruleB: {
181
+ options: {
182
+ optionName: true,
183
+ },
175
184
  },
176
185
  },
177
186
  },
178
- },
179
- ),
180
- ).toStrictEqual({
181
- overrides: {
182
- a: {
183
- rules: {
184
- rule1: false,
187
+ ),
188
+ ).toStrictEqual({
189
+ rules: {
190
+ ruleA: {
191
+ value: true,
192
+ options: {
193
+ optionName: true,
194
+ },
185
195
  },
186
- },
187
- b: {
188
- rules: {
189
- rule1: true,
196
+ ruleB: {
197
+ value: [],
198
+ options: {
199
+ optionName: true,
200
+ },
190
201
  },
191
202
  },
192
- },
203
+ });
193
204
  });
194
205
  });
195
206
 
196
- it('test', () => {
197
- expect(
198
- mergeConfig(
199
- {
200
- rules: {
201
- a: {
202
- // @ts-ignore
203
- option: {
204
- ruleA: true,
205
- },
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',
206
251
  },
207
252
  },
208
- },
209
- {
210
- rules: {
211
- b: {
212
- options: {
213
- ruleB: true,
214
- },
253
+ {
254
+ options: {
255
+ optional: 'CHANGED_OPTIONAL_VALUE',
215
256
  },
216
257
  },
258
+ ),
259
+ ).toStrictEqual({
260
+ options: {
261
+ optional: 'CHANGED_OPTIONAL_VALUE',
217
262
  },
218
- ),
219
- ).toStrictEqual({
220
- rules: {
221
- a: {
222
- options: {
223
- ruleA: true,
263
+ });
264
+ });
265
+
266
+ test('{value} + empty', () => {
267
+ expect(
268
+ mergeRule(
269
+ {
270
+ value: [],
224
271
  },
225
- },
226
- b: {
227
- options: {
228
- ruleB: true,
272
+ {},
273
+ ),
274
+ ).toStrictEqual({
275
+ value: [],
276
+ });
277
+ });
278
+
279
+ test('{value} + {options}', () => {
280
+ expect(
281
+ mergeRule(
282
+ {
283
+ value: [],
229
284
  },
230
- },
231
- },
285
+ {
286
+ options: {},
287
+ },
288
+ ),
289
+ ).toStrictEqual({
290
+ value: [],
291
+ options: {},
292
+ });
232
293
  });
233
294
  });