forked from MarketDataApp/documentation
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport-sdk-docs.js
More file actions
148 lines (129 loc) · 5.32 KB
/
Copy pathexport-sdk-docs.js
File metadata and controls
148 lines (129 loc) · 5.32 KB
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
#!/usr/bin/env node
'use strict';
/**
* Export SDK docs from /sdk/{lang}/ as clean .md, ready to land in MarketDataApp/sdk-{lang}/docs.
*
* node scripts/export-sdk-docs.js --sdk js [--out ./build/sdk-docs/js]
*
* The CLI is intentionally thin — all conversion lives in lib/mdx-to-md.js.
* Output dir is wiped before write so deleted source files don't linger in the target.
*/
const fs = require('fs');
const path = require('path');
const { cleanMdx } = require('../lib/mdx-to-md');
const REPO_ROOT = path.resolve(__dirname, '..');
const SUPPORTED_SDKS = ['js', 'py', 'go', 'php'];
function parseArgs(argv) {
const args = { sdk: null, out: null };
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a === '--sdk') args.sdk = argv[++i];
else if (a === '--out') args.out = argv[++i];
else if (a === '-h' || a === '--help') args.help = true;
else {
console.error(`Unknown argument: ${a}`);
process.exit(2);
}
}
return args;
}
function printUsage() {
console.log(`Usage: node scripts/export-sdk-docs.js --sdk <${SUPPORTED_SDKS.join('|')}> [--out <dir>]`);
console.log('');
console.log('Converts /sdk/<sdk>/*.mdx → clean .md files under <out> (default: build/sdk-docs/<sdk>/).');
}
function walkMdx(dir, acc = []) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) walkMdx(full, acc);
else if (entry.isFile() && /\.(mdx?|md)$/.test(entry.name)) acc.push(full);
}
return acc;
}
function emptyDir(dir) {
if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true });
fs.mkdirSync(dir, { recursive: true });
}
function main() {
const args = parseArgs(process.argv.slice(2));
if (args.help || !args.sdk) {
printUsage();
process.exit(args.help ? 0 : 2);
}
if (!SUPPORTED_SDKS.includes(args.sdk)) {
console.error(`--sdk must be one of: ${SUPPORTED_SDKS.join(', ')}`);
process.exit(2);
}
const sourceDir = path.join(REPO_ROOT, 'sdk', args.sdk);
if (!fs.existsSync(sourceDir)) {
console.error(`Source directory not found: ${sourceDir}`);
process.exit(1);
}
const outDir = path.resolve(args.out || path.join(REPO_ROOT, 'build', 'sdk-docs', args.sdk));
emptyDir(outDir);
const files = walkMdx(sourceDir);
// Build the source-aware link target map BEFORE writing any file. For each
// source .mdx, compute what /sdk/{sdk}/... URLs in *other* docs would point
// at, and which output file we'll write it as. Directory indices land as
// README.md so GitHub auto-renders them at the directory URL.
// Map keys are Docusaurus subpaths (no leading slash, no extension); values
// are repo-relative POSIX output paths.
const linkTargets = {};
for (const sourceAbs of files) {
const relFromSdk = path.relative(sourceDir, sourceAbs).split(path.sep).join('/');
const noExt = relFromSdk.replace(/\.(mdx?|md)$/, '');
const isIndex = path.posix.basename(noExt) === 'index';
if (isIndex) {
const dirSub = path.posix.dirname(noExt);
const key = dirSub === '.' ? '' : dirSub;
const out = key === '' ? 'README.md' : `${key}/README.md`;
linkTargets[key] = out;
} else {
linkTargets[noExt] = `${noExt}.md`;
}
}
const manifest = [];
for (const sourceAbs of files) {
const relPosix = path.relative(sourceDir, sourceAbs).split(path.sep).join('/');
const sourcePathRel = path.posix.join('sdk', args.sdk, relPosix);
const noExt = relPosix.replace(/\.(mdx?|md)$/, '');
const isIndex = path.posix.basename(noExt) === 'index';
const outRelative = isIndex
? (path.posix.dirname(noExt) === '.' ? 'README.md' : `${path.posix.dirname(noExt)}/README.md`)
: `${noExt}.md`;
const outAbs = path.join(outDir, ...outRelative.split('/'));
const raw = fs.readFileSync(sourceAbs, 'utf8');
const body = cleanMdx(raw, {
sourcePath: sourcePathRel,
sdk: args.sdk,
linkTargets,
});
fs.mkdirSync(path.dirname(outAbs), { recursive: true });
fs.writeFileSync(outAbs, body, 'utf8');
manifest.push({ path: outRelative, bytes: Buffer.byteLength(body, 'utf8') });
}
// Write a manifest of every file we generated, so the sync workflow can
// delete exactly these paths on the next run without touching repo-owned
// content. The manifest itself is also listed so it gets refreshed each
// sync (and removed cleanly if the workflow is ever retired).
const generatedPaths = [...manifest.map((m) => m.path), '.sync-manifest.txt'].sort();
const manifestPath = path.join(outDir, '.sync-manifest.txt');
const manifestBody =
'# Auto-generated by MarketDataApp/documentation/scripts/export-sdk-docs.js.\n' +
'# These files are owned by the docs sync workflow — do not edit them by hand.\n' +
'# Editing this manifest will not break anything; the workflow rebuilds it each run.\n' +
generatedPaths.join('\n') +
'\n';
fs.writeFileSync(manifestPath, manifestBody, 'utf8');
manifest.push({
path: '.sync-manifest.txt',
bytes: Buffer.byteLength(manifestBody, 'utf8'),
note: '(workflow manifest)',
});
manifest.sort((a, b) => a.path.localeCompare(b.path));
console.log(`Exported ${manifest.length} file(s) to ${outDir}\n`);
for (const { path: p, bytes, note } of manifest) {
console.log(` ${String(bytes).padStart(7)} ${p}${note ? ' ' + note : ''}`);
}
}
main();