-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathdocgen.mjs
180 lines (149 loc) · 5.52 KB
/
docgen.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// @ts-check
import fs from 'fs';
// @ts-expect-error — Untyped npm package
import jsdoc from 'jsdoc-api';
// Fill this in to test a response locally, with fetching.
const STUB = ``; // fs.readFileSync('/PATH/TO/MONOREPO/astro/packages/astro/src/types/public/config.ts', {encoding: 'utf-8'});
const HEADER = `---
# NOTE: This file is auto-generated from 'scripts/docgen.mjs'
# Do not make edits to it directly, they will be overwritten.
# Instead, change this file: https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/config.ts
# Translators, please remove this note and the <DontEditWarning/> component.
title: Configuration Reference
i18nReady: true
githubURL: https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/config.ts
---
import Since from '~/components/Since.astro'
import DontEditWarning from '~/components/DontEditWarning.astro'
<DontEditWarning />
The following reference covers all supported configuration options in Astro. To learn more about configuring Astro, read our guide on [Configuring Astro](/en/guides/configuring-astro/).
\`\`\`js
// astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
// your configuration options here...
})
\`\`\`
`;
const FOOTER = ``;
/**
* The simple demo does not rely on the TypeScript compiler API; instead, it parses the
* source file directly. It uses the default parser configuration.
*/
export async function run() {
const sourceBranch = process.env.SOURCE_BRANCH || 'main';
const sourceRepo = process.env.SOURCE_REPO || 'withastro/astro';
let task = 'Fetch `src/types/public/config.ts` from ' + sourceRepo + '#' + sourceBranch;
console.time(task);
const inputBuffer =
STUB ||
(await fetch(
`https://raw.githubusercontent.com/${sourceRepo}/${sourceBranch}/packages/astro/src/types/public/config.ts`
).then((r) => r.text()));
console.timeEnd(task);
task = 'Parse types and generate configuration reference';
console.time(task);
// Get all `@docs` JSDoc comments in the file.
const allComments = [
...inputBuffer.matchAll(/\/\*\*\s*\n([^*]|\*[^/])*@docs([^*]|\*[^/])*\*\//g),
];
const allCommentsInput = allComments
.map((m) => m[0])
.filter((c) => c.includes('* @docs'))
.join('\n\n');
const allParsedComments = (await jsdoc.explain({ source: allCommentsInput })).filter(
(/** @type {any} */ data) => data.tags
);
let result = ``;
for (const comment of allParsedComments) {
if (!comment.name) {
throw new Error(`Missing @docs JSDoc tag: @name`);
}
result += [
getHeading(comment),
getDeprecatedAside(comment.deprecated),
getCommentProperties(comment),
comment.description?.trim() || undefined,
comment.see
? `**See Also:**\n${comment.see.map((/** @type {any} */ s) => `- ${s}`.trim()).join('\n')}`
: undefined,
`\n`,
]
.filter((l) => l !== undefined)
.join('\n');
}
// Make any links to docs relative instead of absolute.
result = result.replace(/https:\/\/docs\.astro\.build\//g, '/');
console.timeEnd(task);
task = 'Update configuration-reference.mdx';
console.time(task);
fs.writeFileSync(
'src/content/docs/en/reference/configuration-reference.mdx',
HEADER + result + FOOTER,
'utf8'
);
console.timeEnd(task);
}
/**
* Create a string of ### to create a Markdown heading for the given level.
* @param {number} headingLevel
*/
function h(headingLevel) {
return Array.from({ length: headingLevel }).fill('#').join('');
}
/**
* Get a Markdown heading of the correct level for this comment.
* @param {{ kind: string | undefined; longname: string }} comment
*/
function getHeading(comment) {
let headingLevel = 3;
const headingMatches = /^h(1|2|3|4|5|6)$/.exec(comment.kind || '');
if (headingMatches) {
headingLevel = parseInt(headingMatches[1]);
} else if (comment.kind === 'heading') {
headingLevel = 2;
}
return `${h(headingLevel)} ${comment.longname}\n`;
}
/**
* Get a `:::caution` block if the passed tag is deprecated.
* @param {string | undefined} tag
*/
function getDeprecatedAside(tag) {
if (!tag) return undefined;
return [
'',
':::caution[Deprecated]',
typeof tag === 'string' ? tag : 'This option is deprecated.',
':::',
'',
].join('\n');
}
/**
* Get block of type, CLI command, default value, and version added in for the current comment.
* @param {{ tags: { title: string; text: string }[]; kind: string; type?: { names: string [] }; defaultvalue?: string; version?: string }} comment
*/
function getCommentProperties(comment) {
const cliFlag = comment.tags.find((f) => f.title === 'cli');
const typerawFlag = comment.tags.find((f) => f.title === 'typeraw');
if (comment.kind !== 'heading' && !comment.type && !typerawFlag) {
throw new Error(`Missing @docs JSDoc tag: @type or @typeraw`);
}
const typesFormatted = (
typerawFlag ? typerawFlag.text.replace(/\{(.*)\}/, '$1') : comment.type?.names.join(' | ')
)
// JSDoc represents types like objects and arrays using an old Closure-style notation,
// e.g. `Array.<string>` or `Record.<string, string>`. This `replace()` removes the `.` to match
// the notation used for TypeScript-style generics.
?.replaceAll('.<', '<');
const properties = [
typesFormatted ? `**Type:** \`${typesFormatted}\`` : undefined,
cliFlag ? `**CLI:** \`${cliFlag.text}\`` : undefined,
comment.defaultvalue ? `**Default:** ${comment.defaultvalue}` : undefined,
comment.version ? `<Since v="${comment.version}" />` : undefined,
]
.filter((l) => l !== undefined)
.join('<br />\n');
return properties.length ? ['<p>', '', properties, '</p>', ''].join('\n') : undefined;
}
run();