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.
Files changed (66) hide show
  1. package/lib/api/index.d.mts +2 -0
  2. package/lib/api/index.mjs +2 -0
  3. package/lib/api/lint.d.mts +4 -0
  4. package/lib/api/lint.mjs +15 -0
  5. package/lib/api/ml-engine.d.mts +27 -0
  6. package/lib/api/ml-engine.d.ts +18 -18
  7. package/lib/api/ml-engine.mjs +232 -0
  8. package/lib/api/types.d.mts +43 -0
  9. package/lib/api/types.d.ts +32 -39
  10. package/lib/api/types.mjs +1 -0
  11. package/lib/api/v1.d.mts +51 -0
  12. package/lib/api/v1.d.ts +43 -43
  13. package/lib/api/v1.mjs +39 -0
  14. package/lib/cli/bootstrap.d.mts +52 -0
  15. package/lib/cli/bootstrap.d.ts +49 -50
  16. package/lib/cli/bootstrap.mjs +81 -0
  17. package/lib/cli/command.d.mts +3 -0
  18. package/lib/cli/command.mjs +50 -0
  19. package/lib/cli/create-rule/index.d.mts +1 -0
  20. package/lib/cli/create-rule/index.mjs +51 -0
  21. package/lib/cli/index.d.mts +1 -0
  22. package/lib/cli/index.mjs +64 -0
  23. package/lib/cli/index.spec.d.mts +1 -0
  24. package/lib/cli/index.spec.mjs +48 -0
  25. package/lib/cli/init/index.d.mts +1 -0
  26. package/lib/cli/init/index.mjs +266 -0
  27. package/lib/cli/init/install-module.d.mts +5 -0
  28. package/lib/cli/init/install-module.d.ts +2 -2
  29. package/lib/cli/init/install-module.mjs +61 -0
  30. package/lib/cli/output.d.mts +3 -0
  31. package/lib/cli/output.mjs +31 -0
  32. package/lib/cli/prompt.d.mts +18 -0
  33. package/lib/cli/prompt.d.ts +12 -17
  34. package/lib/cli/prompt.mjs +68 -0
  35. package/lib/debug.d.mts +3 -0
  36. package/lib/debug.mjs +10 -0
  37. package/lib/global-settings.d.mts +5 -0
  38. package/lib/global-settings.d.ts +1 -1
  39. package/lib/global-settings.mjs +10 -0
  40. package/lib/i18n.d.mts +6 -0
  41. package/lib/i18n.d.ts +4 -4
  42. package/lib/i18n.mjs +19 -0
  43. package/lib/index.d.mts +8 -0
  44. package/lib/index.mjs +8 -0
  45. package/lib/reporter/index.d.mts +2 -0
  46. package/lib/reporter/index.mjs +2 -0
  47. package/lib/reporter/simple-reporter.d.mts +3 -0
  48. package/lib/reporter/simple-reporter.mjs +30 -0
  49. package/lib/reporter/standard-reporter.d.mts +3 -0
  50. package/lib/reporter/standard-reporter.mjs +43 -0
  51. package/lib/testing-tool/index.d.mts +35 -0
  52. package/lib/testing-tool/index.d.ts +25 -43
  53. package/lib/testing-tool/index.mjs +83 -0
  54. package/lib/types.d.mts +27 -0
  55. package/lib/types.d.ts +17 -17
  56. package/lib/types.mjs +1 -0
  57. package/lib/util.d.mts +19 -0
  58. package/lib/util.d.ts +3 -3
  59. package/lib/util.mjs +73 -0
  60. package/lib/v1.d.mts +4 -0
  61. package/lib/v1.mjs +4 -0
  62. package/package.json +4 -4
  63. package/lib/cli/head.d.ts +0 -1
  64. package/lib/cli/head.js +0 -31
  65. package/lib/reporter/utils.d.ts +0 -6
  66. 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,5 @@
1
+ export declare type InstallModuleResult = {
2
+ success: boolean;
3
+ alreadyExists: boolean;
4
+ };
5
+ export declare function installModule(module: string[], dev?: boolean): Promise<InstallModuleResult>;
@@ -1,5 +1,5 @@
1
1
  export declare type InstallModuleResult = {
2
- success: boolean;
3
- alreadyExists: boolean;
2
+ success: boolean;
3
+ alreadyExists: boolean;
4
4
  };
5
5
  export declare function installModule(module: string[], dev?: boolean): Promise<InstallModuleResult>;
@@ -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,3 @@
1
+ import type { MLResultInfo } from '../types.mjs';
2
+ import type { CLIOptions } from './bootstrap.mjs';
3
+ export declare function output(results: MLResultInfo, options: CLIOptions): Promise<void>;
@@ -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 {};
@@ -1,23 +1,18 @@
1
1
  declare type SelectQuestion<T> = {
2
- message: string;
3
- choices: {
4
- name: string;
5
- value: T;
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
- question: string,
13
- options?: {
14
- initial?: boolean;
15
- },
16
- ): Promise<boolean>;
17
- export declare function confirmSequence<T extends string = string>(
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
+ }
@@ -0,0 +1,3 @@
1
+ import debug from 'debug';
2
+ export declare const log: debug.Debugger;
3
+ export declare function verbosely(): void;
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
+ }
@@ -0,0 +1,5 @@
1
+ export declare type GlobalSettings = {
2
+ locale: string;
3
+ };
4
+ export declare function setGlobal(settings: Partial<GlobalSettings>): void;
5
+ export declare function getGlobal(): Readonly<Partial<GlobalSettings>>;
@@ -1,5 +1,5 @@
1
1
  export declare type GlobalSettings = {
2
- locale: string;
2
+ locale: string;
3
3
  };
4
4
  export declare function setGlobal(settings: Partial<GlobalSettings>): void;
5
5
  export declare function getGlobal(): Readonly<Partial<GlobalSettings>>;
@@ -0,0 +1,10 @@
1
+ let globalSettings = {};
2
+ export function setGlobal(settings) {
3
+ globalSettings = {
4
+ ...globalSettings,
5
+ ...settings,
6
+ };
7
+ }
8
+ export function getGlobal() {
9
+ return globalSettings;
10
+ }
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
- 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;
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
+ }
@@ -0,0 +1,8 @@
1
+ export { MLEngine } from './api/index.mjs';
2
+ export * from './i18n.mjs';
3
+ export * from './testing-tool/index.mjs';
4
+ export * from './types.mjs';
5
+ /**
6
+ * @deprecated
7
+ */
8
+ export * from './v1.mjs';
package/lib/index.mjs ADDED
@@ -0,0 +1,8 @@
1
+ export { MLEngine } from './api/index.mjs';
2
+ export * from './i18n.mjs';
3
+ export * from './testing-tool/index.mjs';
4
+ export * from './types.mjs';
5
+ /**
6
+ * @deprecated
7
+ */
8
+ export * from './v1.mjs';
@@ -0,0 +1,2 @@
1
+ export * from './standard-reporter.mjs';
2
+ export * from './simple-reporter.mjs';
@@ -0,0 +1,2 @@
1
+ export * from './standard-reporter.mjs';
2
+ export * from './simple-reporter.mjs';
@@ -0,0 +1,3 @@
1
+ import type { CLIOptions } from '../cli/bootstrap.mjs';
2
+ import type { MLResultInfo } from '../types.mjs';
3
+ export declare function simpleReporter(results: MLResultInfo, options: CLIOptions): string[];
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ import type { CLIOptions } from '../cli/bootstrap.mjs';
2
+ import type { MLResultInfo } from '../types.mjs';
3
+ export declare function standardReporter(results: MLResultInfo, options: CLIOptions): string[];