markuplint 3.0.0-dev.25 → 3.0.0-dev.300
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/README.md +10 -6
- package/bin/markuplint.mjs +3 -0
- package/lib/api/index.d.ts +2 -2
- package/lib/api/index.js +2 -10
- package/lib/api/lint.d.ts +3 -3
- package/lib/api/lint.js +5 -10
- package/lib/api/ml-engine.d.ts +15 -9
- package/lib/api/ml-engine.js +135 -102
- package/lib/api/types.d.ts +30 -34
- package/lib/api/types.js +1 -2
- package/lib/api/v1.d.ts +12 -12
- package/lib/api/v1.js +13 -24
- package/lib/cli/bootstrap.d.ts +15 -7
- package/lib/cli/bootstrap.js +19 -11
- package/lib/cli/command.d.ts +3 -3
- package/lib/cli/command.js +27 -26
- package/lib/cli/create-rule/index.js +56 -42
- package/lib/cli/index.js +27 -31
- package/lib/cli/init/create-config.d.ts +4 -0
- package/lib/cli/init/create-config.js +90 -0
- package/lib/cli/init/get-default-rules.d.ts +3 -0
- package/lib/cli/init/get-default-rules.js +52 -0
- package/lib/cli/init/index.js +43 -231
- package/lib/cli/init/install-module.d.ts +3 -1
- package/lib/cli/init/install-module.js +22 -17
- package/lib/cli/init/types.d.ts +8 -0
- package/lib/cli/init/types.js +1 -0
- package/lib/cli/output.d.ts +2 -2
- package/lib/cli/output.js +13 -15
- package/lib/cli/prompt.d.ts +9 -9
- package/lib/cli/prompt.js +15 -25
- package/lib/cli/search/index.d.ts +2 -2
- package/lib/cli/search/index.js +7 -10
- package/lib/debug.js +8 -13
- package/lib/get-json-module.d.ts +1 -0
- package/lib/get-json-module.js +10 -0
- package/lib/global-settings.d.ts +1 -1
- package/lib/global-settings.js +2 -7
- package/lib/i18n.js +9 -15
- package/lib/index.d.ts +7 -5
- package/lib/index.js +6 -10
- package/lib/reporter/github-reporter.d.ts +2 -0
- package/lib/reporter/github-reporter.js +19 -0
- package/lib/reporter/index.d.ts +3 -2
- package/lib/reporter/index.js +3 -5
- package/lib/reporter/simple-reporter.d.ts +2 -2
- package/lib/reporter/simple-reporter.js +12 -17
- package/lib/reporter/standard-reporter.d.ts +2 -2
- package/lib/reporter/standard-reporter.js +18 -23
- package/lib/testing-tool/index.d.ts +10 -10
- package/lib/testing-tool/index.js +17 -25
- package/lib/types.d.ts +6 -7
- package/lib/types.js +1 -2
- package/lib/util.d.ts +0 -2
- package/lib/util.js +21 -37
- package/lib/v1.d.ts +1 -1
- package/lib/v1.js +1 -5
- package/lib/version.d.ts +1 -0
- package/lib/version.js +3 -0
- package/package.json +43 -31
- package/bin/markuplint +0 -3
- package/media/screenshot01.png +0 -0
- package/test/plugin001.js +0 -24
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const extRExp = {
|
|
2
|
+
jsx: '\\.[jt]sx?$',
|
|
3
|
+
vue: '\\.vue$',
|
|
4
|
+
svelte: '\\.svelte$',
|
|
5
|
+
astro: '\\.astro$',
|
|
6
|
+
pug: '\\.pug$',
|
|
7
|
+
php: '\\.php$',
|
|
8
|
+
smarty: '\\.tpl$',
|
|
9
|
+
erb: '\\.erb$',
|
|
10
|
+
ejs: '\\.ejs$',
|
|
11
|
+
mustache: '\\.(mustache|hbs)$',
|
|
12
|
+
nunjucks: '\\.nunjucks$',
|
|
13
|
+
liquid: '\\.liquid$',
|
|
14
|
+
};
|
|
15
|
+
export const langs = {
|
|
16
|
+
jsx: 'React (JSX)',
|
|
17
|
+
vue: 'Vue',
|
|
18
|
+
svelte: 'Svelte',
|
|
19
|
+
astro: 'Astro',
|
|
20
|
+
pug: 'Pug',
|
|
21
|
+
php: 'PHP',
|
|
22
|
+
smarty: 'Smarty',
|
|
23
|
+
erb: 'eRuby',
|
|
24
|
+
ejs: 'EJS',
|
|
25
|
+
mustache: 'Mustache/Handlebars',
|
|
26
|
+
nunjucks: 'Nunjucks',
|
|
27
|
+
liquid: 'liquid (Shopify)',
|
|
28
|
+
};
|
|
29
|
+
export function createConfig(langs, mode, defaultRules) {
|
|
30
|
+
let config = {};
|
|
31
|
+
const parser = { ...config.parser };
|
|
32
|
+
for (const lang of langs) {
|
|
33
|
+
const ext = extRExp[lang];
|
|
34
|
+
if (!ext) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
parser[ext] = `@markuplint/${lang}-parser`;
|
|
38
|
+
if (lang === 'vue') {
|
|
39
|
+
config = {
|
|
40
|
+
...config,
|
|
41
|
+
specs: {
|
|
42
|
+
...config.specs,
|
|
43
|
+
'\\.vue$': '@markuplint/vue-spec',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (lang === 'jsx') {
|
|
48
|
+
config = {
|
|
49
|
+
...config,
|
|
50
|
+
specs: {
|
|
51
|
+
...config.specs,
|
|
52
|
+
'\\.[jt]sx?$': '@markuplint/react-spec',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (Object.keys(parser).length > 0) {
|
|
58
|
+
config.parser = parser;
|
|
59
|
+
}
|
|
60
|
+
const rules = { ...config.rules };
|
|
61
|
+
if (Array.isArray(mode)) {
|
|
62
|
+
const ruleNames = Object.keys(defaultRules);
|
|
63
|
+
for (const ruleName of ruleNames) {
|
|
64
|
+
const rule = defaultRules[ruleName];
|
|
65
|
+
if (!rule) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (mode.includes(rule.category)) {
|
|
69
|
+
rules[ruleName] = rule.defaultValue;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (mode === 'recommended') {
|
|
74
|
+
config.extends = [...(config.extends ?? []), 'markuplint:recommended'];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const ruleNames = Object.keys(defaultRules);
|
|
78
|
+
for (const ruleName of ruleNames) {
|
|
79
|
+
const rule = defaultRules[ruleName];
|
|
80
|
+
if (!rule) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
rules[ruleName] = rule.defaultValue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (Object.keys(rules).length > 0) {
|
|
87
|
+
config.rules = rules;
|
|
88
|
+
}
|
|
89
|
+
return config;
|
|
90
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import matter from 'gray-matter';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
const RULES_SCHEMA_URL = 'https://raw.githubusercontent.com/markuplint/markuplint/[VERSION]/packages/@markuplint/rules/schema.json';
|
|
4
|
+
const RULES_README_URL = 'https://raw.githubusercontent.com/markuplint/markuplint/[VERSION]/packages/@markuplint/rules/src/[NAME]/README.md';
|
|
5
|
+
export async function getDefaultRules(version) {
|
|
6
|
+
const json = await safeFetch(RULES_SCHEMA_URL, version);
|
|
7
|
+
const rules = {};
|
|
8
|
+
await Promise.all(Object.entries(json.definitions.rules.properties).map(async ([name, rule]) => {
|
|
9
|
+
const json = await safeFetch(rule.$ref.replace('/main/', '/[VERSION]/'), version);
|
|
10
|
+
let severity = (Array.isArray(json.oneOf) ? json.oneOf : []).find((val) => val.properties)?.properties
|
|
11
|
+
?.severity?.default;
|
|
12
|
+
let category = json._category;
|
|
13
|
+
if (severity == null || category == null) {
|
|
14
|
+
const data = await getCatAndSeverityFromLegacy(version, name);
|
|
15
|
+
severity = data.severity;
|
|
16
|
+
category = data.category;
|
|
17
|
+
}
|
|
18
|
+
const defaultValue = severity === 'warning' ? false : json.definitions.value.default ?? true;
|
|
19
|
+
rules[name] = {
|
|
20
|
+
defaultValue,
|
|
21
|
+
category,
|
|
22
|
+
};
|
|
23
|
+
}));
|
|
24
|
+
return rules;
|
|
25
|
+
}
|
|
26
|
+
async function safeFetch(baseUrl, version, type = 'json') {
|
|
27
|
+
const url = baseUrl.replace('[VERSION]', `v${version}`);
|
|
28
|
+
const res = await fetch(url);
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
return safeFetch(baseUrl, '3.0.0', type);
|
|
31
|
+
}
|
|
32
|
+
if (type === 'json') {
|
|
33
|
+
return (await res.json());
|
|
34
|
+
}
|
|
35
|
+
const md = await res.text();
|
|
36
|
+
const { data } = matter(md);
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fallback fetching until 3.0.x
|
|
41
|
+
*
|
|
42
|
+
* @param version
|
|
43
|
+
* @param name
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
async function getCatAndSeverityFromLegacy(version, name) {
|
|
47
|
+
const data = await safeFetch(RULES_README_URL.replace('[NAME]', name), version, 'md');
|
|
48
|
+
return {
|
|
49
|
+
category: data.category,
|
|
50
|
+
severity: data.severity,
|
|
51
|
+
};
|
|
52
|
+
}
|
package/lib/cli/init/index.js
CHANGED
|
@@ -1,267 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import module from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import util from 'node:util';
|
|
5
|
+
import { head, write, error } from '../../util.js';
|
|
6
|
+
import { confirm, confirmSequence, multiSelect } from '../prompt.js';
|
|
7
|
+
import { createConfig, langs } from './create-config.js';
|
|
8
|
+
import { getDefaultRules } from './get-default-rules.js';
|
|
9
|
+
import { installModule, selectModules } from './install-module.js';
|
|
10
|
+
const require = module.createRequire(import.meta.url);
|
|
11
|
+
const writeFile = util.promisify(fs.writeFile);
|
|
13
12
|
const ruleCategories = {
|
|
14
13
|
validation: {
|
|
15
14
|
message: 'Are you going to conformance check according to HTML standard?',
|
|
16
15
|
},
|
|
17
16
|
a11y: {
|
|
18
|
-
message: '
|
|
17
|
+
message: 'Do you want high accessibility?',
|
|
19
18
|
},
|
|
20
19
|
'naming-convention': {
|
|
21
20
|
message: 'Are you going to set the convention about naming?',
|
|
22
21
|
},
|
|
22
|
+
maintainability: {
|
|
23
|
+
message: 'Do you want high maintainability?',
|
|
24
|
+
},
|
|
23
25
|
style: {
|
|
24
26
|
message: 'Are you going to check for the code styles?',
|
|
25
27
|
},
|
|
26
28
|
};
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
'attr-value-quotes': {
|
|
33
|
-
category: 'style',
|
|
34
|
-
default: true,
|
|
35
|
-
},
|
|
36
|
-
'case-sensitive-attr-name': {
|
|
37
|
-
category: 'style',
|
|
38
|
-
default: true,
|
|
39
|
-
},
|
|
40
|
-
'case-sensitive-attr-value': {
|
|
41
|
-
category: 'style',
|
|
42
|
-
default: true,
|
|
43
|
-
},
|
|
44
|
-
'case-sensitive-tag-name': {
|
|
45
|
-
category: 'style',
|
|
46
|
-
default: true,
|
|
47
|
-
},
|
|
48
|
-
'character-reference': {
|
|
49
|
-
category: 'style',
|
|
50
|
-
default: true,
|
|
51
|
-
},
|
|
52
|
-
'class-naming': {
|
|
53
|
-
category: 'naming-convention',
|
|
54
|
-
default: false,
|
|
55
|
-
recommendedValue: '/.+/',
|
|
56
|
-
},
|
|
57
|
-
'deprecated-attr': {
|
|
58
|
-
category: 'validation',
|
|
59
|
-
default: true,
|
|
60
|
-
},
|
|
61
|
-
'deprecated-element': {
|
|
62
|
-
category: 'validation',
|
|
63
|
-
default: true,
|
|
64
|
-
},
|
|
65
|
-
'disallowed-element': {
|
|
66
|
-
category: 'validation',
|
|
67
|
-
default: false,
|
|
68
|
-
},
|
|
69
|
-
doctype: {
|
|
70
|
-
category: 'validation',
|
|
71
|
-
default: true,
|
|
72
|
-
},
|
|
73
|
-
'end-tag': {
|
|
74
|
-
category: 'style',
|
|
75
|
-
default: true,
|
|
76
|
-
},
|
|
77
|
-
'id-duplication': {
|
|
78
|
-
category: 'validation',
|
|
79
|
-
default: true,
|
|
80
|
-
},
|
|
81
|
-
'ineffective-attr': {
|
|
82
|
-
category: 'validation',
|
|
83
|
-
default: true,
|
|
84
|
-
},
|
|
85
|
-
'invalid-attr': {
|
|
86
|
-
category: 'validation',
|
|
87
|
-
default: true,
|
|
88
|
-
},
|
|
89
|
-
'label-has-control': {
|
|
90
|
-
category: 'a11y',
|
|
91
|
-
default: false,
|
|
92
|
-
},
|
|
93
|
-
'landmark-roles': {
|
|
94
|
-
category: 'a11y',
|
|
95
|
-
default: true,
|
|
96
|
-
},
|
|
97
|
-
'no-boolean-attr-value': {
|
|
98
|
-
category: 'style',
|
|
99
|
-
default: true,
|
|
100
|
-
},
|
|
101
|
-
'no-default-value': {
|
|
102
|
-
category: 'style',
|
|
103
|
-
default: true,
|
|
104
|
-
},
|
|
105
|
-
'no-empty-palpable-content': {
|
|
106
|
-
category: 'validation',
|
|
107
|
-
default: false,
|
|
108
|
-
},
|
|
109
|
-
'no-hard-code-id': {
|
|
110
|
-
category: 'style',
|
|
111
|
-
default: true,
|
|
112
|
-
},
|
|
113
|
-
'no-refer-to-non-existent-id': {
|
|
114
|
-
category: 'a11y',
|
|
115
|
-
default: true,
|
|
116
|
-
},
|
|
117
|
-
'no-use-event-handler-attr': {
|
|
118
|
-
category: 'style',
|
|
119
|
-
default: true,
|
|
120
|
-
},
|
|
121
|
-
'permitted-contents': {
|
|
122
|
-
category: 'validation',
|
|
123
|
-
default: true,
|
|
124
|
-
},
|
|
125
|
-
'required-attr': {
|
|
126
|
-
category: 'validation',
|
|
127
|
-
default: true,
|
|
128
|
-
},
|
|
129
|
-
'required-element': {
|
|
130
|
-
category: 'validation',
|
|
131
|
-
default: true,
|
|
132
|
-
},
|
|
133
|
-
'required-h1': {
|
|
134
|
-
category: 'a11y',
|
|
135
|
-
default: true,
|
|
136
|
-
},
|
|
137
|
-
'use-list': {
|
|
138
|
-
category: 'a11y',
|
|
139
|
-
default: false,
|
|
140
|
-
},
|
|
141
|
-
'wai-aria': {
|
|
142
|
-
category: 'a11y',
|
|
143
|
-
default: true,
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
const extRExp = {
|
|
147
|
-
jsx: '\\.[jt]sx?$',
|
|
148
|
-
vue: '\\.vue$',
|
|
149
|
-
svelte: '\\.svelte$',
|
|
150
|
-
astro: '\\.astro',
|
|
151
|
-
pug: '\\.pug$',
|
|
152
|
-
php: '\\.php$',
|
|
153
|
-
erb: '\\.erb$',
|
|
154
|
-
ejs: '\\.ejs$',
|
|
155
|
-
mustache: '\\.(mustache|handlebars)$',
|
|
156
|
-
nunjucks: '\\.nunjucks$',
|
|
157
|
-
liquid: '\\.liquid$',
|
|
158
|
-
};
|
|
159
|
-
async function initialize() {
|
|
160
|
-
let config = {};
|
|
161
|
-
(0, util_2.write)((0, util_2.head)('Initialization'));
|
|
162
|
-
util_2.write.break();
|
|
163
|
-
const langs = await (0, prompt_1.multiSelect)({
|
|
29
|
+
export async function initialize() {
|
|
30
|
+
write(head('Initialization'));
|
|
31
|
+
write.break();
|
|
32
|
+
const selectedLangs = await multiSelect({
|
|
164
33
|
message: 'Which do you use template engines?',
|
|
165
|
-
choices: [
|
|
166
|
-
{ name: 'React (JSX)', value: 'jsx' },
|
|
167
|
-
{ name: 'Vue', value: 'vue' },
|
|
168
|
-
{ name: 'Svelte', value: 'svelte' },
|
|
169
|
-
{ name: 'Astro', value: 'astro' },
|
|
170
|
-
{ name: 'Pug', value: 'pug' },
|
|
171
|
-
{ name: 'PHP', value: 'php' },
|
|
172
|
-
{ name: 'Smarty', value: 'smarty' },
|
|
173
|
-
{ name: 'eRuby', value: 'erb' },
|
|
174
|
-
{ name: 'EJS', value: 'ejs' },
|
|
175
|
-
{ name: 'Mustache/Handlebars', value: 'mustache' },
|
|
176
|
-
{ name: 'Nunjucks', value: 'nunjucks' },
|
|
177
|
-
{ name: 'liquid (Shopify)', value: 'liquid' },
|
|
178
|
-
],
|
|
34
|
+
choices: Object.entries(langs).map(([key, name]) => ({ name, value: key })),
|
|
179
35
|
});
|
|
180
|
-
const autoInstall = await
|
|
181
|
-
const customize = await
|
|
182
|
-
|
|
183
|
-
config.parser = config.parser || {};
|
|
184
|
-
// @ts-ignore
|
|
185
|
-
const ext = extRExp[lang];
|
|
186
|
-
if (!ext) {
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
config.parser[ext] = `@markuplint/${lang}-parser`;
|
|
190
|
-
if (lang === 'vue') {
|
|
191
|
-
config = (0, ml_config_1.mergeConfig)(config, {
|
|
192
|
-
specs: {
|
|
193
|
-
'\\.vue$': '@markuplint/vue-spec',
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
if (lang === 'jsx') {
|
|
198
|
-
config = (0, ml_config_1.mergeConfig)(config, {
|
|
199
|
-
specs: {
|
|
200
|
-
'\\.[jt]sx?$': '@markuplint/react-spec',
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
36
|
+
const autoInstall = await confirm('May I install them automatically?');
|
|
37
|
+
const customize = await confirm('Do you customize rules?');
|
|
38
|
+
let ruleSettingMode = 'none';
|
|
205
39
|
if (customize) {
|
|
206
|
-
const ruleNames = Object.keys(defaultRules);
|
|
207
40
|
const categories = Object.keys(ruleCategories);
|
|
208
|
-
const
|
|
41
|
+
const selectedCategories = await confirmSequence(categories.map(catName => {
|
|
209
42
|
const cat = ruleCategories[catName];
|
|
210
43
|
return {
|
|
211
44
|
message: cat.message,
|
|
212
45
|
name: catName,
|
|
213
46
|
};
|
|
214
47
|
}));
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
if (res[rule.category]) {
|
|
221
|
-
if (!config.rules) {
|
|
222
|
-
config.rules = {};
|
|
223
|
-
}
|
|
224
|
-
config.rules[ruleName] = rule.recommendedValue || true;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
48
|
+
ruleSettingMode = Object.entries(selectedCategories)
|
|
49
|
+
.map(([name, enabled]) => (enabled ? name : ''))
|
|
50
|
+
.filter((name) => !!name);
|
|
227
51
|
}
|
|
228
|
-
else {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const ruleNames = Object.keys(defaultRules);
|
|
236
|
-
for (const ruleName of ruleNames) {
|
|
237
|
-
const rule = defaultRules[ruleName];
|
|
238
|
-
config.rules[ruleName] = rule.default;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
52
|
+
else if (await confirm('Does it import the recommended config?')) {
|
|
53
|
+
ruleSettingMode = 'recommended';
|
|
54
|
+
}
|
|
55
|
+
let defaultRules = {};
|
|
56
|
+
if (ruleSettingMode !== 'recommended') {
|
|
57
|
+
const rulesVersion = require('../../../package.json').version;
|
|
58
|
+
defaultRules = await getDefaultRules(rulesVersion);
|
|
241
59
|
}
|
|
242
|
-
const
|
|
60
|
+
const config = createConfig(selectedLangs, ruleSettingMode, defaultRules);
|
|
61
|
+
const filePath = path.resolve(process.cwd(), '.markuplintrc');
|
|
243
62
|
await writeFile(filePath, JSON.stringify(config, null, 2), { encoding: 'utf-8' });
|
|
244
|
-
|
|
63
|
+
write(`✨Created: ${filePath}`);
|
|
245
64
|
if (autoInstall) {
|
|
246
|
-
|
|
247
|
-
const modules =
|
|
248
|
-
|
|
249
|
-
modules.push('@markuplint/vue-spec');
|
|
250
|
-
}
|
|
251
|
-
if (langs.includes('jsx')) {
|
|
252
|
-
modules.push('@markuplint/react-spec');
|
|
253
|
-
}
|
|
254
|
-
const result = await (0, install_module_1.installModule)(modules, true).catch(e => new Error(e));
|
|
65
|
+
write('Install automatically');
|
|
66
|
+
const modules = selectModules(selectedLangs);
|
|
67
|
+
const result = await installModule(modules, true).catch(e => new Error(e));
|
|
255
68
|
if (result instanceof Error) {
|
|
256
|
-
|
|
69
|
+
error.exit();
|
|
257
70
|
return;
|
|
258
71
|
}
|
|
259
72
|
if (result.alreadyExists) {
|
|
260
|
-
|
|
73
|
+
write('Modules are installed already.');
|
|
261
74
|
}
|
|
262
75
|
else {
|
|
263
|
-
|
|
76
|
+
write('✨ Success');
|
|
264
77
|
}
|
|
265
78
|
}
|
|
266
79
|
}
|
|
267
|
-
exports.initialize = initialize;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { Langs } from './types.js';
|
|
1
2
|
export type InstallModuleResult = {
|
|
2
3
|
success: boolean;
|
|
3
4
|
alreadyExists: boolean;
|
|
4
5
|
};
|
|
5
|
-
export declare function
|
|
6
|
+
export declare function selectModules(selectedLangs: readonly Langs[]): string[];
|
|
7
|
+
export declare function installModule(module: readonly string[], dev?: boolean): Promise<InstallModuleResult>;
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.installModule = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const child_process_1 = require("child_process");
|
|
6
|
-
const cli_color_1 = tslib_1.__importDefault(require("cli-color"));
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import c from 'cli-color';
|
|
7
3
|
// @ts-ignore
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
import detectInstalled from 'detect-installed';
|
|
5
|
+
import hasYarn from 'has-yarn';
|
|
6
|
+
export function selectModules(selectedLangs) {
|
|
7
|
+
const modules = ['markuplint', ...selectedLangs.map(lang => `@markuplint/${lang}-parser`)];
|
|
8
|
+
if (selectedLangs.includes('vue')) {
|
|
9
|
+
modules.push('@markuplint/vue-spec');
|
|
10
|
+
}
|
|
11
|
+
if (selectedLangs.includes('jsx')) {
|
|
12
|
+
modules.push('@markuplint/react-spec');
|
|
13
|
+
}
|
|
14
|
+
return modules;
|
|
15
|
+
}
|
|
16
|
+
export async function installModule(module, dev = false) {
|
|
11
17
|
module = module.map(m => m.trim());
|
|
12
18
|
const uninstallMods = [];
|
|
13
19
|
try {
|
|
@@ -21,25 +27,25 @@ async function installModule(module, dev = false) {
|
|
|
21
27
|
catch (_) {
|
|
22
28
|
// void
|
|
23
29
|
}
|
|
24
|
-
if (
|
|
30
|
+
if (uninstallMods.length === 0) {
|
|
25
31
|
return {
|
|
26
32
|
success: true,
|
|
27
33
|
alreadyExists: true,
|
|
28
34
|
};
|
|
29
35
|
}
|
|
30
|
-
const mod = (
|
|
31
|
-
const installOpt = (
|
|
36
|
+
const mod = hasYarn() ? 'yarn' : 'npm';
|
|
37
|
+
const installOpt = hasYarn() ? 'add' : 'install';
|
|
32
38
|
const opt = [installOpt];
|
|
33
39
|
if (dev) {
|
|
34
40
|
opt.push('-D');
|
|
35
41
|
}
|
|
36
|
-
if (!(
|
|
42
|
+
if (!hasYarn()) {
|
|
37
43
|
opt.push('--legacy-peer-deps');
|
|
38
44
|
}
|
|
39
45
|
opt.push(...uninstallMods);
|
|
40
46
|
return new Promise((resolve, reject) => {
|
|
41
|
-
process.stdout.write(
|
|
42
|
-
const result =
|
|
47
|
+
process.stdout.write(c.blackBright(`${mod} ${opt.join(' ')}\n`));
|
|
48
|
+
const result = spawnSync(mod, opt, { stdio: 'inherit' });
|
|
43
49
|
if (result.error || result.status !== 0) {
|
|
44
50
|
const message = 'Error running command.';
|
|
45
51
|
const error = new Error(message);
|
|
@@ -52,11 +58,10 @@ async function installModule(module, dev = false) {
|
|
|
52
58
|
});
|
|
53
59
|
});
|
|
54
60
|
}
|
|
55
|
-
exports.installModule = installModule;
|
|
56
61
|
function isInstalled(module) {
|
|
57
62
|
return new Promise((resolve, reject) => {
|
|
58
63
|
try {
|
|
59
|
-
(
|
|
64
|
+
detectInstalled(module, {
|
|
60
65
|
local: true,
|
|
61
66
|
}).then((exists) => {
|
|
62
67
|
resolve(exists);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type Langs = 'jsx' | 'vue' | 'svelte' | 'astro' | 'pug' | 'php' | 'smarty' | 'erb' | 'ejs' | 'mustache' | 'nunjucks' | 'liquid';
|
|
2
|
+
export type Category = 'validation' | 'a11y' | 'naming-convention' | 'style' | 'maintainability';
|
|
3
|
+
export type RuleSettingMode = readonly Category[] | 'recommended' | 'none';
|
|
4
|
+
export type DefaultRules = Readonly<Record<string, Rule>>;
|
|
5
|
+
export type Rule = {
|
|
6
|
+
readonly category: Category;
|
|
7
|
+
readonly defaultValue: boolean | string | number;
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/cli/output.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { CLIOptions } from './bootstrap.js';
|
|
2
|
+
import type { MLResultInfo } from '../types.js';
|
|
3
3
|
export declare function output(results: MLResultInfo, options: CLIOptions): void;
|
package/lib/cli/output.js
CHANGED
|
@@ -1,36 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const strip_ansi_1 = tslib_1.__importDefault(require("strip-ansi"));
|
|
6
|
-
const reporter_1 = require("../reporter");
|
|
7
|
-
function output(results, options) {
|
|
8
|
-
var _a;
|
|
9
|
-
const format = (_a = options.format) !== null && _a !== void 0 ? _a : 'Standard';
|
|
1
|
+
import stripAnsi from 'strip-ansi';
|
|
2
|
+
import { simpleReporter, standardReporter, githubReporter } from '../reporter/index.js';
|
|
3
|
+
export function output(results, options) {
|
|
4
|
+
const format = options.format ?? 'Standard';
|
|
10
5
|
let out;
|
|
11
6
|
switch (format.toLowerCase()) {
|
|
12
7
|
case 'json': {
|
|
13
8
|
return;
|
|
14
9
|
}
|
|
15
10
|
case 'simple': {
|
|
16
|
-
out =
|
|
11
|
+
out = simpleReporter(results, options);
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
case 'github': {
|
|
15
|
+
out = githubReporter(results);
|
|
17
16
|
break;
|
|
18
17
|
}
|
|
19
18
|
default: {
|
|
20
|
-
out =
|
|
19
|
+
out = standardReporter(results, options);
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
if (
|
|
22
|
+
if (out.length === 0) {
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
25
|
let msg = `${out.join('\n')}\n`;
|
|
27
|
-
msg = options.color ? msg : (
|
|
26
|
+
msg = options.color ? msg : stripAnsi(msg);
|
|
28
27
|
// If it has errors, Write to `stderr` and failure and exit.
|
|
29
|
-
if (results.violations.length) {
|
|
28
|
+
if (results.violations.length > 0) {
|
|
30
29
|
process.stderr.write(msg);
|
|
31
30
|
process.exitCode = 1;
|
|
32
31
|
return;
|
|
33
32
|
}
|
|
34
33
|
process.stdout.write(msg);
|
|
35
34
|
}
|
|
36
|
-
exports.output = output;
|
package/lib/cli/prompt.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
type SelectQuestion<T> = {
|
|
2
|
-
message: string;
|
|
3
|
-
choices: {
|
|
4
|
-
name: string;
|
|
5
|
-
value: T;
|
|
2
|
+
readonly message: string;
|
|
3
|
+
readonly choices: readonly {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly value: T;
|
|
6
6
|
}[];
|
|
7
7
|
};
|
|
8
8
|
export declare function select<T>(question: SelectQuestion<T>): Promise<T>;
|
|
9
9
|
export declare function multiSelect<T>(question: SelectQuestion<T>): Promise<T[]>;
|
|
10
|
-
export declare function input<T extends string = string>(question: string, validation?: RegExp): Promise<T>;
|
|
10
|
+
export declare function input<T extends string = string>(question: string, validation?: Readonly<RegExp>): Promise<T>;
|
|
11
11
|
export declare function confirm(question: string, options?: {
|
|
12
|
-
initial?: boolean;
|
|
12
|
+
readonly initial?: boolean;
|
|
13
13
|
}): Promise<boolean>;
|
|
14
|
-
export declare function confirmSequence<T extends string = string>(questions: {
|
|
15
|
-
message: string;
|
|
16
|
-
name: T;
|
|
14
|
+
export declare function confirmSequence<T extends string = string>(questions: readonly {
|
|
15
|
+
readonly message: string;
|
|
16
|
+
readonly name: T;
|
|
17
17
|
}[]): Promise<Record<T, boolean>>;
|
|
18
18
|
export {};
|