@adobe/helix-md2jcr 1.1.38 → 1.2.1
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/CHANGELOG.md +14 -0
- package/README.md +67 -10
- package/baseline-tests.sh +1 -1
- package/bin/md2jcr.js +219 -0
- package/package.json +4 -1
- package/src/cli/convert2jcr.js +0 -135
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.2.1](https://github.com/adobe/helix-md2jcr/compare/v1.2.0...v1.2.1) (2025-10-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* cli specify the folder to look for the json files in ([b7664fe](https://github.com/adobe/helix-md2jcr/commit/b7664fe1b5a8781218e8585649cb1d0bc099cdbc))
|
|
7
|
+
|
|
8
|
+
# [1.2.0](https://github.com/adobe/helix-md2jcr/compare/v1.1.38...v1.2.0) (2025-10-06)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add global CLI command for md2jcr ([4705024](https://github.com/adobe/helix-md2jcr/commit/47050246625b58ea93d23ac8c7fc303edc81998f))
|
|
14
|
+
|
|
1
15
|
## [1.1.38](https://github.com/adobe/helix-md2jcr/compare/v1.1.37...v1.1.38) (2025-10-06)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -16,31 +16,88 @@ npm install
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
19
|
+
|
|
20
|
+
### Installation
|
|
21
|
+
|
|
19
22
|
You can install the package via npm:
|
|
20
23
|
|
|
21
24
|
```bash
|
|
22
25
|
npm install @adobe/helix-md2jcr
|
|
23
26
|
```
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
Or use it directly with `npx` without installing:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @adobe/helix-md2jcr path/to/content.md
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Converting Markdown to JCR Nodes
|
|
35
|
+
|
|
36
|
+
The package includes a CLI tool `md2jcr` that converts markdown files to JCR XML format.
|
|
37
|
+
|
|
38
|
+
**Basic usage:**
|
|
39
|
+
```bash
|
|
40
|
+
npx @adobe/helix-md2jcr path/to/content.md
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Convert a single file:**
|
|
44
|
+
```bash
|
|
45
|
+
md2jcr test/fixtures/simple.md
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Convert all markdown files in a directory:**
|
|
49
|
+
```bash
|
|
50
|
+
md2jcr test/fixtures/
|
|
51
|
+
```
|
|
27
52
|
|
|
28
|
-
|
|
53
|
+
**View output in console with verbose flag `-v`:**
|
|
29
54
|
```bash
|
|
30
|
-
|
|
55
|
+
md2jcr test/fixtures/simple.md -v
|
|
31
56
|
```
|
|
32
|
-
|
|
57
|
+
|
|
58
|
+
**View decoded XML output with `-v` and `-d` flags:**
|
|
33
59
|
```bash
|
|
34
|
-
|
|
60
|
+
md2jcr test/fixtures/simple.md -v -d
|
|
35
61
|
```
|
|
36
62
|
|
|
37
|
-
|
|
63
|
+
**Use custom Universal Editor files from a directory:**
|
|
38
64
|
```bash
|
|
39
|
-
|
|
65
|
+
md2jcr content.md -ue path/to/ue-files-directory
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The converter will generate a `.xml` file alongside the markdown file containing the JCR structure. This can be used to check for potential content changes due to conversion.
|
|
69
|
+
|
|
70
|
+
#### Command-Line Options
|
|
71
|
+
|
|
72
|
+
- `-v`, `--verbose` - Print the XML output to the console
|
|
73
|
+
- `-d`, `--decode` - Decode HTML entities in the XML output (use with `-v`)
|
|
74
|
+
- `-ue`, `--ue-files <directory>` - Specify a directory containing Universal Editor configuration files
|
|
75
|
+
|
|
76
|
+
Example directory structure:
|
|
77
|
+
```
|
|
78
|
+
ue-files/
|
|
79
|
+
├── component-models.json
|
|
80
|
+
├── component-definition.json
|
|
81
|
+
└── component-filters.json
|
|
40
82
|
```
|
|
41
83
|
|
|
42
|
-
|
|
43
|
-
|
|
84
|
+
### Programmatic Usage
|
|
85
|
+
|
|
86
|
+
You can also use the library programmatically in your Node.js code:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
import { md2jcr } from '@adobe/helix-md2jcr';
|
|
90
|
+
|
|
91
|
+
const markdown = '# Hello World\n\nThis is a test.';
|
|
92
|
+
const options = {
|
|
93
|
+
models: [...],
|
|
94
|
+
definition: {...},
|
|
95
|
+
filters: [...]
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const xml = await md2jcr(markdown, options);
|
|
99
|
+
console.log(xml);
|
|
100
|
+
```
|
|
44
101
|
|
|
45
102
|
## Baseline XML Files
|
|
46
103
|
Running the ./baseline-tests.sh script will detect any md file under test/fixtures and execute the convert2jcr node script.
|
package/baseline-tests.sh
CHANGED
package/bin/md2jcr.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Copyright 2024 Adobe. All rights reserved.
|
|
5
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
7
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
10
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
11
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
12
|
+
* governing permissions and limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/* eslint-disable no-await-in-loop,no-console */
|
|
16
|
+
import {
|
|
17
|
+
readdir, readFile, stat, writeFile,
|
|
18
|
+
} from 'fs/promises';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
import { decode } from 'entities';
|
|
21
|
+
import { md2jcr } from '../src/index.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Read a JSON file. If the file does not exist, return an empty object.
|
|
25
|
+
* @param {string} filePath The path to the JSON file.
|
|
26
|
+
* @returns {Promise<{}|any>} A promise that resolves to the JSON object in the file,
|
|
27
|
+
*/
|
|
28
|
+
async function readJsonFile(filePath) {
|
|
29
|
+
try {
|
|
30
|
+
if ((await stat(filePath)).isFile()) {
|
|
31
|
+
const models = await readFile(filePath, 'utf-8');
|
|
32
|
+
return JSON.parse(models);
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// ignore the fact that the file doesn't exist
|
|
36
|
+
// console.error(`Error due to: ${error} for file ${filePath}`);
|
|
37
|
+
}
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Convert a markdown file to JCR XML.
|
|
43
|
+
* @param mdFile {string} The path to the markdown file.
|
|
44
|
+
* @param verbose - if true the XML will be printed to the console.
|
|
45
|
+
* @param decodeXML - if true a file with the decoded XML will be created.
|
|
46
|
+
* @param ueFilesDir - optional path to directory containing UE files (models, definitions, filters)
|
|
47
|
+
* @returns {Promise<void>} A promise that resolves when the conversion is
|
|
48
|
+
* complete, or rejects if the file is not a markdown file.
|
|
49
|
+
*/
|
|
50
|
+
async function convert(
|
|
51
|
+
mdFile,
|
|
52
|
+
verbose = false,
|
|
53
|
+
decodeXML = false,
|
|
54
|
+
ueFilesDir = null,
|
|
55
|
+
) {
|
|
56
|
+
if (!mdFile.endsWith('.md')) {
|
|
57
|
+
return Promise.reject(new Error('File must be a markdown file'));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const dir = path.dirname(mdFile);
|
|
61
|
+
const base = path.basename(mdFile, '.md');
|
|
62
|
+
const fileJcrXML = path.resolve(dir, `${base}.xml`);
|
|
63
|
+
|
|
64
|
+
let modelJson;
|
|
65
|
+
let definitionJson;
|
|
66
|
+
let filtersJson;
|
|
67
|
+
|
|
68
|
+
// Use provided UE files directory if specified
|
|
69
|
+
if (ueFilesDir) {
|
|
70
|
+
const ueDir = path.resolve(process.cwd(), ueFilesDir);
|
|
71
|
+
|
|
72
|
+
// Try to load models.json
|
|
73
|
+
const modelsPath = path.resolve(ueDir, 'component-models.json');
|
|
74
|
+
const loadedModels = await readJsonFile(modelsPath);
|
|
75
|
+
modelJson = Array.isArray(loadedModels) ? loadedModels : loadedModels.models;
|
|
76
|
+
|
|
77
|
+
// Try to load definitions.json
|
|
78
|
+
const definitionsPath = path.resolve(ueDir, 'component-definition.json');
|
|
79
|
+
const loadedDefinitions = await readJsonFile(definitionsPath);
|
|
80
|
+
if (loadedDefinitions.groups) {
|
|
81
|
+
definitionJson = loadedDefinitions;
|
|
82
|
+
} else if (loadedDefinitions.definitions) {
|
|
83
|
+
// Wrap definitions in the expected structure
|
|
84
|
+
definitionJson = {
|
|
85
|
+
groups: [
|
|
86
|
+
{
|
|
87
|
+
title: 'Blocks',
|
|
88
|
+
id: 'blocks',
|
|
89
|
+
components: loadedDefinitions.definitions,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
} else {
|
|
94
|
+
definitionJson = loadedDefinitions;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Try to load filters.json
|
|
98
|
+
const filtersPath = path.resolve(ueDir, 'component-filters.json');
|
|
99
|
+
const loadedFilters = await readJsonFile(filtersPath);
|
|
100
|
+
filtersJson = Array.isArray(loadedFilters) ? loadedFilters : loadedFilters.filters;
|
|
101
|
+
} else {
|
|
102
|
+
// Fall back to automatic discovery
|
|
103
|
+
const blockDefinitionsPath = path.resolve(dir, `_${base}.json`);
|
|
104
|
+
|
|
105
|
+
// check to see if the blockFiles exists
|
|
106
|
+
try {
|
|
107
|
+
await stat(blockDefinitionsPath);
|
|
108
|
+
const blockDefinitionFile = await readJsonFile(path.resolve(dir, `_${base}.json`));
|
|
109
|
+
modelJson = blockDefinitionFile.models;
|
|
110
|
+
definitionJson = {
|
|
111
|
+
groups: [
|
|
112
|
+
{
|
|
113
|
+
title: 'Blocks',
|
|
114
|
+
id: 'blocks',
|
|
115
|
+
components: [
|
|
116
|
+
...blockDefinitionFile.definitions,
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
filtersJson = blockDefinitionFile.filters;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
const modelFile = path.resolve(dir, `${base}-models.json`);
|
|
124
|
+
const definitionFile = path.resolve(dir, `${base}-definitions.json`);
|
|
125
|
+
const filtersFile = path.resolve(dir, `${base}-filters.json`);
|
|
126
|
+
modelJson = await readJsonFile(modelFile);
|
|
127
|
+
definitionJson = await readJsonFile(definitionFile);
|
|
128
|
+
filtersJson = await readJsonFile(filtersFile);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const md = await readFile(mdFile, 'utf-8');
|
|
133
|
+
|
|
134
|
+
/** @type {Mdast2JCROptions} */
|
|
135
|
+
const opts = {
|
|
136
|
+
models: modelJson,
|
|
137
|
+
definition: definitionJson,
|
|
138
|
+
filters: filtersJson,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const xml = await md2jcr(md, opts);
|
|
142
|
+
|
|
143
|
+
if (verbose) {
|
|
144
|
+
if (!decodeXML) {
|
|
145
|
+
console.log(xml);
|
|
146
|
+
} else if (decodeXML) {
|
|
147
|
+
console.log(decode(xml));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return writeFile(fileJcrXML, xml);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Parse command-line arguments
|
|
156
|
+
* @returns {object} Parsed arguments
|
|
157
|
+
*/
|
|
158
|
+
function parseArgs() {
|
|
159
|
+
const args = {
|
|
160
|
+
path: null,
|
|
161
|
+
verbose: false,
|
|
162
|
+
decode: false,
|
|
163
|
+
ueFilesDir: null,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
for (let i = 2; i < process.argv.length; i += 1) {
|
|
167
|
+
const arg = process.argv[i];
|
|
168
|
+
|
|
169
|
+
if (arg === '-v' || arg === '--verbose') {
|
|
170
|
+
args.verbose = true;
|
|
171
|
+
} else if (arg === '-d' || arg === '--decode') {
|
|
172
|
+
args.decode = true;
|
|
173
|
+
} else if (arg === '-ue' || arg === '--ue-files') {
|
|
174
|
+
args.ueFilesDir = process.argv[i + 1];
|
|
175
|
+
i += 1;
|
|
176
|
+
} else if (!arg.startsWith('-')) {
|
|
177
|
+
args.path = arg;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return args;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Entry point to convert a markdown file to JCR XML.
|
|
186
|
+
* @param inPath {string} The path to the markdown file or directory containing
|
|
187
|
+
* markdown files.
|
|
188
|
+
* @param verbose {boolean} If true, print output to console
|
|
189
|
+
* @param htmlDecode {boolean} If true, decode HTML entities in output
|
|
190
|
+
* @param ueFilesDir {string|null} Optional path to directory containing UE files
|
|
191
|
+
* @returns {Promise<void>} A promise that resolves when the conversion is
|
|
192
|
+
* complete.
|
|
193
|
+
*/
|
|
194
|
+
export async function run(inPath, verbose, htmlDecode, ueFilesDir) {
|
|
195
|
+
const dirOrFilePath = path.resolve(process.cwd(), inPath);
|
|
196
|
+
|
|
197
|
+
const files = [];
|
|
198
|
+
if ((await stat(dirOrFilePath)).isDirectory()) {
|
|
199
|
+
const items = await readdir(dirOrFilePath);
|
|
200
|
+
items
|
|
201
|
+
.filter((item) => item.endsWith('.md'))
|
|
202
|
+
.forEach((item) => files.push(path.resolve(dirOrFilePath, item)));
|
|
203
|
+
} else {
|
|
204
|
+
files.push(dirOrFilePath);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
for (const file of files) {
|
|
208
|
+
await convert(file, verbose, htmlDecode, ueFilesDir);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const args = parseArgs();
|
|
213
|
+
|
|
214
|
+
run(
|
|
215
|
+
args.path || process.cwd(),
|
|
216
|
+
args.verbose,
|
|
217
|
+
args.decode,
|
|
218
|
+
args.ueFilesDir,
|
|
219
|
+
).catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-md2jcr",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Helix Service that converts markdown to JCR content structure",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"md2jcr": "./bin/md2jcr.js"
|
|
9
|
+
},
|
|
7
10
|
"scripts": {
|
|
8
11
|
"test": "c8 mocha 'test/*.tests.js'",
|
|
9
12
|
"lint": "eslint .",
|
package/src/cli/convert2jcr.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/* eslint-disable no-await-in-loop,no-console */
|
|
14
|
-
import {
|
|
15
|
-
readdir, readFile, stat, writeFile,
|
|
16
|
-
} from 'fs/promises';
|
|
17
|
-
import path from 'path';
|
|
18
|
-
import { decode } from 'entities';
|
|
19
|
-
import { md2jcr } from '../index.js';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Read a JSON file. If the file does not exist, return an empty object.
|
|
23
|
-
* @param {string} filePath The path to the JSON file.
|
|
24
|
-
* @returns {Promise<{}|any>} A promise that resolves to the JSON object in the file,
|
|
25
|
-
*/
|
|
26
|
-
async function readJsonFile(filePath) {
|
|
27
|
-
try {
|
|
28
|
-
if ((await stat(filePath)).isFile()) {
|
|
29
|
-
const models = await readFile(filePath, 'utf-8');
|
|
30
|
-
return JSON.parse(models);
|
|
31
|
-
}
|
|
32
|
-
} catch (error) {
|
|
33
|
-
// ignore the fact that the file doesn't exist
|
|
34
|
-
// console.error(`Error due to: ${error} for file ${filePath}`);
|
|
35
|
-
}
|
|
36
|
-
return {};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Convert a markdown file to JCR XML.
|
|
41
|
-
* @param mdFile {string} The path to the markdown file.
|
|
42
|
-
* @param verbose - if true the XML will be printed to the console.
|
|
43
|
-
* @param decodeXML - if true a file with the decoded XML will be created.
|
|
44
|
-
* @returns {Promise<void>} A promise that resolves when the conversion is
|
|
45
|
-
* complete, or rejects if the file is not a markdown file.
|
|
46
|
-
*/
|
|
47
|
-
async function convert(mdFile, verbose = false, decodeXML = false) {
|
|
48
|
-
if (!mdFile.endsWith('.md')) {
|
|
49
|
-
return Promise.reject(new Error('File must be a markdown file'));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const dir = path.dirname(mdFile);
|
|
53
|
-
const base = path.basename(mdFile, '.md');
|
|
54
|
-
const fileJcrXML = path.resolve(dir, `${base}.xml`);
|
|
55
|
-
|
|
56
|
-
let modelJson;
|
|
57
|
-
let definitionJson;
|
|
58
|
-
let filtersJson;
|
|
59
|
-
|
|
60
|
-
const blockDefinitionsPath = path.resolve(dir, `_${base}.json`);
|
|
61
|
-
|
|
62
|
-
// check to see if the blockFiles exists
|
|
63
|
-
try {
|
|
64
|
-
await stat(blockDefinitionsPath);
|
|
65
|
-
const blockDefinitionFile = await readJsonFile(path.resolve(dir, `_${base}.json`));
|
|
66
|
-
modelJson = blockDefinitionFile.models;
|
|
67
|
-
definitionJson = {
|
|
68
|
-
groups: [
|
|
69
|
-
{
|
|
70
|
-
title: 'Blocks',
|
|
71
|
-
id: 'blocks',
|
|
72
|
-
components: [
|
|
73
|
-
...blockDefinitionFile.definitions,
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
};
|
|
78
|
-
filtersJson = blockDefinitionFile.filters;
|
|
79
|
-
} catch (err) {
|
|
80
|
-
const modelFile = path.resolve(dir, `${base}-models.json`);
|
|
81
|
-
const definitionFile = path.resolve(dir, `${base}-definitions.json`);
|
|
82
|
-
const filtersFile = path.resolve(dir, `${base}-filters.json`);
|
|
83
|
-
modelJson = await readJsonFile(modelFile);
|
|
84
|
-
definitionJson = await readJsonFile(definitionFile);
|
|
85
|
-
filtersJson = await readJsonFile(filtersFile);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const md = await readFile(mdFile, 'utf-8');
|
|
89
|
-
|
|
90
|
-
/** @type {Mdast2JCROptions} */
|
|
91
|
-
const opts = {
|
|
92
|
-
models: modelJson,
|
|
93
|
-
definition: definitionJson,
|
|
94
|
-
filters: filtersJson,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const xml = await md2jcr(md, opts);
|
|
98
|
-
|
|
99
|
-
if (verbose) {
|
|
100
|
-
if (!decodeXML) {
|
|
101
|
-
console.log(xml);
|
|
102
|
-
} else if (decodeXML) {
|
|
103
|
-
console.log(decode(xml));
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return writeFile(fileJcrXML, xml);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Entry point to convert a markdown file to JCR XML.
|
|
112
|
-
* @param inPath {string} The path to the markdown file or directory containing
|
|
113
|
-
* markdown files.
|
|
114
|
-
* @returns {Promise<void>} A promise that resolves when the conversion is
|
|
115
|
-
* complete.
|
|
116
|
-
*/
|
|
117
|
-
async function run(inPath) {
|
|
118
|
-
const dirOrFilePath = path.resolve(process.cwd(), inPath);
|
|
119
|
-
|
|
120
|
-
const files = [];
|
|
121
|
-
if ((await stat(dirOrFilePath)).isDirectory()) {
|
|
122
|
-
const items = await readdir(dirOrFilePath);
|
|
123
|
-
items
|
|
124
|
-
.filter((item) => item.endsWith('.md'))
|
|
125
|
-
.forEach((item) => files.push(path.resolve(dirOrFilePath, item)));
|
|
126
|
-
} else {
|
|
127
|
-
files.push(dirOrFilePath);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
for (const file of files) {
|
|
131
|
-
await convert(file, process.argv.includes('-v'), process.argv.includes('-d'));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
run(process.argv[2] || process.cwd()).catch(console.error);
|