markuplint 2.0.0 → 2.1.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/api/index.d.mts +2 -0
- package/lib/api/index.mjs +2 -0
- package/lib/api/lint.d.mts +4 -0
- package/lib/api/lint.mjs +15 -0
- package/lib/api/ml-engine.d.mts +27 -0
- package/lib/api/ml-engine.d.ts +18 -18
- package/lib/api/ml-engine.mjs +232 -0
- package/lib/api/types.d.mts +43 -0
- package/lib/api/types.d.ts +32 -39
- package/lib/api/types.mjs +1 -0
- package/lib/api/v1.d.mts +51 -0
- package/lib/api/v1.d.ts +43 -43
- package/lib/api/v1.mjs +39 -0
- package/lib/cli/bootstrap.d.mts +52 -0
- package/lib/cli/bootstrap.d.ts +49 -50
- package/lib/cli/bootstrap.mjs +81 -0
- package/lib/cli/command.d.mts +3 -0
- package/lib/cli/command.mjs +50 -0
- package/lib/cli/create-rule/index.d.mts +1 -0
- package/lib/cli/create-rule/index.mjs +51 -0
- package/lib/cli/index.d.mts +1 -0
- package/lib/cli/index.mjs +64 -0
- package/lib/cli/index.spec.d.mts +1 -0
- package/lib/cli/index.spec.mjs +48 -0
- package/lib/cli/init/index.d.mts +1 -0
- package/lib/cli/init/index.mjs +266 -0
- package/lib/cli/init/install-module.d.mts +5 -0
- package/lib/cli/init/install-module.d.ts +2 -2
- package/lib/cli/init/install-module.mjs +61 -0
- package/lib/cli/output.d.mts +3 -0
- package/lib/cli/output.mjs +31 -0
- package/lib/cli/prompt.d.mts +18 -0
- package/lib/cli/prompt.d.ts +12 -17
- package/lib/cli/prompt.mjs +68 -0
- package/lib/debug.d.mts +3 -0
- package/lib/debug.mjs +10 -0
- package/lib/global-settings.d.mts +5 -0
- package/lib/global-settings.d.ts +1 -1
- package/lib/global-settings.mjs +10 -0
- package/lib/i18n.d.mts +6 -0
- package/lib/i18n.d.ts +4 -4
- package/lib/i18n.mjs +19 -0
- package/lib/index.d.mts +8 -0
- package/lib/index.mjs +8 -0
- package/lib/reporter/index.d.mts +2 -0
- package/lib/reporter/index.mjs +2 -0
- package/lib/reporter/simple-reporter.d.mts +3 -0
- package/lib/reporter/simple-reporter.mjs +30 -0
- package/lib/reporter/standard-reporter.d.mts +3 -0
- package/lib/reporter/standard-reporter.mjs +43 -0
- package/lib/testing-tool/index.d.mts +35 -0
- package/lib/testing-tool/index.d.ts +25 -43
- package/lib/testing-tool/index.mjs +83 -0
- package/lib/types.d.mts +27 -0
- package/lib/types.d.ts +17 -17
- package/lib/types.mjs +1 -0
- package/lib/util.d.mts +19 -0
- package/lib/util.d.ts +3 -3
- package/lib/util.mjs +73 -0
- package/lib/v1.d.mts +4 -0
- package/lib/v1.mjs +4 -0
- package/package.json +4 -4
- package/lib/cli/head.d.ts +0 -1
- package/lib/cli/head.js +0 -31
- package/lib/reporter/utils.d.ts +0 -6
- package/lib/reporter/utils.js +0 -40
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import util from 'util';
|
|
4
|
+
import { mergeConfig } from '@markuplint/ml-config';
|
|
5
|
+
import { head, write, error } from '../../util.mjs';
|
|
6
|
+
import { confirm, confirmSequence, multiSelect } from '../prompt.mjs';
|
|
7
|
+
import { installModule } from './install-module.mjs';
|
|
8
|
+
const writeFile = util.promisify(fs.writeFile);
|
|
9
|
+
const ruleCategories = {
|
|
10
|
+
validation: {
|
|
11
|
+
message: 'Are you going to conformance check according to HTML standard?',
|
|
12
|
+
},
|
|
13
|
+
a11y: {
|
|
14
|
+
message: 'Are you going to do with accessibility better practices?',
|
|
15
|
+
},
|
|
16
|
+
'naming-convention': {
|
|
17
|
+
message: 'Are you going to set the convention about naming?',
|
|
18
|
+
},
|
|
19
|
+
style: {
|
|
20
|
+
message: 'Are you going to check for the code styles?',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
const defaultRules = {
|
|
24
|
+
'attr-duplication': {
|
|
25
|
+
category: 'validation',
|
|
26
|
+
default: true,
|
|
27
|
+
},
|
|
28
|
+
'attr-equal-space-after': {
|
|
29
|
+
category: 'style',
|
|
30
|
+
default: true,
|
|
31
|
+
},
|
|
32
|
+
'attr-equal-space-before': {
|
|
33
|
+
category: 'style',
|
|
34
|
+
default: true,
|
|
35
|
+
},
|
|
36
|
+
'attr-spacing': {
|
|
37
|
+
category: 'style',
|
|
38
|
+
default: true,
|
|
39
|
+
},
|
|
40
|
+
'attr-value-quotes': {
|
|
41
|
+
category: 'style',
|
|
42
|
+
default: true,
|
|
43
|
+
},
|
|
44
|
+
'case-sensitive-attr-name': {
|
|
45
|
+
category: 'style',
|
|
46
|
+
default: true,
|
|
47
|
+
},
|
|
48
|
+
'case-sensitive-attr-value': {
|
|
49
|
+
category: 'style',
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
'case-sensitive-tag-name': {
|
|
53
|
+
category: 'style',
|
|
54
|
+
default: true,
|
|
55
|
+
},
|
|
56
|
+
'character-reference': {
|
|
57
|
+
category: 'validation',
|
|
58
|
+
default: true,
|
|
59
|
+
},
|
|
60
|
+
'class-naming': {
|
|
61
|
+
category: 'naming-convention',
|
|
62
|
+
default: false,
|
|
63
|
+
recommendedValue: '/.+/',
|
|
64
|
+
},
|
|
65
|
+
'deprecated-attr': {
|
|
66
|
+
category: 'validation',
|
|
67
|
+
default: true,
|
|
68
|
+
},
|
|
69
|
+
'deprecated-element': {
|
|
70
|
+
category: 'validation',
|
|
71
|
+
default: true,
|
|
72
|
+
},
|
|
73
|
+
'disallowed-element': {
|
|
74
|
+
category: 'validation',
|
|
75
|
+
default: false,
|
|
76
|
+
},
|
|
77
|
+
doctype: {
|
|
78
|
+
category: 'validation',
|
|
79
|
+
default: true,
|
|
80
|
+
},
|
|
81
|
+
'end-tag': {
|
|
82
|
+
category: 'style',
|
|
83
|
+
default: true,
|
|
84
|
+
},
|
|
85
|
+
'id-duplication': {
|
|
86
|
+
category: 'validation',
|
|
87
|
+
default: true,
|
|
88
|
+
},
|
|
89
|
+
indentation: {
|
|
90
|
+
category: 'style',
|
|
91
|
+
default: false,
|
|
92
|
+
recommendedValue: 2,
|
|
93
|
+
},
|
|
94
|
+
'ineffective-attr': {
|
|
95
|
+
category: 'validation',
|
|
96
|
+
default: true,
|
|
97
|
+
},
|
|
98
|
+
'invalid-attr': {
|
|
99
|
+
category: 'validation',
|
|
100
|
+
default: true,
|
|
101
|
+
},
|
|
102
|
+
'landmark-roles': {
|
|
103
|
+
category: 'a11y',
|
|
104
|
+
default: true,
|
|
105
|
+
},
|
|
106
|
+
'no-boolean-attr-value': {
|
|
107
|
+
category: 'style',
|
|
108
|
+
default: true,
|
|
109
|
+
},
|
|
110
|
+
'no-default-value': {
|
|
111
|
+
category: 'style',
|
|
112
|
+
default: true,
|
|
113
|
+
},
|
|
114
|
+
'no-hard-code-id': {
|
|
115
|
+
category: 'style',
|
|
116
|
+
default: true,
|
|
117
|
+
},
|
|
118
|
+
'no-refer-to-non-existent-id': {
|
|
119
|
+
category: 'a11y',
|
|
120
|
+
default: true,
|
|
121
|
+
},
|
|
122
|
+
'no-use-event-handler-attr': {
|
|
123
|
+
category: 'style',
|
|
124
|
+
default: true,
|
|
125
|
+
},
|
|
126
|
+
'permitted-contents': {
|
|
127
|
+
category: 'validation',
|
|
128
|
+
default: true,
|
|
129
|
+
},
|
|
130
|
+
'required-attr': {
|
|
131
|
+
category: 'validation',
|
|
132
|
+
default: true,
|
|
133
|
+
},
|
|
134
|
+
'required-element': {
|
|
135
|
+
category: 'validation',
|
|
136
|
+
default: true,
|
|
137
|
+
},
|
|
138
|
+
'required-h1': {
|
|
139
|
+
category: 'a11y',
|
|
140
|
+
default: true,
|
|
141
|
+
},
|
|
142
|
+
'wai-aria': {
|
|
143
|
+
category: 'a11y',
|
|
144
|
+
default: true,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
const extRExp = {
|
|
148
|
+
jsx: '\\.[jt]sx?$',
|
|
149
|
+
vue: '\\.vue$',
|
|
150
|
+
svelte: '\\.svelte$',
|
|
151
|
+
astro: '\\.astro',
|
|
152
|
+
pug: '\\.pug$',
|
|
153
|
+
php: '\\.php$',
|
|
154
|
+
erb: '\\.erb$',
|
|
155
|
+
ejs: '\\.ejs$',
|
|
156
|
+
mustache: '\\.(mustache|handlebars)$',
|
|
157
|
+
nunjucks: '\\.nunjucks$',
|
|
158
|
+
liquid: '\\.liquid$',
|
|
159
|
+
};
|
|
160
|
+
export async function initialize() {
|
|
161
|
+
let config = {};
|
|
162
|
+
write(head('Initialization'));
|
|
163
|
+
write.break();
|
|
164
|
+
const langs = await multiSelect({
|
|
165
|
+
message: 'Which do you use template engines?',
|
|
166
|
+
choices: [
|
|
167
|
+
{ name: 'React (JSX)', value: 'jsx' },
|
|
168
|
+
{ name: 'Vue', value: 'vue' },
|
|
169
|
+
{ name: 'Svelte', value: 'svelte' },
|
|
170
|
+
{ name: 'Astro', value: 'astro' },
|
|
171
|
+
{ name: 'Pug', value: 'pug' },
|
|
172
|
+
{ name: 'PHP', value: 'php' },
|
|
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
|
+
],
|
|
179
|
+
});
|
|
180
|
+
const autoInstall = await confirm('May I install them automatically?');
|
|
181
|
+
const customize = await confirm('Do you customize rules?');
|
|
182
|
+
for (const lang of langs) {
|
|
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 = mergeConfig(config, {
|
|
192
|
+
specs: {
|
|
193
|
+
'\\.vue$': '@markuplint/vue-spec',
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
if (lang === 'jsx') {
|
|
198
|
+
config = mergeConfig(config, {
|
|
199
|
+
specs: {
|
|
200
|
+
'\\.[jt]sx?$': '@markuplint/react-spec',
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (customize) {
|
|
206
|
+
const ruleNames = Object.keys(defaultRules);
|
|
207
|
+
const categories = Object.keys(ruleCategories);
|
|
208
|
+
const res = await confirmSequence(categories.map(catName => {
|
|
209
|
+
const cat = ruleCategories[catName];
|
|
210
|
+
return {
|
|
211
|
+
message: cat.message,
|
|
212
|
+
name: catName,
|
|
213
|
+
};
|
|
214
|
+
}));
|
|
215
|
+
for (const ruleName of ruleNames) {
|
|
216
|
+
const rule = defaultRules[ruleName];
|
|
217
|
+
if (!rule) {
|
|
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
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const recommended = await confirm('Does it import the recommended config?');
|
|
230
|
+
if (recommended) {
|
|
231
|
+
config.extends = [...(config.extends || []), 'markuplint:recommended'];
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
config.rules = {};
|
|
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
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const filePath = path.resolve(process.cwd(), '.markuplintrc');
|
|
243
|
+
await writeFile(filePath, JSON.stringify(config, null, 2), { encoding: 'utf-8' });
|
|
244
|
+
write(`✨Created: ${filePath}`);
|
|
245
|
+
if (autoInstall) {
|
|
246
|
+
write('Install automatically');
|
|
247
|
+
const modules = ['markuplint', ...langs.map(lang => `@markuplint/${lang}-parser`)];
|
|
248
|
+
if (langs.includes('vue')) {
|
|
249
|
+
modules.push('@markuplint/vue-spec');
|
|
250
|
+
}
|
|
251
|
+
if (langs.includes('jsx')) {
|
|
252
|
+
modules.push('@markuplint/react-spec');
|
|
253
|
+
}
|
|
254
|
+
const result = await installModule(modules, true).catch(e => new Error(e));
|
|
255
|
+
if (result instanceof Error) {
|
|
256
|
+
error.exit();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (result.alreadyExists) {
|
|
260
|
+
write('Modules are installed already.');
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
write('✨ Success');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
import c from 'cli-color';
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import detectInstalled from 'detect-installed';
|
|
5
|
+
import hasYarn from 'has-yarn';
|
|
6
|
+
export async function installModule(module, dev = false) {
|
|
7
|
+
module = module.map(m => m.trim());
|
|
8
|
+
const uninstallMods = [];
|
|
9
|
+
try {
|
|
10
|
+
for (const mod of module) {
|
|
11
|
+
const installed = await isInstalled(mod);
|
|
12
|
+
if (!installed) {
|
|
13
|
+
uninstallMods.push(mod);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (_) {
|
|
18
|
+
// void
|
|
19
|
+
}
|
|
20
|
+
if (!uninstallMods.length) {
|
|
21
|
+
return {
|
|
22
|
+
success: true,
|
|
23
|
+
alreadyExists: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const mod = hasYarn() ? 'yarn' : 'npm';
|
|
27
|
+
const installOpt = hasYarn() ? 'add' : 'install';
|
|
28
|
+
const opt = [installOpt];
|
|
29
|
+
if (dev) {
|
|
30
|
+
opt.push('-D');
|
|
31
|
+
}
|
|
32
|
+
opt.push(...uninstallMods);
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
process.stdout.write(c.blackBright(`${mod} ${opt.join(' ')}\n`));
|
|
35
|
+
const result = spawnSync(mod, opt, { stdio: 'inherit' });
|
|
36
|
+
if (result.error || result.status !== 0) {
|
|
37
|
+
const message = 'Error running command.';
|
|
38
|
+
const error = new Error(message);
|
|
39
|
+
error.stack = message;
|
|
40
|
+
reject(error);
|
|
41
|
+
}
|
|
42
|
+
resolve({
|
|
43
|
+
success: true,
|
|
44
|
+
alreadyExists: false,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async function isInstalled(module) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
try {
|
|
51
|
+
detectInstalled(module, {
|
|
52
|
+
local: true,
|
|
53
|
+
}).then((exists) => {
|
|
54
|
+
resolve(exists);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
reject(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import stripAnsi from 'strip-ansi';
|
|
2
|
+
import { simpleReporter, standardReporter } from '../reporter/index.mjs';
|
|
3
|
+
export async function output(results, options) {
|
|
4
|
+
const format = options.format ?? 'Standard';
|
|
5
|
+
let out;
|
|
6
|
+
switch (format.toLowerCase()) {
|
|
7
|
+
case 'json': {
|
|
8
|
+
process.stdout.write(JSON.stringify(results.violations, null, 2));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
case 'simple': {
|
|
12
|
+
out = simpleReporter(results, options);
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
default: {
|
|
16
|
+
out = standardReporter(results, options);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!out.length) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let msg = `${out.join('\n')}\n`;
|
|
23
|
+
msg = options.color ? msg : stripAnsi(msg);
|
|
24
|
+
// If it has errors, Write to `stderr` and failure and exit.
|
|
25
|
+
if (results.violations.length) {
|
|
26
|
+
process.stderr.write(msg);
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
process.stdout.write(msg);
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare type SelectQuestion<T> = {
|
|
2
|
+
message: string;
|
|
3
|
+
choices: {
|
|
4
|
+
name: string;
|
|
5
|
+
value: T;
|
|
6
|
+
}[];
|
|
7
|
+
};
|
|
8
|
+
export declare function select<T>(question: SelectQuestion<T>): Promise<T>;
|
|
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>;
|
|
11
|
+
export declare function confirm(question: string, options?: {
|
|
12
|
+
initial?: boolean;
|
|
13
|
+
}): Promise<boolean>;
|
|
14
|
+
export declare function confirmSequence<T extends string = string>(questions: {
|
|
15
|
+
message: string;
|
|
16
|
+
name: T;
|
|
17
|
+
}[]): Promise<Record<T, boolean>>;
|
|
18
|
+
export {};
|
package/lib/cli/prompt.d.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
declare type SelectQuestion<T> = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
message: string;
|
|
3
|
+
choices: {
|
|
4
|
+
name: string;
|
|
5
|
+
value: T;
|
|
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
10
|
export declare function input<T extends string = string>(question: string, validation?: RegExp): Promise<T>;
|
|
11
|
-
export declare function confirm(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
questions: {
|
|
19
|
-
message: string;
|
|
20
|
-
name: T;
|
|
21
|
-
}[],
|
|
22
|
-
): Promise<Record<T, boolean>>;
|
|
11
|
+
export declare function confirm(question: string, options?: {
|
|
12
|
+
initial?: boolean;
|
|
13
|
+
}): Promise<boolean>;
|
|
14
|
+
export declare function confirmSequence<T extends string = string>(questions: {
|
|
15
|
+
message: string;
|
|
16
|
+
name: T;
|
|
17
|
+
}[]): Promise<Record<T, boolean>>;
|
|
23
18
|
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import c from 'cli-color';
|
|
2
|
+
import enquirer from 'enquirer';
|
|
3
|
+
const { prompt } = enquirer;
|
|
4
|
+
export async function select(question) {
|
|
5
|
+
const res = await prompt({
|
|
6
|
+
...question,
|
|
7
|
+
name: '__Q__',
|
|
8
|
+
type: 'select',
|
|
9
|
+
result(resName) {
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
return this.options.choices.find(c => c.name === resName)?.value;
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
return res['__Q__'];
|
|
16
|
+
}
|
|
17
|
+
export async function multiSelect(question) {
|
|
18
|
+
const res = await prompt({
|
|
19
|
+
...question,
|
|
20
|
+
name: '__Q__',
|
|
21
|
+
type: 'multiselect',
|
|
22
|
+
result(names) {
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
const map = this.map(names);
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
const values = names.map(name => map[name]);
|
|
27
|
+
return values;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
return res['__Q__'];
|
|
32
|
+
}
|
|
33
|
+
export async function input(question, validation) {
|
|
34
|
+
// eslint-disable-next-line no-constant-condition
|
|
35
|
+
while (true) {
|
|
36
|
+
const _res = await prompt({
|
|
37
|
+
message: question,
|
|
38
|
+
name: '__Q__',
|
|
39
|
+
type: 'input',
|
|
40
|
+
});
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
const res = _res['__Q__'];
|
|
43
|
+
if (validation && !validation.test(res)) {
|
|
44
|
+
process.stdout.write(c.yellow('Oops! The name that you type is an invalid format.\n'));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
return res;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function confirm(question, options) {
|
|
51
|
+
const res = await prompt({
|
|
52
|
+
message: question,
|
|
53
|
+
name: '__Q__',
|
|
54
|
+
type: 'confirm',
|
|
55
|
+
initial: !!options?.initial,
|
|
56
|
+
});
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
return !!res['__Q__'];
|
|
59
|
+
}
|
|
60
|
+
export async function confirmSequence(questions) {
|
|
61
|
+
const res = await prompt(questions.map(question => {
|
|
62
|
+
return {
|
|
63
|
+
...question,
|
|
64
|
+
type: 'confirm',
|
|
65
|
+
};
|
|
66
|
+
}));
|
|
67
|
+
return res;
|
|
68
|
+
}
|
package/lib/debug.d.mts
ADDED
package/lib/debug.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { enableDebug } from '@markuplint/ml-core';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
export const log = debug('markuplint-cli');
|
|
4
|
+
export function verbosely() {
|
|
5
|
+
if (!log.enabled) {
|
|
6
|
+
debug.enable(`${log.namespace}*`);
|
|
7
|
+
log(`Debug enable: ${log.namespace}`);
|
|
8
|
+
}
|
|
9
|
+
enableDebug();
|
|
10
|
+
}
|
package/lib/global-settings.d.ts
CHANGED
package/lib/i18n.d.mts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function i18n(locale?: string): Promise<{
|
|
2
|
+
locale: string;
|
|
3
|
+
listFormat?: import("packages/@markuplint/i18n/src/types.js").ListFormat | undefined;
|
|
4
|
+
keywords?: import("packages/@markuplint/i18n/src/types.js").LocalesKeywords | undefined;
|
|
5
|
+
sentences?: import("packages/@markuplint/i18n/src/types.js").LocalesKeywords | undefined;
|
|
6
|
+
}>;
|
package/lib/i18n.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare function i18n(locale?: string): Promise<{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
locale: string;
|
|
3
|
+
listFormat?: import("packages/@markuplint/i18n/src/types").ListFormat | undefined;
|
|
4
|
+
keywords?: import("packages/@markuplint/i18n/src/types").LocalesKeywords | undefined;
|
|
5
|
+
sentences?: import("packages/@markuplint/i18n/src/types").LocalesKeywords | undefined;
|
|
6
6
|
}>;
|
package/lib/i18n.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { osLocale } from 'os-locale';
|
|
2
|
+
let cachedLocale = null;
|
|
3
|
+
async function getLocale() {
|
|
4
|
+
if (!cachedLocale) {
|
|
5
|
+
cachedLocale = await osLocale({ spawn: true });
|
|
6
|
+
}
|
|
7
|
+
return cachedLocale;
|
|
8
|
+
}
|
|
9
|
+
export async function i18n(locale) {
|
|
10
|
+
locale = locale || (await getLocale()) || 'en';
|
|
11
|
+
const langCode = locale.split('-')[0];
|
|
12
|
+
const localeSet = langCode
|
|
13
|
+
? await import(`@markuplint/i18n/locales/${langCode}`).catch(() => null)
|
|
14
|
+
: null;
|
|
15
|
+
return {
|
|
16
|
+
locale: langCode,
|
|
17
|
+
...localeSet,
|
|
18
|
+
};
|
|
19
|
+
}
|
package/lib/index.d.mts
ADDED
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import c from 'cli-color';
|
|
2
|
+
import { markuplint, messageToString, p, w } from '../util.mjs';
|
|
3
|
+
const loggerError = c.red;
|
|
4
|
+
const loggerWarning = c.xterm(208);
|
|
5
|
+
export function simpleReporter(results, options) {
|
|
6
|
+
const sizes = {
|
|
7
|
+
line: 0,
|
|
8
|
+
col: 0,
|
|
9
|
+
meg: 0,
|
|
10
|
+
};
|
|
11
|
+
for (const violation of results.violations) {
|
|
12
|
+
sizes.line = Math.max(sizes.line, violation.line.toString(10).length);
|
|
13
|
+
sizes.col = Math.max(sizes.col, violation.col.toString(10).length);
|
|
14
|
+
const meg = messageToString(violation.message, violation.reason);
|
|
15
|
+
sizes.meg = Math.max(sizes.meg, w(meg));
|
|
16
|
+
}
|
|
17
|
+
const out = [];
|
|
18
|
+
if (results.violations.length) {
|
|
19
|
+
out.push(`<${markuplint}> ${c.underline(results.filePath)}: ${loggerError('✗')}`);
|
|
20
|
+
for (const violation of results.violations) {
|
|
21
|
+
const s = violation.severity === 'error' ? loggerError('✖') : loggerWarning('⚠️');
|
|
22
|
+
const meg = messageToString(violation.message, violation.reason);
|
|
23
|
+
out.push(` ${c.cyan(`${p(violation.line, sizes.line, true)}:${p(violation.col, sizes.col)}`)} ${s} ${p(meg, sizes.meg)} ${c.xterm(8)(violation.ruleId)} `);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (!options.problemOnly) {
|
|
27
|
+
out.push(`<${markuplint}> ${c.underline(results.filePath)}: ${c.green('✓')}`);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|