@forsakringskassan/docs-generator 2.12.0 → 2.14.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.
- package/README.md +28 -8
- package/dist/compile-example.js +3 -3
- package/dist/{create-markdown-renderer-D5z4jt-T.js → create-markdown-renderer-DVss8WXD.js} +240 -4
- package/dist/index.d.ts +26 -7
- package/dist/index.js +170 -201
- package/dist/markdown.js +6 -4
- package/dist/{vendor-CJBsNZrh.js → vendor-Bb38Rlio.js} +48 -48
- package/dist/{vue3-rkJOanAd.js → vue3-BqgRpcI0.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,10 +11,17 @@ npm install --save-dev --save-exact @forsakringskassan/docs-generator
|
|
|
11
11
|
You can start a development server with watch for incremental builds using `.serve()`.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
+
import {
|
|
15
|
+
Generator,
|
|
16
|
+
livereloadProcessor,
|
|
17
|
+
} from "@forsakringskassan/docs-generator";
|
|
18
|
+
|
|
14
19
|
const docs = new Generator({
|
|
15
|
-
|
|
20
|
+
site: {
|
|
21
|
+
name: "My Awesome Site",
|
|
22
|
+
},
|
|
23
|
+
setupPath: "docs/src/setup.ts",
|
|
16
24
|
processors: [livereloadProcessor({ enabled: true })],
|
|
17
|
-
/* ... */
|
|
18
25
|
});
|
|
19
26
|
|
|
20
27
|
docs.build([
|
|
@@ -29,8 +36,17 @@ docs.serve();
|
|
|
29
36
|
Vendor alias is optional, it lets you substitute one package for another when bundling. The example below substitutes the package `vue` with the package `vue/dist/esm.bundle.js`. When an alias is given the package can be imported using the given alias as well as the original package name. For instance, when using the following configuration "vue" can be imported and resolved as "vue/dist/esm.bundle.js".
|
|
30
37
|
|
|
31
38
|
```ts
|
|
39
|
+
import {
|
|
40
|
+
Generator,
|
|
41
|
+
livereloadProcessor,
|
|
42
|
+
} from "@forsakringskassan/docs-generator";
|
|
43
|
+
|
|
32
44
|
const docs = new Generator({
|
|
33
|
-
|
|
45
|
+
site: {
|
|
46
|
+
name: "My Awesome Site",
|
|
47
|
+
},
|
|
48
|
+
setupPath: "docs/src/setup.ts",
|
|
49
|
+
|
|
34
50
|
vendor: [
|
|
35
51
|
{
|
|
36
52
|
package: "vue",
|
|
@@ -39,7 +55,6 @@ const docs = new Generator({
|
|
|
39
55
|
alias: "vue/dist/esm.bundle.js",
|
|
40
56
|
},
|
|
41
57
|
],
|
|
42
|
-
/* ... */
|
|
43
58
|
});
|
|
44
59
|
```
|
|
45
60
|
|
|
@@ -55,7 +70,7 @@ npm install --save-dev --save-exact @vue/component-compiler
|
|
|
55
70
|
|
|
56
71
|
Create the `setup` callback in `docs/src/setup.ts`:
|
|
57
72
|
|
|
58
|
-
```ts
|
|
73
|
+
```ts nocompile
|
|
59
74
|
import Vue from "vue";
|
|
60
75
|
import { type SetupOptions } from "@forsakringskassan/docs-generator";
|
|
61
76
|
|
|
@@ -73,7 +88,7 @@ export function setup(options: SetupOptions): void {
|
|
|
73
88
|
|
|
74
89
|
Create the `setup` callback in `docs/src/setup.ts`:
|
|
75
90
|
|
|
76
|
-
```ts
|
|
91
|
+
```ts nocompile
|
|
77
92
|
import { createApp } from "vue";
|
|
78
93
|
import { type SetupOptions } from "@forsakringskassan/docs-generator";
|
|
79
94
|
|
|
@@ -102,8 +117,13 @@ Three CSS files are provided:
|
|
|
102
117
|
Style can be compiled with `compileStyle(name, src, [options])`:
|
|
103
118
|
|
|
104
119
|
```ts
|
|
120
|
+
import { Generator } from "@forsakringskassan/docs-generator";
|
|
121
|
+
|
|
105
122
|
const docs = new Generator({
|
|
106
|
-
|
|
123
|
+
site: {
|
|
124
|
+
name: "My Awesome Site",
|
|
125
|
+
},
|
|
126
|
+
setupPath: "docs/src/setup.ts",
|
|
107
127
|
});
|
|
108
128
|
|
|
109
129
|
docs.compileStyle("docs", "./docs/src/style.scss", {
|
|
@@ -274,7 +294,7 @@ Defaults to `@fkui/icon-lib-default`.
|
|
|
274
294
|
Makes it possible to dynamically load icons and get access to icon metadata.
|
|
275
295
|
The library must have been built using `@fkui/icon-lib-builder`.
|
|
276
296
|
|
|
277
|
-
```js
|
|
297
|
+
```js nocompile
|
|
278
298
|
const icons = await import(process.env.DOCS_ICON_LIB);
|
|
279
299
|
|
|
280
300
|
for (const entry of Object.values(icons)) {
|
package/dist/compile-example.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
var path$1 = require('node:path');
|
|
4
4
|
var esbuild = require('esbuild');
|
|
5
5
|
var vue = require('vue');
|
|
6
|
-
var vue3 = require('./vue3-
|
|
6
|
+
var vue3 = require('./vue3-BqgRpcI0.js');
|
|
7
7
|
var path = require('node:path/posix');
|
|
8
8
|
require('@vue/compiler-sfc');
|
|
9
|
-
require('./vendor-
|
|
9
|
+
require('./vendor-Bb38Rlio.js');
|
|
10
10
|
require('node:url');
|
|
11
11
|
require('fs');
|
|
12
12
|
require('node:fs');
|
|
@@ -14,6 +14,7 @@ require('node:fs/promises');
|
|
|
14
14
|
require('node:events');
|
|
15
15
|
require('node:stream');
|
|
16
16
|
require('node:string_decoder');
|
|
17
|
+
require('typescript');
|
|
17
18
|
require('constants');
|
|
18
19
|
require('stream');
|
|
19
20
|
require('util');
|
|
@@ -25,7 +26,6 @@ require('node:process');
|
|
|
25
26
|
require('node:util');
|
|
26
27
|
require('node:child_process');
|
|
27
28
|
require('node:stream/promises');
|
|
28
|
-
require('typescript');
|
|
29
29
|
require('fs/promises');
|
|
30
30
|
require('os');
|
|
31
31
|
require('http');
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var vendor = require('./vendor-
|
|
3
|
+
var vendor = require('./vendor-Bb38Rlio.js');
|
|
4
4
|
var path = require('node:path/posix');
|
|
5
5
|
var path$1 = require('node:path');
|
|
6
6
|
require('crypto');
|
|
7
7
|
var crypto = require('node:crypto');
|
|
8
8
|
require('node:child_process');
|
|
9
|
+
var fs = require('node:fs');
|
|
10
|
+
var vue = require('vue');
|
|
11
|
+
var vue3 = require('./vue3-BqgRpcI0.js');
|
|
9
12
|
|
|
10
13
|
function findDocument(haystack, needle) {
|
|
11
14
|
const match = haystack.find((it) => {
|
|
@@ -65,6 +68,236 @@ function getOutputFilePath(outputFolder, fileInfo) {
|
|
|
65
68
|
return normalizePath(outputFolder, path, outputName);
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
function parseImport(raw) {
|
|
72
|
+
const comments = [];
|
|
73
|
+
const stripped = raw.replace(/<!--.*?-->/gms, (match) => {
|
|
74
|
+
comments.push(match);
|
|
75
|
+
return "";
|
|
76
|
+
});
|
|
77
|
+
const filename = stripped.trim();
|
|
78
|
+
const extension = path$1.parse(filename).ext.slice(1);
|
|
79
|
+
return {
|
|
80
|
+
filename,
|
|
81
|
+
extension,
|
|
82
|
+
comments
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getExampleImport(searchDirs, filename) {
|
|
87
|
+
const pattern = searchDirs.map((dir) => `${dir}/**/${filename}`);
|
|
88
|
+
const matches = vendor.globSync(pattern);
|
|
89
|
+
if (matches.length === 0) {
|
|
90
|
+
const message = `No files matched import "${filename}"`;
|
|
91
|
+
throw new Error(message);
|
|
92
|
+
} else if (matches.length > 1) {
|
|
93
|
+
const message = `Multiple files matched import "${filename}"`;
|
|
94
|
+
throw new Error(message);
|
|
95
|
+
} else {
|
|
96
|
+
return normalizePath(matches[0]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getExampleName(filename) {
|
|
101
|
+
return path$1.parse(filename).name;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function removeLinesInline(lines, { begin, end }) {
|
|
105
|
+
for (let i = begin; i <= end; i++) {
|
|
106
|
+
lines[i] = "";
|
|
107
|
+
}
|
|
108
|
+
if (lines[begin - 1] === "\n") {
|
|
109
|
+
lines[begin - 1] = "";
|
|
110
|
+
begin--;
|
|
111
|
+
}
|
|
112
|
+
if (lines[end + 1] === "\n") {
|
|
113
|
+
lines[end + 1] = "";
|
|
114
|
+
}
|
|
115
|
+
if (end === lines.length - 1 && begin > 0) {
|
|
116
|
+
lines[begin - 1] = lines[begin - 1].slice(0, -1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function cutSnippets(code) {
|
|
120
|
+
const lines = code.split(/\n/).map((it, index, lines2) => index < lines2.length - 1 ? `${it}
|
|
121
|
+
` : it);
|
|
122
|
+
const directive = /\/\* +--- +cut (above|below|begin|end) +--- +\*\//;
|
|
123
|
+
let buffer = -1;
|
|
124
|
+
lines.forEach((line, index) => {
|
|
125
|
+
const match = line.match(directive);
|
|
126
|
+
const [, instruction] = match ?? ["", null];
|
|
127
|
+
if (!instruction) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
switch (instruction) {
|
|
131
|
+
/* --- cut above --- */
|
|
132
|
+
case "above":
|
|
133
|
+
removeLinesInline(lines, {
|
|
134
|
+
begin: 0,
|
|
135
|
+
end: index
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
/* --- cut below --- */
|
|
139
|
+
case "below":
|
|
140
|
+
removeLinesInline(lines, {
|
|
141
|
+
begin: index,
|
|
142
|
+
end: lines.length - 1
|
|
143
|
+
});
|
|
144
|
+
break;
|
|
145
|
+
/* --- cut begin --- */
|
|
146
|
+
case "begin":
|
|
147
|
+
if (buffer === -1) {
|
|
148
|
+
buffer = index;
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
/* --- cut end --- */
|
|
152
|
+
case "end":
|
|
153
|
+
removeLinesInline(lines, {
|
|
154
|
+
begin: Math.max(buffer, 0),
|
|
155
|
+
end: index
|
|
156
|
+
});
|
|
157
|
+
buffer = -1;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
if (buffer >= 0) {
|
|
162
|
+
removeLinesInline(lines, {
|
|
163
|
+
begin: buffer,
|
|
164
|
+
end: lines.length - 1
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return lines.join("");
|
|
168
|
+
}
|
|
169
|
+
function stripEslintComments(code) {
|
|
170
|
+
const matchLine = /^[ \t]*(\/\* eslint-disable[^*]*\*\/|\/\/ eslint-disable.*)\n/gm;
|
|
171
|
+
const matchEmbedded = /[ \t]*(\/\* eslint-disable[^*]*\*\/|\/\/ eslint-disable.*)/g;
|
|
172
|
+
return code.replace(matchLine, "").replace(matchEmbedded, "");
|
|
173
|
+
}
|
|
174
|
+
function maybeDedent(value) {
|
|
175
|
+
if (/^\s*$/.test(value)) {
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
if (/^\s/.test(value)) {
|
|
179
|
+
return vendor.dedent(value);
|
|
180
|
+
} else {
|
|
181
|
+
return value;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const transformations = {
|
|
185
|
+
javascript: [cutSnippets, stripEslintComments, maybeDedent],
|
|
186
|
+
typescript: [cutSnippets, stripEslintComments, maybeDedent]
|
|
187
|
+
};
|
|
188
|
+
function transformCode(code, lang) {
|
|
189
|
+
const fns = transformations[lang] ?? [];
|
|
190
|
+
for (const fn of fns) {
|
|
191
|
+
code = fn(code);
|
|
192
|
+
}
|
|
193
|
+
return code;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const vueMajor = parseInt(vue.version.split(".", 2)[0], 10);
|
|
197
|
+
function vueGenerator() {
|
|
198
|
+
switch (vueMajor) {
|
|
199
|
+
case 2:
|
|
200
|
+
throw new Error(
|
|
201
|
+
"Vue 2 is no longer supported, upgrade to Vue 3 or downgrade docs-generator"
|
|
202
|
+
);
|
|
203
|
+
case 3:
|
|
204
|
+
return vue3.generateCode;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function generateExample(options) {
|
|
208
|
+
const { language } = options;
|
|
209
|
+
if (language === "import") {
|
|
210
|
+
const parsed = parseImport(options.source);
|
|
211
|
+
const filename = getExampleImport(
|
|
212
|
+
options.exampleFolders,
|
|
213
|
+
parsed.filename
|
|
214
|
+
);
|
|
215
|
+
const language2 = parsed.extension;
|
|
216
|
+
const comments = parsed.comments;
|
|
217
|
+
const content = fs.readFileSync(filename, "utf-8");
|
|
218
|
+
const source = transformCode(content, language2);
|
|
219
|
+
const example = generateExample({
|
|
220
|
+
...options,
|
|
221
|
+
source,
|
|
222
|
+
language: language2,
|
|
223
|
+
filename
|
|
224
|
+
});
|
|
225
|
+
return { ...example, comments };
|
|
226
|
+
}
|
|
227
|
+
switch (language) {
|
|
228
|
+
case "vue":
|
|
229
|
+
return generateVueExample(options);
|
|
230
|
+
case "html":
|
|
231
|
+
return generateStaticExample(options);
|
|
232
|
+
default:
|
|
233
|
+
return generateStaticExample(options);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function generateVueExample(options) {
|
|
237
|
+
const { filename, source, parent, setupPath, tags } = options;
|
|
238
|
+
const fn = vueGenerator();
|
|
239
|
+
const slug = getExampleName(filename);
|
|
240
|
+
const fingerprint = getFingerprint(source);
|
|
241
|
+
const { markup, sourcecode, output } = fn({
|
|
242
|
+
filename,
|
|
243
|
+
slug,
|
|
244
|
+
fingerprint,
|
|
245
|
+
code: source,
|
|
246
|
+
setupPath
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
source,
|
|
250
|
+
language: options.language,
|
|
251
|
+
comments: [],
|
|
252
|
+
tags,
|
|
253
|
+
markup,
|
|
254
|
+
output,
|
|
255
|
+
runtime: true,
|
|
256
|
+
task: {
|
|
257
|
+
outputFile: output,
|
|
258
|
+
sourcecode,
|
|
259
|
+
sourceFile: filename,
|
|
260
|
+
parent
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function generateStaticExample(options) {
|
|
265
|
+
const { filename, source, language, tags } = options;
|
|
266
|
+
const slug = getExampleName(filename);
|
|
267
|
+
const fingerprint = getFingerprint(source);
|
|
268
|
+
const asset = `${slug}-${fingerprint}.${language}`;
|
|
269
|
+
const runtimeLanguages = ["html"];
|
|
270
|
+
const runtime = runtimeLanguages.includes(language);
|
|
271
|
+
return {
|
|
272
|
+
source,
|
|
273
|
+
language: options.language,
|
|
274
|
+
comments: [],
|
|
275
|
+
tags,
|
|
276
|
+
markup: source,
|
|
277
|
+
output: runtime ? asset : null,
|
|
278
|
+
runtime,
|
|
279
|
+
task: null
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function normalizeLanguage(lang) {
|
|
284
|
+
switch (lang) {
|
|
285
|
+
case "ts":
|
|
286
|
+
return "typescript";
|
|
287
|
+
case "js":
|
|
288
|
+
return "javascript";
|
|
289
|
+
default:
|
|
290
|
+
return lang;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function parseInfostring(infostring) {
|
|
294
|
+
const [rawLanguage, ...rawTags] = infostring.trim().split(/\s+/);
|
|
295
|
+
return {
|
|
296
|
+
language: normalizeLanguage(rawLanguage),
|
|
297
|
+
tags: rawTags
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
68
301
|
class SoftError extends Error {
|
|
69
302
|
code;
|
|
70
303
|
details;
|
|
@@ -274,16 +507,17 @@ function codePreview(options) {
|
|
|
274
507
|
};
|
|
275
508
|
function fence(_md, tokens, idx, _options, env) {
|
|
276
509
|
const { fileInfo } = env;
|
|
277
|
-
const { content:
|
|
278
|
-
const
|
|
510
|
+
const { content: rawSource, info, map } = tokens[idx];
|
|
511
|
+
const { language, tags: rawTags } = parseInfostring(info);
|
|
279
512
|
if (language === "mermaid") {
|
|
280
513
|
return (
|
|
281
514
|
/* HTML */
|
|
282
515
|
`
|
|
283
|
-
<pre class="mermaid">${htmlencode(
|
|
516
|
+
<pre class="mermaid">${htmlencode(rawSource)}</pre>
|
|
284
517
|
`
|
|
285
518
|
);
|
|
286
519
|
}
|
|
520
|
+
const source = transformCode(rawSource, language);
|
|
287
521
|
const example = generateExample({
|
|
288
522
|
source,
|
|
289
523
|
language,
|
|
@@ -774,7 +1008,9 @@ function createMarkdownRenderer(options) {
|
|
|
774
1008
|
|
|
775
1009
|
exports.SoftError = SoftError;
|
|
776
1010
|
exports.createMarkdownRenderer = createMarkdownRenderer;
|
|
1011
|
+
exports.generateExample = generateExample;
|
|
777
1012
|
exports.generateId = generateId;
|
|
778
1013
|
exports.getFingerprint = getFingerprint;
|
|
779
1014
|
exports.getOutputFilePath = getOutputFilePath;
|
|
780
1015
|
exports.normalizePath = normalizePath;
|
|
1016
|
+
exports.parseInfostring = parseInfostring;
|
package/dist/index.d.ts
CHANGED
|
@@ -112,6 +112,23 @@ export declare interface DocumentOutlineEntry {
|
|
|
112
112
|
subheadings: DocumentOutline;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Options for `extractExamplesProcessor`.
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
*/
|
|
120
|
+
export declare interface ExtractExamplesOptions extends ProcessorOptions {
|
|
121
|
+
outputFolder: string;
|
|
122
|
+
languages?: string[];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Processor to extract and write examples to separate files.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
130
|
+
export declare function extractExamplesProcessor(options: ExtractExamplesOptions): Processor;
|
|
131
|
+
|
|
115
132
|
/**
|
|
116
133
|
* @public
|
|
117
134
|
*/
|
|
@@ -199,10 +216,12 @@ export { Generator_2 as Generator }
|
|
|
199
216
|
export declare interface GeneratorOptions {
|
|
200
217
|
/** Site options */
|
|
201
218
|
site: GeneratorSiteOptions;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
|
|
219
|
+
/** Output folder. Default: `public` */
|
|
220
|
+
outputFolder?: string;
|
|
221
|
+
/** Where cached content is stored. Default: `temp/docs` */
|
|
222
|
+
cacheFolder?: string;
|
|
223
|
+
/** List of folders to search when locating examples (searched recursively). Default: `[]` */
|
|
224
|
+
exampleFolders?: string[];
|
|
206
225
|
/** List of folders to search when locating templates. */
|
|
207
226
|
templateFolders?: string[];
|
|
208
227
|
/** List of extra processors to run */
|
|
@@ -216,11 +235,11 @@ export declare interface GeneratorOptions {
|
|
|
216
235
|
/**
|
|
217
236
|
* Options for markdown renderer.
|
|
218
237
|
*/
|
|
219
|
-
markdown
|
|
238
|
+
markdown?: {
|
|
220
239
|
/**
|
|
221
240
|
* Options for markdown messagebox container.
|
|
222
241
|
*/
|
|
223
|
-
messagebox
|
|
242
|
+
messagebox?: {
|
|
224
243
|
/**
|
|
225
244
|
* Default titles for messageboxes.
|
|
226
245
|
*
|
|
@@ -345,7 +364,7 @@ export declare interface MOTDOptions {
|
|
|
345
364
|
*
|
|
346
365
|
* @public
|
|
347
366
|
*/
|
|
348
|
-
export declare function motdProcessor(options
|
|
367
|
+
export declare function motdProcessor(options?: MOTDOptions): Processor;
|
|
349
368
|
|
|
350
369
|
/**
|
|
351
370
|
* Read a JSON file with arbitrary navigation entries.
|