md-hopper 1.0.0-alpha
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 +20 -0
- package/cli/commands/generate/README.md/package.json +6 -0
- package/cli/commands/generate/action/package.json +6 -0
- package/cli/commands/generate/command/package.json +6 -0
- package/cli/commands/help/action/package.json +6 -0
- package/cli/commands/help/command/package.json +6 -0
- package/cli/commands/index/package.json +6 -0
- package/cli/index/package.json +6 -0
- package/dist/_internal/types/command.d.ts +11 -0
- package/dist/_internal/types/command.js +1 -0
- package/dist/_internal/types/md.d.ts +48 -0
- package/dist/_internal/types/md.js +21 -0
- package/dist/_internal/types/options.d.ts +15 -0
- package/dist/_internal/types/options.js +1 -0
- package/dist/_internal/types/process.d.ts +5 -0
- package/dist/_internal/types/process.js +4 -0
- package/dist/_internal/types/settings.d.ts +8 -0
- package/dist/_internal/types/settings.js +1 -0
- package/dist/_internal/utils/command.d.ts +18 -0
- package/dist/_internal/utils/command.js +55 -0
- package/dist/_internal/utils/configs.d.ts +3 -0
- package/dist/_internal/utils/configs.js +3 -0
- package/dist/_internal/utils/fs.d.ts +1 -0
- package/dist/_internal/utils/fs.js +1 -0
- package/dist/_internal/utils/log.d.ts +4 -0
- package/dist/_internal/utils/log.js +13 -0
- package/dist/_internal/utils/md.d.ts +5 -0
- package/dist/_internal/utils/md.js +231 -0
- package/dist/_internal/utils/path-match.d.ts +1 -0
- package/dist/_internal/utils/path-match.js +2 -0
- package/dist/_internal/utils/path.d.ts +14 -0
- package/dist/_internal/utils/path.js +52 -0
- package/dist/_internal/utils/process.d.ts +6 -0
- package/dist/_internal/utils/process.js +27 -0
- package/dist/_internal/utils/settings.d.ts +5 -0
- package/dist/_internal/utils/settings.js +45 -0
- package/dist/_internal/utils/type-check.d.ts +1 -0
- package/dist/_internal/utils/type-check.js +10 -0
- package/dist/cli/commands/generate/action.d.ts +3 -0
- package/dist/cli/commands/generate/action.js +87 -0
- package/dist/cli/commands/generate/command.d.ts +2 -0
- package/dist/cli/commands/generate/command.js +21 -0
- package/dist/cli/commands/help/action.d.ts +3 -0
- package/dist/cli/commands/help/action.js +26 -0
- package/dist/cli/commands/help/command.d.ts +2 -0
- package/dist/cli/commands/help/command.js +13 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.js +8 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +17 -0
- package/package.json +100 -0
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!-- MD_HOPPER: CONFIG: -->
|
|
2
|
+
|
|
3
|
+
# MD HOPPER
|
|
4
|
+
|
|
5
|
+
This Package Link md files in same repository.
|
|
6
|
+
|
|
7
|
+
# Commands
|
|
8
|
+
|
|
9
|
+
<!-- MD_HOPPER: LINK_NEXT_LINE:
|
|
10
|
+
id: generate-command
|
|
11
|
+
inline: true
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
[generate][md_hopper:generate-command]
|
|
15
|
+
|
|
16
|
+
<!-- MD_HOPPER: BEGIN_DEFINE_LINKS: -->
|
|
17
|
+
|
|
18
|
+
[md_hopper:generate-command]: ./src/cli/commands/generate/README.md 'GENERATE COMMAND'
|
|
19
|
+
|
|
20
|
+
<!-- MD_HOPPER: END_DEFINE_LINKS: -->
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Options, DefaultOptions } from './options.js';
|
|
2
|
+
import { Settings } from './settings.js';
|
|
3
|
+
export type Action = (...args: any[]) => any;
|
|
4
|
+
export interface BeforeFunction {
|
|
5
|
+
fn: Action;
|
|
6
|
+
args: any[];
|
|
7
|
+
}
|
|
8
|
+
export interface ActionArg<T extends DefaultOptions> {
|
|
9
|
+
options: Options<T>;
|
|
10
|
+
settings: Settings;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export declare const PROPERTIES: {
|
|
2
|
+
CONFIG: string;
|
|
3
|
+
LINK_NEXT_LINE: string;
|
|
4
|
+
BEGIN_LINKS: string;
|
|
5
|
+
END_LINKS: string;
|
|
6
|
+
BEGIN_DEFINE_LINKS: string;
|
|
7
|
+
END_DEFINE_LINKS: string;
|
|
8
|
+
BEFORE_GENERATE_LINK: string;
|
|
9
|
+
};
|
|
10
|
+
export interface PathInfo {
|
|
11
|
+
id: string;
|
|
12
|
+
lock: boolean;
|
|
13
|
+
title: string;
|
|
14
|
+
path: string;
|
|
15
|
+
dir: string;
|
|
16
|
+
output: string;
|
|
17
|
+
outputPath: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PathDepthClassify {
|
|
20
|
+
children: string[];
|
|
21
|
+
grandchildren: string[];
|
|
22
|
+
parallels: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface Detail extends PathInfo, PathDepthClassify {
|
|
25
|
+
}
|
|
26
|
+
export interface LinkNextLineProperties {
|
|
27
|
+
id: string;
|
|
28
|
+
inline: true;
|
|
29
|
+
}
|
|
30
|
+
export interface EndLinksProperties {
|
|
31
|
+
all: boolean;
|
|
32
|
+
linked: boolean;
|
|
33
|
+
child: boolean;
|
|
34
|
+
grandChild: boolean;
|
|
35
|
+
parallel: boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare const LINK_NAME_PREFIX = "md_hopper:";
|
|
38
|
+
export declare const BEGIN_COMMENT = "<!--";
|
|
39
|
+
export declare const END_COMMENT = "-->";
|
|
40
|
+
export declare const PARAM_SEPARATOR = ":";
|
|
41
|
+
export declare const MD_HOPPER_COMMENT_PREFIX = "MD_HOPPER";
|
|
42
|
+
export declare const COMMENT_REG_EXP: RegExp;
|
|
43
|
+
export declare const BRAKE_LINE_REG_EXP: RegExp;
|
|
44
|
+
export declare const LINK_REG_EXP: RegExp;
|
|
45
|
+
export declare const MD_HOPPER_COMMENT_PREFIX_REG_EXP: RegExp;
|
|
46
|
+
export declare const MD_HOPPER_PARAMS_REG_EXP: RegExp;
|
|
47
|
+
export declare const MD_HOPPER_CONTENT_REG_EXP: RegExp;
|
|
48
|
+
export declare const MD_HOPPER_PROPERTY_REG_EXP: RegExp;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const PROPERTIES = {
|
|
2
|
+
CONFIG: 'CONFIG',
|
|
3
|
+
LINK_NEXT_LINE: 'LINK_NEXT_LINE',
|
|
4
|
+
BEGIN_LINKS: 'BEGIN_LINKS',
|
|
5
|
+
END_LINKS: 'END_LINKS',
|
|
6
|
+
BEGIN_DEFINE_LINKS: 'BEGIN_DEFINE_LINKS',
|
|
7
|
+
END_DEFINE_LINKS: 'END_DEFINE_LINKS',
|
|
8
|
+
BEFORE_GENERATE_LINK: 'BEFORE_GENERATE_LINK',
|
|
9
|
+
};
|
|
10
|
+
export const LINK_NAME_PREFIX = 'md_hopper:';
|
|
11
|
+
export const BEGIN_COMMENT = '<!--';
|
|
12
|
+
export const END_COMMENT = '-->';
|
|
13
|
+
export const PARAM_SEPARATOR = ':';
|
|
14
|
+
export const MD_HOPPER_COMMENT_PREFIX = 'MD_HOPPER';
|
|
15
|
+
export const COMMENT_REG_EXP = new RegExp(`${BEGIN_COMMENT}\\s*.*?${END_COMMENT}`, 'gs');
|
|
16
|
+
export const BRAKE_LINE_REG_EXP = new RegExp(/\r?\n/, 'g');
|
|
17
|
+
export const LINK_REG_EXP = new RegExp('^\\s*.*\\[(.+)][(|\\[](.+)[)|\\]].*');
|
|
18
|
+
export const MD_HOPPER_COMMENT_PREFIX_REG_EXP = new RegExp(`${BEGIN_COMMENT}\\s*${MD_HOPPER_COMMENT_PREFIX}${PARAM_SEPARATOR}\\s*`);
|
|
19
|
+
export const MD_HOPPER_PARAMS_REG_EXP = new RegExp(`^[^${PARAM_SEPARATOR}]+${PARAM_SEPARATOR}(.*?)${END_COMMENT}.*`, 's');
|
|
20
|
+
export const MD_HOPPER_CONTENT_REG_EXP = new RegExp(`^[^${PARAM_SEPARATOR}]+${PARAM_SEPARATOR}.*${END_COMMENT}(.*)`, 's');
|
|
21
|
+
export const MD_HOPPER_PROPERTY_REG_EXP = new RegExp(`^([^${PARAM_SEPARATOR}]+?)${PARAM_SEPARATOR}.*`, 's');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BundleOptions {
|
|
2
|
+
skipHidden?: boolean;
|
|
3
|
+
include?: string;
|
|
4
|
+
exclude?: string;
|
|
5
|
+
filenames?: string;
|
|
6
|
+
output?: string;
|
|
7
|
+
input?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface HelpOptions {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
export interface DefaultOptions {
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
}
|
|
15
|
+
export type Options<T extends DefaultOptions = DefaultOptions> = T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command as Program } from 'commander';
|
|
2
|
+
import { Action, ActionArg } from '../types/command.js';
|
|
3
|
+
import { DefaultOptions } from '../types/options.js';
|
|
4
|
+
import { Settings } from '../types/settings.js';
|
|
5
|
+
export declare class CommandClass<T extends DefaultOptions> {
|
|
6
|
+
program: Program;
|
|
7
|
+
private befores;
|
|
8
|
+
private args;
|
|
9
|
+
constructor(program: Program);
|
|
10
|
+
init(options: ActionArg<T>['options'], settings: Settings): Promise<this>;
|
|
11
|
+
command(command: string): this;
|
|
12
|
+
help(helpTxt: string): CommandClass<T>;
|
|
13
|
+
before(before: Action, ...args: any[]): CommandClass<T>;
|
|
14
|
+
description(description: string): CommandClass<T>;
|
|
15
|
+
option(...args: any[]): CommandClass<T>;
|
|
16
|
+
requiredOption(...args: any[]): CommandClass<T>;
|
|
17
|
+
action(action: Action): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getSettings } from './settings.js';
|
|
2
|
+
export class CommandClass {
|
|
3
|
+
program;
|
|
4
|
+
befores = [];
|
|
5
|
+
args;
|
|
6
|
+
constructor(program) {
|
|
7
|
+
this.program = program;
|
|
8
|
+
}
|
|
9
|
+
async init(options, settings) {
|
|
10
|
+
this.args = {
|
|
11
|
+
options,
|
|
12
|
+
settings,
|
|
13
|
+
};
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
command(command) {
|
|
17
|
+
this.program = this.program.command(command).option('-d, --debug', 'turn on debugging', false);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
help(helpTxt) {
|
|
21
|
+
this.program = this.program.on('--help', () => {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(helpTxt);
|
|
24
|
+
});
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
before(before, ...args) {
|
|
28
|
+
this.befores.push({ fn: before, args: args });
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
description(description) {
|
|
32
|
+
this.program = this.program.description(description);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
option(...args) {
|
|
36
|
+
const flags = args.shift();
|
|
37
|
+
this.program = this.program.option(flags, ...args);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
requiredOption(...args) {
|
|
41
|
+
const flags = args.shift();
|
|
42
|
+
this.program = this.program.requiredOption(flags, ...args);
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
action(action) {
|
|
46
|
+
this.program = this.program.action(async (...args) => {
|
|
47
|
+
const options = args[0];
|
|
48
|
+
await this.init(options, getSettings(options.input || ''));
|
|
49
|
+
for (const before of this.befores) {
|
|
50
|
+
await before.fn(options, ...before.args);
|
|
51
|
+
}
|
|
52
|
+
return action(this.args, ...args);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getAllFiles } from 'my-gadgetry/fs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getAllFiles } from 'my-gadgetry/fs';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const success = (...args) => {
|
|
3
|
+
console.log(chalk.green(...args));
|
|
4
|
+
};
|
|
5
|
+
export const warn = (...args) => {
|
|
6
|
+
console.log(chalk.hex('#FFA500')(...args));
|
|
7
|
+
};
|
|
8
|
+
export const info = (...args) => {
|
|
9
|
+
console.log(chalk.blue(...args));
|
|
10
|
+
};
|
|
11
|
+
export const error = (...args) => {
|
|
12
|
+
console.log(chalk.red(...args));
|
|
13
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Detail } from '../types/md.js';
|
|
2
|
+
export declare const getParam: (text: string, key: string) => string;
|
|
3
|
+
export declare const getParams: (text: string, key: string) => RegExpMatchArray | "";
|
|
4
|
+
export declare const getTitle: (text: string) => string;
|
|
5
|
+
export declare const replace: (detail: Detail, details: Detail[]) => string;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { PROPERTIES, LINK_NAME_PREFIX, COMMENT_REG_EXP, PARAM_SEPARATOR, LINK_REG_EXP, MD_HOPPER_COMMENT_PREFIX, MD_HOPPER_COMMENT_PREFIX_REG_EXP, MD_HOPPER_PROPERTY_REG_EXP, MD_HOPPER_PARAMS_REG_EXP, BRAKE_LINE_REG_EXP, MD_HOPPER_CONTENT_REG_EXP, BEGIN_COMMENT, END_COMMENT, } from '../types/md.js';
|
|
3
|
+
import { getRelative } from './path.js';
|
|
4
|
+
import { isBoolean } from './type-check.js';
|
|
5
|
+
export const getParam = (text, key) => {
|
|
6
|
+
const PREFIX = `${BEGIN_COMMENT}\\s*${MD_HOPPER_COMMENT_PREFIX}:\\s*${key}:`;
|
|
7
|
+
const reg = new RegExp(`${PREFIX}(.*?)${END_COMMENT}`, 's');
|
|
8
|
+
if (!reg.test(text)) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
return reg.exec(text)[1];
|
|
12
|
+
};
|
|
13
|
+
export const getParams = (text, key) => {
|
|
14
|
+
const PREFIX = `${BEGIN_COMMENT}\\s*${MD_HOPPER_COMMENT_PREFIX}:\\s*${key}:`;
|
|
15
|
+
const reg = new RegExp(`${PREFIX}(.*?)${END_COMMENT}`, 'gs');
|
|
16
|
+
if (!reg.test(text)) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
return text.match(reg);
|
|
20
|
+
};
|
|
21
|
+
const getRemovedCommentOut = (text) => text.replace(COMMENT_REG_EXP, '');
|
|
22
|
+
const getFirstLine = (text) => {
|
|
23
|
+
const lines = text.split('\n').filter(line => line.trim().length);
|
|
24
|
+
return lines.length ? lines[0].trim() : '';
|
|
25
|
+
};
|
|
26
|
+
export const getTitle = (text) => {
|
|
27
|
+
const title = getParam(text, 'TITLE');
|
|
28
|
+
if (title) {
|
|
29
|
+
return title;
|
|
30
|
+
}
|
|
31
|
+
const md = getRemovedCommentOut(text);
|
|
32
|
+
return getParam(text, 'TITLE') || md.replace(/\r?\n?#+(.*?)\r?\n.*/s, '$1').trim() || getFirstLine(md);
|
|
33
|
+
};
|
|
34
|
+
const getLinkName = (id) => `${LINK_NAME_PREFIX}${id}`;
|
|
35
|
+
const getLink = (id, title) => `[${title}][${getLinkName(id)}]`;
|
|
36
|
+
const getLinksByDetails = (details) => details.map(d => getLink(d.id, d.title));
|
|
37
|
+
const getDefineLink = (id, url, title) => `[${getLinkName(id)}]: ${url}${title ? ` '${title}'` : ''}`;
|
|
38
|
+
const replaceToLink = (txt, inline, detail) => {
|
|
39
|
+
if (LINK_REG_EXP.test(txt)) {
|
|
40
|
+
const url = txt.replace(LINK_REG_EXP, '$2');
|
|
41
|
+
if (url === getLinkName(detail.id)) {
|
|
42
|
+
return txt;
|
|
43
|
+
}
|
|
44
|
+
return `[${txt.replace(LINK_REG_EXP, '$1')}][${getLinkName(detail.id)}]
|
|
45
|
+
<!-- ${MD_HOPPER_COMMENT_PREFIX}${PARAM_SEPARATOR} ${PROPERTIES.BEFORE_GENERATE_LINK}${PARAM_SEPARATOR} -->
|
|
46
|
+
<!-- ${txt} -->
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
if (inline) {
|
|
50
|
+
return `[${txt}][${getLinkName(detail.id)}]`;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return `[${detail.title}][${getLinkName(detail.id)}]
|
|
54
|
+
${txt}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const getLinkContent = (path, content, { id, inline }, details) => {
|
|
59
|
+
const data = details.find(d => d.path !== path && d.id === id);
|
|
60
|
+
if (!data) {
|
|
61
|
+
return content;
|
|
62
|
+
}
|
|
63
|
+
const splits = content.split('\n');
|
|
64
|
+
const lines = [];
|
|
65
|
+
let firstLine = false;
|
|
66
|
+
for (const split of splits) {
|
|
67
|
+
if (split.trim().length && !firstLine) {
|
|
68
|
+
firstLine = true;
|
|
69
|
+
lines.push(replaceToLink(split, inline, data));
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
lines.push(split);
|
|
73
|
+
}
|
|
74
|
+
return lines.join('\n');
|
|
75
|
+
};
|
|
76
|
+
const getSectionParams = (section) => {
|
|
77
|
+
const params = section.replace(MD_HOPPER_PARAMS_REG_EXP, '$1');
|
|
78
|
+
const splits = params
|
|
79
|
+
.split(BRAKE_LINE_REG_EXP)
|
|
80
|
+
.filter(p => p.trim().length);
|
|
81
|
+
return {
|
|
82
|
+
params: splits.reduce((acc, keyValueText) => {
|
|
83
|
+
const keyValue = keyValueText.split(PARAM_SEPARATOR).map(k => k.trim());
|
|
84
|
+
if (keyValue.length !== 2) {
|
|
85
|
+
return acc;
|
|
86
|
+
}
|
|
87
|
+
acc[keyValue[0]] = isBoolean(keyValue[1]) ? JSON.parse(keyValue[1]) : keyValue[1];
|
|
88
|
+
return acc;
|
|
89
|
+
}, {}),
|
|
90
|
+
content: section.replace(MD_HOPPER_CONTENT_REG_EXP, '$1'),
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
const getRelateDetails = (details, list) => details.filter(d => list.includes(d.path));
|
|
94
|
+
const push = (list, stack = []) => {
|
|
95
|
+
for (const data of list) {
|
|
96
|
+
stack.push(data);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const getLinksByProperties = (detail, properties, details) => {
|
|
100
|
+
if (properties.all) {
|
|
101
|
+
return details.filter(d => d.path !== detail.path);
|
|
102
|
+
}
|
|
103
|
+
const links = [];
|
|
104
|
+
if (properties.parallel) {
|
|
105
|
+
push(getRelateDetails(details, detail.parallels), links);
|
|
106
|
+
}
|
|
107
|
+
if (properties.child) {
|
|
108
|
+
push(getRelateDetails(details, detail.children), links);
|
|
109
|
+
}
|
|
110
|
+
if (properties.grandChild) {
|
|
111
|
+
push(getRelateDetails(details, detail.grandchildren), links);
|
|
112
|
+
}
|
|
113
|
+
return links;
|
|
114
|
+
};
|
|
115
|
+
const getLinksContent = (properties, linksDetails, lineLinkDetails) => {
|
|
116
|
+
let list = linksDetails;
|
|
117
|
+
if (!properties.linked) {
|
|
118
|
+
list = linksDetails.filter(d => lineLinkDetails.every(lineLinkDetail => lineLinkDetail.path !== d.path));
|
|
119
|
+
}
|
|
120
|
+
return `\n${getLinksByDetails(list).join('\n')}\n`;
|
|
121
|
+
};
|
|
122
|
+
const rebaseCommentSection = (property, params) => {
|
|
123
|
+
if (!Object.keys(params).length) {
|
|
124
|
+
return `${property}: ${END_COMMENT}`;
|
|
125
|
+
}
|
|
126
|
+
return `${property}:\n${Object.entries(params)
|
|
127
|
+
.map(([key, value]) => `${key}: ${value}`)
|
|
128
|
+
.join('\n')}\n${END_COMMENT}`;
|
|
129
|
+
};
|
|
130
|
+
const getSectionByContent = (property, params, content) => {
|
|
131
|
+
return `${rebaseCommentSection(property, params)}${content}`;
|
|
132
|
+
};
|
|
133
|
+
const getValidate = (detail, sections, details) => {
|
|
134
|
+
let hasEndLinksSection = false;
|
|
135
|
+
let hasBeginDefineLinksSection = false;
|
|
136
|
+
let hasEndDefineLinksSection = false;
|
|
137
|
+
let linksDetails = [];
|
|
138
|
+
const lineLinksDetails = [];
|
|
139
|
+
for (const section of sections) {
|
|
140
|
+
const property = section.replace(MD_HOPPER_PROPERTY_REG_EXP, '$1');
|
|
141
|
+
switch (property) {
|
|
142
|
+
case PROPERTIES.LINK_NEXT_LINE: {
|
|
143
|
+
const { params } = getSectionParams(section);
|
|
144
|
+
const data = details.find(d => d.path !== detail.path && d.id === params.id);
|
|
145
|
+
if (data) {
|
|
146
|
+
lineLinksDetails.push(data);
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case PROPERTIES.BEGIN_LINKS:
|
|
151
|
+
linksDetails = getLinksByProperties(detail, getSectionParams(section).params, details);
|
|
152
|
+
break;
|
|
153
|
+
case PROPERTIES.END_LINKS:
|
|
154
|
+
hasEndLinksSection = true;
|
|
155
|
+
break;
|
|
156
|
+
case PROPERTIES.BEGIN_DEFINE_LINKS:
|
|
157
|
+
hasBeginDefineLinksSection = true;
|
|
158
|
+
break;
|
|
159
|
+
case PROPERTIES.END_DEFINE_LINKS:
|
|
160
|
+
hasEndDefineLinksSection = true;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
hasEndLinksSection,
|
|
166
|
+
hasBeginDefineLinksSection,
|
|
167
|
+
hasEndDefineLinksSection,
|
|
168
|
+
linksDetails,
|
|
169
|
+
lineLinksDetails,
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
const setDefineLinks = (currentDir, details, defineMap = {}) => {
|
|
173
|
+
for (const { id, title, outputPath } of details) {
|
|
174
|
+
let url = getRelative(currentDir, outputPath);
|
|
175
|
+
if (!/^\.*\//.test(url)) {
|
|
176
|
+
url = `./${url}`;
|
|
177
|
+
}
|
|
178
|
+
defineMap[outputPath] = getDefineLink(id, url, title);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const getDefineLinksContent = (dir, linksDetails, lineLinkDetails, hasEndDefineLinksSection) => {
|
|
182
|
+
const defineMap = {};
|
|
183
|
+
setDefineLinks(dir, linksDetails, defineMap);
|
|
184
|
+
setDefineLinks(dir, lineLinkDetails, defineMap);
|
|
185
|
+
let content = `\n${Object.values(defineMap).join('\n')}\n`;
|
|
186
|
+
if (!hasEndDefineLinksSection) {
|
|
187
|
+
content += `${BEGIN_COMMENT} ${MD_HOPPER_COMMENT_PREFIX}${PARAM_SEPARATOR} ${PROPERTIES.END_DEFINE_LINKS}${PARAM_SEPARATOR} ${END_COMMENT}\n`;
|
|
188
|
+
}
|
|
189
|
+
return content;
|
|
190
|
+
};
|
|
191
|
+
export const replace = (detail, details) => {
|
|
192
|
+
const md = readFileSync(detail.path, 'utf-8');
|
|
193
|
+
const _sections = md.split(MD_HOPPER_COMMENT_PREFIX_REG_EXP);
|
|
194
|
+
const sections = [];
|
|
195
|
+
let i = -1;
|
|
196
|
+
const { hasEndLinksSection, hasBeginDefineLinksSection, hasEndDefineLinksSection, linksDetails, lineLinksDetails } = getValidate(detail, _sections, details);
|
|
197
|
+
for (const _section of _sections) {
|
|
198
|
+
++i;
|
|
199
|
+
if (i === 0) {
|
|
200
|
+
sections.push(_section);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const property = _section.replace(MD_HOPPER_PROPERTY_REG_EXP, '$1');
|
|
204
|
+
const { params, content: _content } = getSectionParams(_section);
|
|
205
|
+
let content = _content;
|
|
206
|
+
let section = _section;
|
|
207
|
+
switch (property) {
|
|
208
|
+
case PROPERTIES.LINK_NEXT_LINE:
|
|
209
|
+
content = getLinkContent(detail.path, _content, params, details);
|
|
210
|
+
section = getSectionByContent(property, params, content);
|
|
211
|
+
break;
|
|
212
|
+
case PROPERTIES.BEGIN_LINKS:
|
|
213
|
+
content = getLinksContent(params, linksDetails, lineLinksDetails);
|
|
214
|
+
section = getSectionByContent(property, params, content);
|
|
215
|
+
if (!hasEndLinksSection) {
|
|
216
|
+
section += `\n${BEGIN_COMMENT} ${MD_HOPPER_COMMENT_PREFIX}${PARAM_SEPARATOR} ${PROPERTIES.END_LINKS}${PARAM_SEPARATOR} ${END_COMMENT}`;
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
case PROPERTIES.BEGIN_DEFINE_LINKS:
|
|
220
|
+
section = getSectionByContent(property, params, getDefineLinksContent(detail.dir, linksDetails, lineLinksDetails, hasEndDefineLinksSection));
|
|
221
|
+
break;
|
|
222
|
+
default:
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
sections.push(section);
|
|
226
|
+
}
|
|
227
|
+
if (!hasBeginDefineLinksSection) {
|
|
228
|
+
sections.push(getSectionByContent(PROPERTIES.BEGIN_DEFINE_LINKS, {}, getDefineLinksContent(detail.dir, linksDetails, lineLinksDetails, hasEndDefineLinksSection)));
|
|
229
|
+
}
|
|
230
|
+
return sections.join(`${BEGIN_COMMENT} ${MD_HOPPER_COMMENT_PREFIX}${PARAM_SEPARATOR} `);
|
|
231
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isMatch: (path: string, pattern: string) => boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const getProjectRootPath: () => string;
|
|
2
|
+
export declare const getFullPath: (...path: string[]) => string;
|
|
3
|
+
export declare const getDir: (path: string) => string;
|
|
4
|
+
export declare const DEPTH_TYPES: {
|
|
5
|
+
ancestor: string;
|
|
6
|
+
parent: string;
|
|
7
|
+
parallel: string;
|
|
8
|
+
child: string;
|
|
9
|
+
grandchild: string;
|
|
10
|
+
different: string;
|
|
11
|
+
};
|
|
12
|
+
export type DepthType = (typeof DEPTH_TYPES)[keyof typeof DEPTH_TYPES];
|
|
13
|
+
export declare const getDepthType: (thisDir: string, isTypeFromThisDir: string) => DepthType;
|
|
14
|
+
export declare const getRelative: (dir: string, path: string) => string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { join, parse, relative } from 'path';
|
|
3
|
+
import { SETTING_FILE_NAME } from './configs.js';
|
|
4
|
+
export const getProjectRootPath = () => {
|
|
5
|
+
let path = process.cwd();
|
|
6
|
+
if (!existsSync(join(path, SETTING_FILE_NAME))) {
|
|
7
|
+
for (const _ in process.cwd().split(/\//g)) {
|
|
8
|
+
path = join(path, '..');
|
|
9
|
+
if (existsSync(join(path, SETTING_FILE_NAME))) {
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return path;
|
|
15
|
+
};
|
|
16
|
+
export const getFullPath = (...path) => join(getProjectRootPath(), ...path);
|
|
17
|
+
export const getDir = (path) => {
|
|
18
|
+
return parse(path).dir;
|
|
19
|
+
};
|
|
20
|
+
export const DEPTH_TYPES = {
|
|
21
|
+
ancestor: 'ancestor',
|
|
22
|
+
parent: 'parent',
|
|
23
|
+
parallel: 'parallel',
|
|
24
|
+
child: 'child',
|
|
25
|
+
grandchild: 'grandchild',
|
|
26
|
+
different: 'different',
|
|
27
|
+
};
|
|
28
|
+
export const getDepthType = (thisDir, isTypeFromThisDir) => {
|
|
29
|
+
if (thisDir === isTypeFromThisDir) {
|
|
30
|
+
return DEPTH_TYPES.parallel;
|
|
31
|
+
}
|
|
32
|
+
const thisDirSeparators = thisDir.split('/');
|
|
33
|
+
const isTypeFromThisDirSeparators = isTypeFromThisDir.split('/');
|
|
34
|
+
if (thisDir.startsWith(isTypeFromThisDir)) {
|
|
35
|
+
if (thisDirSeparators.length - isTypeFromThisDirSeparators.length === 1) {
|
|
36
|
+
return DEPTH_TYPES.child;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return DEPTH_TYPES.grandchild;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (isTypeFromThisDir.startsWith(thisDir)) {
|
|
43
|
+
if (isTypeFromThisDirSeparators.length - thisDirSeparators.length === 1) {
|
|
44
|
+
return DEPTH_TYPES.parent;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return DEPTH_TYPES.ancestor;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return DEPTH_TYPES.different;
|
|
51
|
+
};
|
|
52
|
+
export const getRelative = (dir, path) => relative(dir, path);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Env } from '../types/process.js';
|
|
2
|
+
export * from '../types/process.js';
|
|
3
|
+
export declare const args: string[];
|
|
4
|
+
export declare const init: () => void;
|
|
5
|
+
export declare const set: (env: Env, value: string | boolean | number) => void;
|
|
6
|
+
export declare const get: (env: Env) => string | boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ENVS } from '../types/process.js';
|
|
2
|
+
import pkg from '../../../package.json' assert { type: 'json' };
|
|
3
|
+
export * from '../types/process.js';
|
|
4
|
+
export const args = process.argv.slice(2);
|
|
5
|
+
export const init = () => {
|
|
6
|
+
set(ENVS.PACKAGE_VERSION, pkg.version);
|
|
7
|
+
set(ENVS.IS_DEBUG, bool(process.env.DEBUG) || args.includes('--debug'));
|
|
8
|
+
};
|
|
9
|
+
const bool = (val) => {
|
|
10
|
+
if (val === true || val === 'true') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
export const set = (env, value) => {
|
|
16
|
+
process.env[env] = `${value}`;
|
|
17
|
+
};
|
|
18
|
+
export const get = (env) => {
|
|
19
|
+
const val = process.env[env];
|
|
20
|
+
if (val === 'true') {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (val === 'false') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return val || '';
|
|
27
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Settings } from '../types/settings.js';
|
|
2
|
+
export declare const DEFAULT_MD_FILE_NAME = "README.md";
|
|
3
|
+
export declare const DEFAULT_SETTINGS: Settings;
|
|
4
|
+
export declare const parse: (txt: string) => Settings;
|
|
5
|
+
export declare const getSettings: (inputFilename: string) => Settings;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { getParam } from './md.js';
|
|
3
|
+
import { SETTING_FILE_NAME } from './configs.js';
|
|
4
|
+
import { getProjectRootPath } from './path.js';
|
|
5
|
+
const Booleans = ['skip-hidden'];
|
|
6
|
+
const Strings = ['exclude', 'include', 'filenames'];
|
|
7
|
+
export const DEFAULT_MD_FILE_NAME = 'README.md';
|
|
8
|
+
export const DEFAULT_SETTINGS = Object.freeze({
|
|
9
|
+
'skip-hidden': true,
|
|
10
|
+
exclude: [],
|
|
11
|
+
include: [],
|
|
12
|
+
filenames: [DEFAULT_MD_FILE_NAME],
|
|
13
|
+
output: DEFAULT_MD_FILE_NAME,
|
|
14
|
+
});
|
|
15
|
+
export const parse = (txt) => {
|
|
16
|
+
const lines = txt.split('\n');
|
|
17
|
+
const settings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS));
|
|
18
|
+
for (const line of lines) {
|
|
19
|
+
const keyValue = line.split(':');
|
|
20
|
+
if (keyValue.length !== 2) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const key = keyValue[0].trim();
|
|
24
|
+
const value = keyValue[1].trim();
|
|
25
|
+
let val;
|
|
26
|
+
if (Booleans.includes(key)) {
|
|
27
|
+
val = JSON.parse(`${value}`);
|
|
28
|
+
}
|
|
29
|
+
else if (Strings.includes(key)) {
|
|
30
|
+
val = value.split(',');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
settings[key] = val;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
...DEFAULT_SETTINGS,
|
|
39
|
+
...settings,
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export const getSettings = (inputFilename) => {
|
|
43
|
+
const readme = readFileSync(`${getProjectRootPath()}/${inputFilename || SETTING_FILE_NAME}`, 'utf-8');
|
|
44
|
+
return parse(getParam(readme, 'CONFIG'));
|
|
45
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isBoolean: (val: any, isAllowString?: boolean) => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isBoolean as _isBoolean } from 'my-gadgetry/type-check';
|
|
2
|
+
export const isBoolean = (val, isAllowString = true) => {
|
|
3
|
+
if (_isBoolean(val)) {
|
|
4
|
+
return true;
|
|
5
|
+
}
|
|
6
|
+
if (isAllowString) {
|
|
7
|
+
return val === 'true' || val === 'false';
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { getAllFiles } from '../../../_internal/utils/fs.js';
|
|
4
|
+
import { getParam, getTitle, replace } from '../../../_internal/utils/md.js';
|
|
5
|
+
import { getProjectRootPath } from '../../../_internal/utils/path.js';
|
|
6
|
+
import { getDir, getDepthType, DEPTH_TYPES } from '../../../_internal/utils/path.js';
|
|
7
|
+
const replacePath = (str) => str.replace(/\/{2,}/, '/');
|
|
8
|
+
const splitComma = (str, alternative) => (str ? str.split(',') : null) || alternative;
|
|
9
|
+
const mergeConfig = ({ options, settings }) => {
|
|
10
|
+
return {
|
|
11
|
+
'skip-hidden': typeof options.skipHidden === 'undefined' ? settings['skip-hidden'] : JSON.parse(`${options.skipHidden}`),
|
|
12
|
+
exclude: splitComma(options.exclude, settings.exclude),
|
|
13
|
+
include: splitComma(options.include, settings.include),
|
|
14
|
+
filenames: splitComma(options.filenames, settings.filenames),
|
|
15
|
+
output: options.output || settings.output,
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const classify = (dataList) => {
|
|
19
|
+
return dataList.reduce((mds, data) => {
|
|
20
|
+
const classifyList = { children: [], grandchildren: [], parallels: [] };
|
|
21
|
+
for (const { dir, path } of dataList) {
|
|
22
|
+
if (data.path === path) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
switch (getDepthType(dir, data.dir)) {
|
|
26
|
+
case DEPTH_TYPES.parallel:
|
|
27
|
+
classifyList.parallels.push(path);
|
|
28
|
+
break;
|
|
29
|
+
case DEPTH_TYPES.child:
|
|
30
|
+
classifyList.children.push(path);
|
|
31
|
+
break;
|
|
32
|
+
case DEPTH_TYPES.grandchild:
|
|
33
|
+
classifyList.grandchildren.push(path);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
mds.push({
|
|
38
|
+
...data,
|
|
39
|
+
...classifyList,
|
|
40
|
+
});
|
|
41
|
+
return mds;
|
|
42
|
+
}, []);
|
|
43
|
+
};
|
|
44
|
+
const getPathDetails = (paths, config) => {
|
|
45
|
+
const list = [];
|
|
46
|
+
for (const path of paths) {
|
|
47
|
+
const md = readFileSync(path, 'utf-8');
|
|
48
|
+
const id = getParam(md, 'ID').trim();
|
|
49
|
+
const LOCK = getParam(md, 'LOCK').trim();
|
|
50
|
+
const lock = LOCK ? JSON.parse(LOCK) : false;
|
|
51
|
+
const dir = getDir(path);
|
|
52
|
+
const output = getParam(md, 'OUTPUT').trim() || config.output;
|
|
53
|
+
list.push({
|
|
54
|
+
id,
|
|
55
|
+
lock,
|
|
56
|
+
title: (getTitle(md) || id || path).trim(),
|
|
57
|
+
path,
|
|
58
|
+
dir,
|
|
59
|
+
output,
|
|
60
|
+
outputPath: join(dir, output),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return classify(list);
|
|
64
|
+
};
|
|
65
|
+
export const action = async (args) => {
|
|
66
|
+
const rootPath = getProjectRootPath();
|
|
67
|
+
const config = mergeConfig(args);
|
|
68
|
+
const skipHidden = config['skip-hidden'] ? ['**/.*/**/*', '**/.*'] : [];
|
|
69
|
+
const exclude = [
|
|
70
|
+
'**/node_modules/.*/*',
|
|
71
|
+
'**/node_modules/**/*',
|
|
72
|
+
...skipHidden,
|
|
73
|
+
...config.exclude.map(path => replacePath(`${rootPath}/${path}`)),
|
|
74
|
+
];
|
|
75
|
+
const include = config.include.map(path => replacePath(`${rootPath}/${path}`));
|
|
76
|
+
const paths = getAllFiles(rootPath, [], { include, exclude }).filter(path => config.filenames.some(filename => path.endsWith(`/${filename}`)));
|
|
77
|
+
const pathDetails = getPathDetails(paths, config);
|
|
78
|
+
for (const pathDetail of pathDetails) {
|
|
79
|
+
if (pathDetail.lock) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const content = replace(pathDetail, pathDetails);
|
|
83
|
+
const output = pathDetail.output || config.output;
|
|
84
|
+
const writePath = output ? join(pathDetail.dir, output) : pathDetail.path;
|
|
85
|
+
writeFileSync(writePath, content, 'utf-8');
|
|
86
|
+
}
|
|
87
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommandClass } from '../../../_internal/utils/command.js';
|
|
2
|
+
import { action } from './action.js';
|
|
3
|
+
const setAliases = (commandClass) => {
|
|
4
|
+
commandClass
|
|
5
|
+
.description('This command is used to exec target file.')
|
|
6
|
+
.option('-sh --skip-hidden <boolean>', 'skip read hidden dir, default: true')
|
|
7
|
+
.option('-incl, --include <strings>', 'include dirs, default: [] (all files)')
|
|
8
|
+
.option('-excl, --exclude <strings>', 'ignore dirs, default: node_modules only')
|
|
9
|
+
.option('-f, --filenames <strings>', 'filenames, default: README.md only')
|
|
10
|
+
.option('-o, --output <filename>', 'output filename. default: README.md (replace)')
|
|
11
|
+
.option('-i, --input <filename>', 'target root filename, default: README.md')
|
|
12
|
+
.action(options => {
|
|
13
|
+
return action(options);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
const commands = ['generate', 'g'];
|
|
17
|
+
export const init = (program) => {
|
|
18
|
+
for (const command of commands) {
|
|
19
|
+
setAliases(new CommandClass(program).command(command));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { platform } from 'node:process';
|
|
2
|
+
import { info } from '../../../_internal/utils/log.js';
|
|
3
|
+
import { get, ENVS } from '../../../_internal/utils/process.js';
|
|
4
|
+
const ASCII_ART = `
|
|
5
|
+
|
|
6
|
+
_ _ __ _ _ _ ___ ___ _____
|
|
7
|
+
| | | | | \\ | | | | / / / |/ | | _ \\
|
|
8
|
+
| | | | | \\| | | |/ / / /| /| | | | | |
|
|
9
|
+
| | | | | |\\ | | |\\ \\ / / |__/ | | | | | |
|
|
10
|
+
| |___ | | | | \\ | | | \\ \\ / / | | | |_| |
|
|
11
|
+
|_____| |_| |_| \\_| |_| \\_\\ /_/ |_| |_____/
|
|
12
|
+
|
|
13
|
+
`;
|
|
14
|
+
const VERSIONS = `
|
|
15
|
+
Link MD: ${get(ENVS.PACKAGE_VERSION)}
|
|
16
|
+
Node: ${process.versions.node}
|
|
17
|
+
OS: ${platform} ${process.arch}
|
|
18
|
+
`;
|
|
19
|
+
const show = () => {
|
|
20
|
+
info(ASCII_ART);
|
|
21
|
+
info(VERSIONS);
|
|
22
|
+
};
|
|
23
|
+
export const action = async (_) => {
|
|
24
|
+
show();
|
|
25
|
+
return;
|
|
26
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CommandClass } from '../../../_internal/utils/command.js';
|
|
2
|
+
import { action } from './action.js';
|
|
3
|
+
const setAliases = (commandClass) => {
|
|
4
|
+
commandClass.description('This command is used to show help').action(options => {
|
|
5
|
+
return action(options);
|
|
6
|
+
});
|
|
7
|
+
};
|
|
8
|
+
const commands = ['help', 'h'];
|
|
9
|
+
export const init = (program) => {
|
|
10
|
+
for (const command of commands) {
|
|
11
|
+
setAliases(new CommandClass(program).command(command));
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { error } from '../_internal/utils/log.js';
|
|
4
|
+
import { get, ENVS, init } from '../_internal/utils/process.js';
|
|
5
|
+
import { init as initCommands } from './commands/index.js';
|
|
6
|
+
init();
|
|
7
|
+
program.version(`${get(ENVS.PACKAGE_VERSION)}`);
|
|
8
|
+
await initCommands(program);
|
|
9
|
+
program.action((_, args) => {
|
|
10
|
+
const cmd = args[0];
|
|
11
|
+
error(`${cmd} is not a Link MD command`);
|
|
12
|
+
error('');
|
|
13
|
+
error(`${cmd} has been renamed, please run instead`);
|
|
14
|
+
console.log('exit');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
});
|
|
17
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "md-hopper",
|
|
3
|
+
"version": "1.0.0-alpha",
|
|
4
|
+
"description": "",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"md-hopper": "./dist/cli/index.js",
|
|
8
|
+
"mdhopper": "./dist/cli/index.js",
|
|
9
|
+
"mdhop": "./dist/cli/index.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/cilly-yllic/md-hopper.git"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/cilly-yllic/md-hopper/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/cilly-yllic/md-hopper#readme",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"prepare": "husky",
|
|
21
|
+
"jest": "jest",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"lint:fix": "npm run lint -- --fix",
|
|
24
|
+
"_prettier": "prettier .",
|
|
25
|
+
"prettier:write": "npm run _prettier -- --write",
|
|
26
|
+
"prettier": "npm run prettier:write",
|
|
27
|
+
"prettier:check": "npm run _prettier -- --check",
|
|
28
|
+
"clean": "rimraf ./dist ./cli",
|
|
29
|
+
"tsc": "tsc -p tsconfig.publish.json && tsc-alias -p tsconfig.publish.json",
|
|
30
|
+
"generate": "tsx --tsconfig ./tsconfig.zx.json ./tools/generate-alias.zx.ts",
|
|
31
|
+
"ci:update-version": "tsx --tsconfig ./tsconfig.zx.json ./tools/update-version.zx.ts",
|
|
32
|
+
"md:generate": "tsx --tsconfig ./tsconfig.zx.json ./tools/generate-md.ts",
|
|
33
|
+
|
|
34
|
+
"//--- test ---//": "",
|
|
35
|
+
"test": "run-s test:*",
|
|
36
|
+
"test:lint": "npm run lint",
|
|
37
|
+
"test:prettier": "npm run prettier:check",
|
|
38
|
+
"test:jest": "npm run jest",
|
|
39
|
+
|
|
40
|
+
"//--- build ---//": "",
|
|
41
|
+
"build": "run-s build:*",
|
|
42
|
+
"build:test": "npm run test",
|
|
43
|
+
"build:clean": "npm run clean",
|
|
44
|
+
"build:tsc": "npm run tsc",
|
|
45
|
+
"build:generate": "npm run generate",
|
|
46
|
+
|
|
47
|
+
"//--- publish ---//": "",
|
|
48
|
+
"publish:build": "run-s build:{clean,tsc,generate}"
|
|
49
|
+
},
|
|
50
|
+
"author": "",
|
|
51
|
+
"exports": {
|
|
52
|
+
"./package.json": "./package.json"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=19.0.0"
|
|
56
|
+
},
|
|
57
|
+
"license": "ISC",
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@actions/core": "^1.10.1",
|
|
60
|
+
"@actions/exec": "^1.1.1",
|
|
61
|
+
"@actions/github": "^6.0.0",
|
|
62
|
+
"chalk": "^5.3.0",
|
|
63
|
+
"commander": "^12.0.0",
|
|
64
|
+
"minimatch": "^9.0.4",
|
|
65
|
+
"my-gadgetry": "^1.1.2",
|
|
66
|
+
"zx": "^8.1.0"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@babel/core": "^7.24.5",
|
|
70
|
+
"@babel/preset-env": "^7.24.5",
|
|
71
|
+
"@babel/preset-typescript": "^7.24.1",
|
|
72
|
+
"@eslint/js": "^8.57.0",
|
|
73
|
+
"@types/jest": "^29.5.12",
|
|
74
|
+
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
|
75
|
+
"@typescript-eslint/parser": "^7.9.0",
|
|
76
|
+
"babel-jest": "^29.7.0",
|
|
77
|
+
"eslint": "^8.57.0",
|
|
78
|
+
"eslint-config-prettier": "^9.1.0",
|
|
79
|
+
"eslint-import-resolver-typescript": "^3.6.1",
|
|
80
|
+
"eslint-plugin-import": "^2.29.1",
|
|
81
|
+
"eslint-plugin-jest": "^28.5.0",
|
|
82
|
+
"eslint-plugin-unused-imports": "^3.2.0",
|
|
83
|
+
"fs-extra": "^11.2.0",
|
|
84
|
+
"husky": "^9.0.11",
|
|
85
|
+
"jest": "^29.7.0",
|
|
86
|
+
"lint-staged": "^15.2.2",
|
|
87
|
+
"npm-run-all2": "^6.2.0",
|
|
88
|
+
"prettier": "^3.2.5",
|
|
89
|
+
"ts-jest": "^29.1.2",
|
|
90
|
+
"ts-node": "^10.9.2",
|
|
91
|
+
"tsc-alias": "^1.8.10",
|
|
92
|
+
"tsx": "^4.10.4",
|
|
93
|
+
"typescript": "^5.4.5",
|
|
94
|
+
"typescript-eslint": "^7.9.0"
|
|
95
|
+
},
|
|
96
|
+
"files": [
|
|
97
|
+
"cli",
|
|
98
|
+
"dist"
|
|
99
|
+
]
|
|
100
|
+
}
|