1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | const yargs = require('yargs');
|
14 | const nodepath = require('path');
|
15 |
|
16 | const fs = require('fs');
|
17 | const readdirp = require('readdirp');
|
18 | const logger = require('@adobe/helix-log');
|
19 | const {
|
20 | iter, pipe, filter, map, obj,
|
21 | } = require('ferrum');
|
22 | const npath = require('path');
|
23 | const { i18nConfig } = require('es2015-i18n-tag');
|
24 | const traverse = require('./traverseSchema');
|
25 | const build = require('./markdownBuilder');
|
26 | const { writereadme, writemarkdown } = require('./writeMarkdown');
|
27 | const readme = require('./readmeBuilder');
|
28 | const { loader } = require('./schemaProxy');
|
29 | const { writeSchema } = require('./writeSchema');
|
30 |
|
31 | const { info, error, debug } = logger;
|
32 |
|
33 | async function main(args) {
|
34 |
|
35 | const { argv } = yargs(args)
|
36 | .usage('Generate Markdown documentation from JSON Schema.\n\nUsage: $0')
|
37 |
|
38 | .demand('d')
|
39 | .alias('d', 'input')
|
40 | .describe('d', 'path to directory containing all JSON Schemas or a single JSON Schema file. This will be considered as the baseURL. By default only files ending in .schema.json will be processed, unless the schema-extension is set with the -e flag.')
|
41 | .coerce('d', (d) => {
|
42 | const resolved = nodepath.resolve(d);
|
43 | if (fs.existsSync(resolved) && fs.lstatSync(d).isDirectory()) {
|
44 | return resolved;
|
45 | }
|
46 | throw new Error(`Input file "${d}" is not a directory!`);
|
47 | })
|
48 |
|
49 | .alias('o', 'out')
|
50 | .describe('o', 'path to output directory')
|
51 | .default('o', nodepath.resolve(nodepath.join('.', 'out')))
|
52 | .coerce('o', (o) => nodepath.resolve(o))
|
53 |
|
54 | .option('m', {
|
55 | type: 'array',
|
56 | })
|
57 | .alias('m', 'meta')
|
58 | .describe('m', 'add metadata elements to .md files Eg -m template=reference. Multiple values can be added by repeating the flag Eg: -m template=reference -m hide-nav=true')
|
59 | .coerce('m', (m) => pipe(
|
60 |
|
61 | iter(m),
|
62 | map((i) => i.split('=')),
|
63 | obj,
|
64 | ))
|
65 |
|
66 | .alias('x', 'schema-out')
|
67 | .describe('x', 'output JSON Schema files including description and validated examples in the specified folder, or suppress with -')
|
68 | .default('x', nodepath.resolve(nodepath.join('.', 'out')))
|
69 | .coerce('x', (x) => (x === '-' ? '-' : nodepath.resolve(x)))
|
70 |
|
71 | .alias('e', 'schema-extension')
|
72 | .describe('e', 'JSON Schema file extension eg. schema.json or json')
|
73 | .default('e', 'schema.json')
|
74 |
|
75 | .alias('n', 'no-readme')
|
76 | .describe('n', 'Do not generate a README.md file in the output directory')
|
77 |
|
78 | .describe('link-*', 'Add this file as a link the explain the * attribute, e.g. --link-abstract=abstract.md')
|
79 |
|
80 | .alias('i', 'i18n')
|
81 | .describe('i', 'path to a locales folder with JSON files')
|
82 | .default('i', nodepath.resolve(__dirname, 'locales'))
|
83 | .coerce('i', (i) => nodepath.resolve(i))
|
84 |
|
85 | .alias('l', 'language')
|
86 | .describe('l', 'the selected language')
|
87 | .choices('l', ['en_US', 'de'])
|
88 | .default('l', 'en_US')
|
89 |
|
90 | .alias('f', 'example-format')
|
91 | .describe('f', 'how to format examples')
|
92 | .choices('f', ['json', 'yaml'])
|
93 | .default('f', 'json')
|
94 |
|
95 | .alias('p', 'properties')
|
96 | .array('p')
|
97 | .describe('p', 'name of a custom property which should be also in the description of an element (may be used multiple times)')
|
98 | .default('p', [])
|
99 | .alias('h', 'header')
|
100 | .boolean('h')
|
101 | .describe('h', 'if the value is false the header will be skipped')
|
102 | .default('h', true)
|
103 |
|
104 | .alias('s', 'skip')
|
105 | .array('s')
|
106 | .describe('s', 'name of a default property to skip in markdown (may be used multiple times), e.g. -s typefact -s proptable')
|
107 | .default('s', []);
|
108 |
|
109 | const docs = pipe(
|
110 | iter(argv),
|
111 | filter(([key, _value]) => key.startsWith('link-')),
|
112 | map(([key, value]) => [key.substr(5), value]),
|
113 | obj,
|
114 | );
|
115 |
|
116 | const schemaPath = argv.d;
|
117 | const schemaExtension = argv.e;
|
118 |
|
119 |
|
120 | i18nConfig(require(nodepath.resolve(argv.i, `${argv.l}.json`)));
|
121 |
|
122 | const schemaloader = loader();
|
123 |
|
124 |
|
125 | const schemafiles = await readdirp.promise(schemaPath, { root: schemaPath, fileFilter: `*.${schemaExtension}` });
|
126 |
|
127 | console.log(`loading ${schemafiles.length} schemas`);
|
128 |
|
129 |
|
130 | const loadedschemas = pipe(
|
131 | schemafiles,
|
132 | map((schema) => schema.fullPath),
|
133 |
|
134 | map((path) => schemaloader(require(path), path)),
|
135 |
|
136 | traverse,
|
137 | );
|
138 |
|
139 | if (argv.x !== '-') {
|
140 | console.log('writing schemas');
|
141 | writeSchema({
|
142 | schemadir: argv.x,
|
143 | origindir: argv.d,
|
144 | })(loadedschemas);
|
145 | }
|
146 |
|
147 | if (!argv.n) {
|
148 | console.log('writing README');
|
149 | pipe(
|
150 | loadedschemas,
|
151 |
|
152 | readme({
|
153 | readme: !argv.n,
|
154 | }),
|
155 |
|
156 | writereadme({
|
157 | readme: !argv.n,
|
158 | out: argv.o,
|
159 | info,
|
160 | error,
|
161 | debug,
|
162 | meta: argv.m,
|
163 | }),
|
164 | );
|
165 | }
|
166 |
|
167 | console.log('writing documentation');
|
168 | pipe(
|
169 | loadedschemas,
|
170 |
|
171 | build({
|
172 | header: argv.h,
|
173 | links: docs,
|
174 | includeproperties: argv.p,
|
175 | exampleformat: argv.f,
|
176 | skipproperties: argv.s,
|
177 | rewritelinks: (origin) => {
|
178 | const mddir = argv.o;
|
179 | const srcdir = argv.d;
|
180 | const schemadir = argv.x !== '-' ? argv.x : argv.d;
|
181 |
|
182 | const target = npath.relative(
|
183 | mddir,
|
184 | npath.resolve(schemadir, npath.relative(srcdir, origin)),
|
185 | ).split(npath.sep).join(npath.posix.sep);
|
186 | return target;
|
187 | },
|
188 | }),
|
189 |
|
190 |
|
191 |
|
192 | writemarkdown({
|
193 | out: argv.o,
|
194 | info,
|
195 | error,
|
196 | debug,
|
197 | meta: argv.m,
|
198 | }),
|
199 | );
|
200 |
|
201 | return 1;
|
202 | }
|
203 |
|
204 | module.exports = main;
|