markuplint 4.0.0-dev.10 → 4.0.0-dev.12
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/README.md +2 -1
- package/lib/api/ml-engine.js +1 -1
- package/lib/cli/bootstrap.d.ts +1 -1
- package/lib/cli/bootstrap.js +0 -1
- package/lib/cli/command.js +8 -11
- package/lib/cli/init/create-config.js +11 -1
- package/lib/cli/init/get-default-rules.d.ts +2 -2
- package/lib/cli/init/get-default-rules.js +12 -48
- package/lib/cli/init/index.js +1 -4
- package/lib/cli/init/types.d.ts +3 -2
- package/package.json +15 -17
- package/lib/cli/create-rule/index.d.ts +0 -1
- package/lib/cli/create-rule/index.js +0 -79
- package/lib/cli/init/install-module.d.ts +0 -7
- package/lib/cli/init/install-module.js +0 -74
- package/lib/cli/prompt.d.ts +0 -18
- package/lib/cli/prompt.js +0 -67
- package/lib/util.d.ts +0 -17
- package/lib/util.js +0 -77
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -86,7 +86,6 @@ Options
|
|
|
86
86
|
--include-node-modules Include files in node_modules directory. Default: false.
|
|
87
87
|
|
|
88
88
|
--init Initialize settings interactively.
|
|
89
|
-
--create-rule Add the scaffold of a custom rule.
|
|
90
89
|
|
|
91
90
|
--help, -h Show help.
|
|
92
91
|
--version, -v Show version.
|
|
@@ -126,6 +125,8 @@ Need [Sponsors❤️🔥](https://github.com/sponsors/markuplint)
|
|
|
126
125
|
[<img width="36" src="https://avatars.githubusercontent.com/u/6581173" alt="miita" />](https://github.com/mikimhk)
|
|
127
126
|
[<img width="36" src="https://avatars.githubusercontent.com/u/111797" alt="Yasuo Fukuda" />](https://github.com/sigwyg)
|
|
128
127
|
[<img width="36" src="https://avatars.githubusercontent.com/u/802921" alt="Hideyuki Saito" />](https://github.com/hideyukisaito)
|
|
128
|
+
[<img width="36" src="https://avatars.githubusercontent.com/u/3056064" alt="tamshow" />](https://github.com/tamshow)
|
|
129
|
+
[<img width="36" src="https://avatars.githubusercontent.com/u/91047157" alt="shamokit" />](https://github.com/shamokit)
|
|
129
130
|
|
|
130
131
|
## Thanks
|
|
131
132
|
|
package/lib/api/ml-engine.js
CHANGED
|
@@ -81,7 +81,7 @@ export class MLEngine extends Emitter {
|
|
|
81
81
|
throw error;
|
|
82
82
|
});
|
|
83
83
|
const sourceCode = await __classPrivateFieldGet(this, _MLEngine_file, "f").getCode();
|
|
84
|
-
const fixedCode = core.document.toString();
|
|
84
|
+
const fixedCode = core.document.toString(true);
|
|
85
85
|
if (violations instanceof Error) {
|
|
86
86
|
this.emit('lint-error', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode, violations);
|
|
87
87
|
const errMessage = violations.stack ?? violations.message;
|
package/lib/cli/bootstrap.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReadonlyDeep } from 'type-fest';
|
|
2
|
-
export declare const help = "\nUsage\n\t$ markuplint <HTML file paths (glob format)>\n\t$ <stdout> | markuplint\n\nOptions\n\t--config, -c FILE_PATH A configuration file path.\n\t--fix, Fix HTML.\n\t--format, -f FORMAT Output format. Support \"JSON\", \"Simple\", \"GitHub\" and \"Standard\". Default: \"Standard\".\n\t--no-search-config No search a configure file automatically.\n\t--ignore-ext Evaluate files that are received even though the type of extension.\n\t--no-import-preset-rules No import preset rules.\n\t--locale Locale of the message of violation. Default is an OS setting.\n\t--no-color, Output no color.\n\t--problem-only, -p Output only problems, without passeds.\n\t--allow-warnings Return status code 0 even if there are warnings.\n\t--allow-empty-input Return status code 1 even if there are no input files.\n\t--verbose Output with detailed information.\n\t--include-node-modules Include files in node_modules directory. Default: false.\n\n\t--init Initialize settings interactively.\n\t--
|
|
2
|
+
export declare const help = "\nUsage\n\t$ markuplint <HTML file paths (glob format)>\n\t$ <stdout> | markuplint\n\nOptions\n\t--config, -c FILE_PATH A configuration file path.\n\t--fix, Fix HTML.\n\t--format, -f FORMAT Output format. Support \"JSON\", \"Simple\", \"GitHub\" and \"Standard\". Default: \"Standard\".\n\t--no-search-config No search a configure file automatically.\n\t--ignore-ext Evaluate files that are received even though the type of extension.\n\t--no-import-preset-rules No import preset rules.\n\t--locale Locale of the message of violation. Default is an OS setting.\n\t--no-color, Output no color.\n\t--problem-only, -p Output only problems, without passeds.\n\t--allow-warnings Return status code 0 even if there are warnings.\n\t--allow-empty-input Return status code 1 even if there are no input files.\n\t--verbose Output with detailed information.\n\t--include-node-modules Include files in node_modules directory. Default: false.\n\n\t--init Initialize settings interactively.\n\t--search Search lines of codes that include the target element by selectors.\n\n\t--help, -h Show help.\n\t--version, -v Show version.\n\nExamples\n\t$ markuplint verifyee.html --config path/to/.markuplintrc\n\t$ cat verifyee.html | markuplint\n";
|
|
3
3
|
export declare const cli: import("meow").Result<{
|
|
4
4
|
config: {
|
|
5
5
|
type: "string";
|
package/lib/cli/bootstrap.js
CHANGED
|
@@ -20,7 +20,6 @@ Options
|
|
|
20
20
|
--include-node-modules Include files in node_modules directory. Default: false.
|
|
21
21
|
|
|
22
22
|
--init Initialize settings interactively.
|
|
23
|
-
--create-rule Add the scaffold of a custom rule.
|
|
24
23
|
--search Search lines of codes that include the target element by selectors.
|
|
25
24
|
|
|
26
25
|
--help, -h Show help.
|
package/lib/cli/command.js
CHANGED
|
@@ -50,19 +50,16 @@ export async function command(files, options, apiOptions) {
|
|
|
50
50
|
if (fix) {
|
|
51
51
|
log('Overwrite file: %s', result.filePath);
|
|
52
52
|
await fs.writeFile(result.filePath, result.fixedCode, { encoding: 'utf8' });
|
|
53
|
-
process.stdout.write(`markuplint: Fix "${result.filePath}"\n`);
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
log('Output reports');
|
|
64
|
-
output(result, options);
|
|
54
|
+
if (format === 'json') {
|
|
55
|
+
jsonOutput.push(...result.violations.map(v => ({
|
|
56
|
+
...v,
|
|
57
|
+
filePath: result.filePath,
|
|
58
|
+
})));
|
|
59
|
+
continue;
|
|
65
60
|
}
|
|
61
|
+
log('Output reports');
|
|
62
|
+
output(result, options);
|
|
66
63
|
}
|
|
67
64
|
if (format === 'json') {
|
|
68
65
|
process.stdout.write(JSON.stringify(jsonOutput, null, 2) + '\n');
|
|
@@ -2,6 +2,7 @@ const extRExp = {
|
|
|
2
2
|
jsx: '\\.[jt]sx?$',
|
|
3
3
|
vue: '\\.vue$',
|
|
4
4
|
svelte: '\\.svelte$',
|
|
5
|
+
sveltekit: '\\.html$',
|
|
5
6
|
astro: '\\.astro$',
|
|
6
7
|
pug: '\\.pug$',
|
|
7
8
|
php: '\\.php$',
|
|
@@ -16,6 +17,7 @@ export const langs = {
|
|
|
16
17
|
jsx: 'React (JSX)',
|
|
17
18
|
vue: 'Vue',
|
|
18
19
|
svelte: 'Svelte',
|
|
20
|
+
sveltekit: 'SvelteKit',
|
|
19
21
|
astro: 'Astro',
|
|
20
22
|
pug: 'Pug',
|
|
21
23
|
php: 'PHP',
|
|
@@ -34,7 +36,15 @@ export function createConfig(langs, mode, defaultRules) {
|
|
|
34
36
|
if (!ext) {
|
|
35
37
|
continue;
|
|
36
38
|
}
|
|
37
|
-
|
|
39
|
+
switch (lang) {
|
|
40
|
+
case 'sveltekit': {
|
|
41
|
+
parser[ext] = '@markuplint/svelte-parser/kit';
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
default: {
|
|
45
|
+
parser[ext] = `@markuplint/${lang}-parser`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
38
48
|
if (lang === 'vue') {
|
|
39
49
|
config = {
|
|
40
50
|
...config,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare function getDefaultRules(
|
|
1
|
+
export declare function getDefaultRules(): {
|
|
2
2
|
[x: string]: import("./types.js").Rule;
|
|
3
|
-
}
|
|
3
|
+
};
|
|
@@ -1,52 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
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);
|
|
1
|
+
import builtinRules from '@markuplint/rules';
|
|
2
|
+
export function getDefaultRules() {
|
|
7
3
|
const rules = {};
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
for (const [ruleName, rule] of Object.entries(builtinRules)) {
|
|
5
|
+
const defaultSeverity = rule.defaultSeverity;
|
|
6
|
+
const defaultValue = defaultSeverity === 'warning' ? false : rule.defaultValue ?? true;
|
|
7
|
+
const category = rule.meta?.category;
|
|
8
|
+
if (category) {
|
|
9
|
+
rules[ruleName] = {
|
|
10
|
+
defaultValue,
|
|
11
|
+
category,
|
|
12
|
+
};
|
|
17
13
|
}
|
|
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
14
|
}
|
|
35
|
-
|
|
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
|
-
};
|
|
15
|
+
return rules;
|
|
52
16
|
}
|
package/lib/cli/init/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
-
import module from 'node:module';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { installModule, multiSelect, confirm, confirmSequence, header } from '@markuplint/cli-utils';
|
|
5
4
|
import { createConfig, langs } from './create-config.js';
|
|
6
5
|
import { getDefaultRules } from './get-default-rules.js';
|
|
7
6
|
import { selectModules } from './select-modules.js';
|
|
8
|
-
const require = module.createRequire(import.meta.url);
|
|
9
7
|
const ruleCategories = {
|
|
10
8
|
validation: {
|
|
11
9
|
message: 'Are you going to conformance check according to HTML standard?',
|
|
@@ -52,8 +50,7 @@ export async function initialize() {
|
|
|
52
50
|
}
|
|
53
51
|
let defaultRules = {};
|
|
54
52
|
if (ruleSettingMode !== 'recommended') {
|
|
55
|
-
|
|
56
|
-
defaultRules = await getDefaultRules(rulesVersion);
|
|
53
|
+
defaultRules = getDefaultRules();
|
|
57
54
|
}
|
|
58
55
|
const config = createConfig(selectedLangs, ruleSettingMode, defaultRules);
|
|
59
56
|
const filePath = path.resolve(process.cwd(), '.markuplintrc');
|
package/lib/cli/init/types.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RuleConfigValue } from '@markuplint/ml-config';
|
|
2
|
+
export type Langs = 'jsx' | 'vue' | 'svelte' | 'sveltekit' | 'astro' | 'pug' | 'php' | 'smarty' | 'erb' | 'ejs' | 'mustache' | 'nunjucks' | 'liquid';
|
|
2
3
|
export type Category = 'validation' | 'a11y' | 'naming-convention' | 'style' | 'maintainability';
|
|
3
4
|
export type RuleSettingMode = readonly Category[] | 'recommended' | 'none';
|
|
4
5
|
export type DefaultRules = Readonly<Record<string, Rule>>;
|
|
5
6
|
export type Rule = {
|
|
6
7
|
readonly category: Category;
|
|
7
|
-
readonly defaultValue:
|
|
8
|
+
readonly defaultValue: RuleConfigValue;
|
|
8
9
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markuplint",
|
|
3
|
-
"version": "4.0.0-dev.
|
|
3
|
+
"version": "4.0.0-dev.12+2275fbeb0",
|
|
4
4
|
"description": "An HTML linter for all markup developers",
|
|
5
5
|
"author": "Yusuke Hirao",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,28 +25,26 @@
|
|
|
25
25
|
"clean": "tsc --build --clean"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@markuplint/cli-utils": "4.0.0-dev.
|
|
29
|
-
"@markuplint/file-resolver": "4.0.0-dev.
|
|
30
|
-
"@markuplint/html-parser": "4.0.0-dev.
|
|
31
|
-
"@markuplint/html-spec": "4.0.0-dev.
|
|
32
|
-
"@markuplint/i18n": "4.0.0-dev.
|
|
33
|
-
"@markuplint/ml-ast": "4.0.0-dev.
|
|
34
|
-
"@markuplint/ml-config": "4.0.0-dev.
|
|
35
|
-
"@markuplint/ml-core": "4.0.0-dev.
|
|
36
|
-
"@markuplint/ml-spec": "4.0.0-dev.
|
|
37
|
-
"@markuplint/rules": "4.0.0-dev.
|
|
38
|
-
"@markuplint/shared": "4.0.0-dev.
|
|
28
|
+
"@markuplint/cli-utils": "4.0.0-dev.12+2275fbeb0",
|
|
29
|
+
"@markuplint/file-resolver": "4.0.0-dev.12+2275fbeb0",
|
|
30
|
+
"@markuplint/html-parser": "4.0.0-dev.12+2275fbeb0",
|
|
31
|
+
"@markuplint/html-spec": "4.0.0-dev.12+2275fbeb0",
|
|
32
|
+
"@markuplint/i18n": "4.0.0-dev.12+2275fbeb0",
|
|
33
|
+
"@markuplint/ml-ast": "4.0.0-dev.12+2275fbeb0",
|
|
34
|
+
"@markuplint/ml-config": "4.0.0-dev.12+2275fbeb0",
|
|
35
|
+
"@markuplint/ml-core": "4.0.0-dev.12+2275fbeb0",
|
|
36
|
+
"@markuplint/ml-spec": "4.0.0-dev.12+2275fbeb0",
|
|
37
|
+
"@markuplint/rules": "4.0.0-dev.12+2275fbeb0",
|
|
38
|
+
"@markuplint/shared": "4.0.0-dev.12+2275fbeb0",
|
|
39
39
|
"@types/debug": "^4.1.12",
|
|
40
40
|
"chokidar": "^3.5.3",
|
|
41
41
|
"debug": "^4.3.4",
|
|
42
42
|
"get-stdin": "^9.0.0",
|
|
43
|
-
"
|
|
44
|
-
"meow": "^12.1.1",
|
|
45
|
-
"node-fetch": "^3.3.2",
|
|
43
|
+
"meow": "^13.1.0",
|
|
46
44
|
"os-locale": "^6.0.2",
|
|
47
45
|
"strict-event-emitter": "^0.5.1",
|
|
48
46
|
"strip-ansi": "^7.1.0",
|
|
49
|
-
"type-fest": "^4.
|
|
47
|
+
"type-fest": "^4.9.0"
|
|
50
48
|
},
|
|
51
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "2275fbeb053605b636f080f4fafd7cd4fc57a9a3"
|
|
52
50
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function createRule(): Promise<void>;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { isMarkuplintRepo, createRuleHelper } from '@markuplint/create-rule-helper';
|
|
3
|
-
import c from 'cli-color';
|
|
4
|
-
import { write, head } from '../../util.js';
|
|
5
|
-
import { installModule } from '../init/install-module.js';
|
|
6
|
-
import { input, select, confirm } from '../prompt.js';
|
|
7
|
-
const icons = {
|
|
8
|
-
README: '📝',
|
|
9
|
-
index: '📜',
|
|
10
|
-
schema: '⚙️ ',
|
|
11
|
-
package: '🎁',
|
|
12
|
-
tsconfig: '💎',
|
|
13
|
-
};
|
|
14
|
-
export async function createRule() {
|
|
15
|
-
write(head('Create a rule'));
|
|
16
|
-
write.break();
|
|
17
|
-
const firstChoices = [
|
|
18
|
-
{ name: 'Add the rule to this project', value: 'ADD_TO_PROJECT' },
|
|
19
|
-
{ name: 'Create the rule and publish it as a package', value: 'PUBLISH_AS_PACKAGE' },
|
|
20
|
-
];
|
|
21
|
-
if (await isMarkuplintRepo()) {
|
|
22
|
-
firstChoices.push({ name: 'Contribute the new rule to markuplint core rules', value: 'CONTRIBUTE_TO_CORE' });
|
|
23
|
-
}
|
|
24
|
-
const purpose = await select({
|
|
25
|
-
message: 'What purpose do you create the rule for?',
|
|
26
|
-
choices: firstChoices,
|
|
27
|
-
});
|
|
28
|
-
const dirQuestion = purpose === 'ADD_TO_PROJECT' ? 'What is the directory name?' : 'What is the plugin name?';
|
|
29
|
-
const pluginName = purpose === 'CONTRIBUTE_TO_CORE' ? '' : await input(dirQuestion, /^[a-z][\da-z]*(?:-[a-z][\da-z]*)*$/i);
|
|
30
|
-
const ruleName = await input('What is the rule name?', /^[a-z][\da-z]*(?:-[a-z][\da-z]*)*$/i);
|
|
31
|
-
const core = purpose === 'CONTRIBUTE_TO_CORE'
|
|
32
|
-
? {
|
|
33
|
-
description: await input('Description:'),
|
|
34
|
-
category: await select({
|
|
35
|
-
message: 'Category:',
|
|
36
|
-
choices: [
|
|
37
|
-
{ name: 'Conformance checking', value: 'validation' },
|
|
38
|
-
{ name: 'Accessibility', value: 'a11y' },
|
|
39
|
-
{ name: 'Naming Convention', value: 'naming-convention' },
|
|
40
|
-
{ name: 'Maintainability', value: 'maintainability' },
|
|
41
|
-
{ name: 'Style', value: 'style' },
|
|
42
|
-
],
|
|
43
|
-
}),
|
|
44
|
-
severity: await select({
|
|
45
|
-
message: 'Severity:',
|
|
46
|
-
choices: [
|
|
47
|
-
{ name: 'error', value: 'error' },
|
|
48
|
-
{ name: 'warning', value: 'warning' },
|
|
49
|
-
],
|
|
50
|
-
}),
|
|
51
|
-
}
|
|
52
|
-
: undefined;
|
|
53
|
-
const lang = purpose === 'CONTRIBUTE_TO_CORE'
|
|
54
|
-
? 'TYPESCRIPT'
|
|
55
|
-
: await select({
|
|
56
|
-
message: 'Which language will you implement?',
|
|
57
|
-
choices: [
|
|
58
|
-
{ name: 'TypeScript', value: 'TYPESCRIPT' },
|
|
59
|
-
{ name: 'JavaScript', value: 'JAVASCRIPT' },
|
|
60
|
-
],
|
|
61
|
-
});
|
|
62
|
-
const needTest = purpose === 'CONTRIBUTE_TO_CORE' ? true : await confirm('Do you need the test?', { initial: true });
|
|
63
|
-
const result = await createRuleHelper({ purpose, pluginName, ruleName, lang, needTest, core });
|
|
64
|
-
for (const file of result.files) {
|
|
65
|
-
output(pluginName || 'core', file.test ? '🖍 ' : icons[file.name] ?? '🛡 ', file.fileName, resolve(file.destDir, file.fileName + file.ext));
|
|
66
|
-
}
|
|
67
|
-
if (result.dependencies.length > 0) {
|
|
68
|
-
await installModule(result.dependencies);
|
|
69
|
-
}
|
|
70
|
-
if (result.devDependencies.length > 0) {
|
|
71
|
-
await installModule(result.devDependencies, true);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function output(name, icon, title, path) {
|
|
75
|
-
const _marker = c.xterm(39)('✔') + ' ';
|
|
76
|
-
const _title = (icon, title) => `${icon} ` + c.bold(`${name}/${title}`);
|
|
77
|
-
const _file = (path) => ' ' + c.cyanBright(path);
|
|
78
|
-
write(_marker + _title(icon, title) + _file(path));
|
|
79
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Langs } from './types.js';
|
|
2
|
-
export type InstallModuleResult = {
|
|
3
|
-
success: boolean;
|
|
4
|
-
alreadyExists: boolean;
|
|
5
|
-
};
|
|
6
|
-
export declare function selectModules(selectedLangs: readonly Langs[]): string[];
|
|
7
|
-
export declare function installModule(module: readonly string[], dev?: boolean): Promise<InstallModuleResult>;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node: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 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) {
|
|
17
|
-
module = module.map(m => m.trim());
|
|
18
|
-
const uninstallMods = [];
|
|
19
|
-
try {
|
|
20
|
-
for (const mod of module) {
|
|
21
|
-
const installed = await isInstalled(mod);
|
|
22
|
-
if (!installed) {
|
|
23
|
-
uninstallMods.push(mod);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
// void
|
|
29
|
-
}
|
|
30
|
-
if (uninstallMods.length === 0) {
|
|
31
|
-
return {
|
|
32
|
-
success: true,
|
|
33
|
-
alreadyExists: true,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
const mod = hasYarn() ? 'yarn' : 'npm';
|
|
37
|
-
const installOpt = hasYarn() ? 'add' : 'install';
|
|
38
|
-
const opt = [installOpt];
|
|
39
|
-
if (dev) {
|
|
40
|
-
opt.push('-D');
|
|
41
|
-
}
|
|
42
|
-
if (!hasYarn()) {
|
|
43
|
-
opt.push('--legacy-peer-deps');
|
|
44
|
-
}
|
|
45
|
-
opt.push(...uninstallMods);
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
process.stdout.write(c.blackBright(`${mod} ${opt.join(' ')}\n`));
|
|
48
|
-
const result = spawnSync(mod, opt, { stdio: 'inherit' });
|
|
49
|
-
if (result.error || result.status !== 0) {
|
|
50
|
-
const message = 'Error running command.';
|
|
51
|
-
const error = new Error(message);
|
|
52
|
-
error.stack = message;
|
|
53
|
-
reject(error);
|
|
54
|
-
}
|
|
55
|
-
resolve({
|
|
56
|
-
success: true,
|
|
57
|
-
alreadyExists: false,
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function isInstalled(module) {
|
|
62
|
-
return new Promise((resolve, reject) => {
|
|
63
|
-
try {
|
|
64
|
-
detectInstalled(module, {
|
|
65
|
-
local: true,
|
|
66
|
-
}).then((exists) => {
|
|
67
|
-
resolve(exists);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
reject(error);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
package/lib/cli/prompt.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
type SelectQuestion<T> = {
|
|
2
|
-
readonly message: string;
|
|
3
|
-
readonly choices: readonly {
|
|
4
|
-
readonly name: string;
|
|
5
|
-
readonly 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?: Readonly<RegExp>): Promise<T>;
|
|
11
|
-
export declare function confirm(question: string, options?: {
|
|
12
|
-
readonly initial?: boolean;
|
|
13
|
-
}): Promise<boolean>;
|
|
14
|
-
export declare function confirmSequence<T extends string = string>(questions: readonly {
|
|
15
|
-
readonly message: string;
|
|
16
|
-
readonly name: T;
|
|
17
|
-
}[]): Promise<Record<T, boolean>>;
|
|
18
|
-
export {};
|
package/lib/cli/prompt.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import c from 'cli-color';
|
|
2
|
-
import Enquirer from 'enquirer';
|
|
3
|
-
export async function select(question) {
|
|
4
|
-
const res = await Enquirer.prompt({
|
|
5
|
-
...question,
|
|
6
|
-
name: '__Q__',
|
|
7
|
-
type: 'select',
|
|
8
|
-
result(resName) {
|
|
9
|
-
// @ts-ignore
|
|
10
|
-
return this.options.choices.find(c => c.name === resName)?.value;
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
return res['__Q__'];
|
|
15
|
-
}
|
|
16
|
-
export async function multiSelect(question) {
|
|
17
|
-
const res = await Enquirer.prompt({
|
|
18
|
-
...question,
|
|
19
|
-
name: '__Q__',
|
|
20
|
-
type: 'multiselect',
|
|
21
|
-
result(names) {
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
const map = this.map(names);
|
|
24
|
-
// @ts-ignore
|
|
25
|
-
const values = names.map(name => map[name]);
|
|
26
|
-
return values;
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
// @ts-ignore
|
|
30
|
-
return res['__Q__'];
|
|
31
|
-
}
|
|
32
|
-
export async function input(question, validation) {
|
|
33
|
-
// eslint-disable-next-line no-constant-condition
|
|
34
|
-
while (true) {
|
|
35
|
-
const _res = await Enquirer.prompt({
|
|
36
|
-
message: question,
|
|
37
|
-
name: '__Q__',
|
|
38
|
-
type: 'input',
|
|
39
|
-
});
|
|
40
|
-
// @ts-ignore
|
|
41
|
-
const res = _res['__Q__'];
|
|
42
|
-
if (validation && !validation.test(res)) {
|
|
43
|
-
process.stdout.write(c.yellow('Oops! The name that you type is an invalid format.\n'));
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
return res;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
export async function confirm(question, options) {
|
|
50
|
-
const res = await Enquirer.prompt({
|
|
51
|
-
message: question,
|
|
52
|
-
name: '__Q__',
|
|
53
|
-
type: 'confirm',
|
|
54
|
-
initial: !!options?.initial,
|
|
55
|
-
});
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
return !!res['__Q__'];
|
|
58
|
-
}
|
|
59
|
-
export async function confirmSequence(questions) {
|
|
60
|
-
const res = await Enquirer.prompt(questions.map(question => {
|
|
61
|
-
return {
|
|
62
|
-
...question,
|
|
63
|
-
type: 'confirm',
|
|
64
|
-
};
|
|
65
|
-
}));
|
|
66
|
-
return res;
|
|
67
|
-
}
|
package/lib/util.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare function uuid(): string;
|
|
2
|
-
export declare const markuplint: string;
|
|
3
|
-
export declare function write(message: string): void;
|
|
4
|
-
export declare namespace write {
|
|
5
|
-
var _a: () => boolean;
|
|
6
|
-
export { _a as break };
|
|
7
|
-
}
|
|
8
|
-
export declare function error(message: string): void;
|
|
9
|
-
export declare namespace error {
|
|
10
|
-
var exit: () => never;
|
|
11
|
-
}
|
|
12
|
-
export declare const head: (method: string, noColor?: boolean) => string;
|
|
13
|
-
export declare function p(s: number | string, pad: number, start?: boolean): string;
|
|
14
|
-
export declare function w(s: string): number;
|
|
15
|
-
export declare function space(str: string): string;
|
|
16
|
-
export declare function invisibleSpace(str: string): string;
|
|
17
|
-
export declare function messageToString(message: string, reason?: string): string;
|
package/lib/util.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import module from 'node:module';
|
|
2
|
-
import c from 'cli-color';
|
|
3
|
-
// @ts-ignore
|
|
4
|
-
import eastasianwidth from 'eastasianwidth';
|
|
5
|
-
import stripAnsi from 'strip-ansi';
|
|
6
|
-
import { v4 } from 'uuid';
|
|
7
|
-
const require = module.createRequire(import.meta.url);
|
|
8
|
-
export function uuid() {
|
|
9
|
-
return v4();
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Brand color (xTerm color)
|
|
13
|
-
*
|
|
14
|
-
* @see http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
|
|
15
|
-
*/
|
|
16
|
-
const PRIMARY_COLOR = 33;
|
|
17
|
-
const logo = `/${c.xterm(PRIMARY_COLOR)('✔')}\\`;
|
|
18
|
-
const version = require('../package.json').version;
|
|
19
|
-
const eaw = eastasianwidth;
|
|
20
|
-
const box = (lines, { width = 40, padding = 1, center = false, noColor = false }) => {
|
|
21
|
-
const bt = `┌${'─'.repeat(width - 2)}┐`;
|
|
22
|
-
const pd = `│${' '.repeat(width - 2)}│`;
|
|
23
|
-
const bb = `└${'─'.repeat(width - 2)}┘`;
|
|
24
|
-
const texts = lines.map(line => {
|
|
25
|
-
const nc = stripAnsi(line);
|
|
26
|
-
const length = nc.length;
|
|
27
|
-
const pad = width - 2 - 1 - length;
|
|
28
|
-
const pad2 = Math.floor(pad / 2);
|
|
29
|
-
const padD = pad % 2;
|
|
30
|
-
const padL = center ? pad2 : 0;
|
|
31
|
-
const padR = center ? pad2 + padD : pad;
|
|
32
|
-
const text = noColor ? nc : line;
|
|
33
|
-
return `│ ${' '.repeat(padL)}${text}${' '.repeat(padR)}│`;
|
|
34
|
-
});
|
|
35
|
-
const result = [bt, pd, ...texts, pd, bb];
|
|
36
|
-
return result.join('\n');
|
|
37
|
-
};
|
|
38
|
-
export const markuplint = `markup${c.xterm(PRIMARY_COLOR)('lint')}`;
|
|
39
|
-
export function write(message) {
|
|
40
|
-
process.stdout.write(message + '\n');
|
|
41
|
-
}
|
|
42
|
-
write.break = () => process.stdout.write('\n');
|
|
43
|
-
export function error(message) {
|
|
44
|
-
process.stderr.write(message + '\n');
|
|
45
|
-
}
|
|
46
|
-
// eslint-disable-next-line unicorn/no-process-exit
|
|
47
|
-
error.exit = () => process.exit(1);
|
|
48
|
-
export const head = (method, noColor) => box([`${logo} ${markuplint}`, c.blackBright(`v${version}`), '', c.bold(method)], {
|
|
49
|
-
center: true,
|
|
50
|
-
noColor,
|
|
51
|
-
});
|
|
52
|
-
export function p(s, pad, start = false) {
|
|
53
|
-
const l = w(`${s}`.trim());
|
|
54
|
-
const d = pad - l;
|
|
55
|
-
const _ = ' '.repeat(d < 0 ? 0 : d);
|
|
56
|
-
return start ? `${_}${s}` : `${s}${_}`;
|
|
57
|
-
}
|
|
58
|
-
export function w(s) {
|
|
59
|
-
return s.replaceAll(/./g, _ => '0'.repeat(eaw.characterLength(_))).length;
|
|
60
|
-
}
|
|
61
|
-
export function space(str) {
|
|
62
|
-
return str
|
|
63
|
-
.replaceAll(/\s+/g, $0 => {
|
|
64
|
-
return c.xterm(8)($0);
|
|
65
|
-
})
|
|
66
|
-
.replaceAll(' ', $0 => '•')
|
|
67
|
-
.replaceAll('\t', $0 => '→ ');
|
|
68
|
-
}
|
|
69
|
-
export function invisibleSpace(str) {
|
|
70
|
-
return str.replaceAll('\t', $0 => ' ').replaceAll(/./g, $0 => ' ');
|
|
71
|
-
}
|
|
72
|
-
export function messageToString(message, reason) {
|
|
73
|
-
if (!reason) {
|
|
74
|
-
return message;
|
|
75
|
-
}
|
|
76
|
-
return `${message} / ${reason}`;
|
|
77
|
-
}
|