Skip to content

Commit f22ac74

Browse files
committed
chore(docs): add versioned documentation with auto-detection
Close #675
1 parent 287dedb commit f22ac74

File tree

5 files changed

+558
-10
lines changed

5 files changed

+558
-10
lines changed

.github/scripts/merge-versions.mjs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Merge versions.json for documentation deployment
5+
*
6+
* This script merges existing versions from S3 with newly deployed versions,
7+
* ensuring the version selector shows all available documentation versions.
8+
*/
9+
10+
import { readFileSync, writeFileSync } from 'fs';
11+
12+
/**
13+
* Compute sort key for a version string
14+
* Returns [category, value] where:
15+
* - category 0: "latest"
16+
* - category 1: "preview"
17+
* - category 2: versioned releases (v1, v2, etc.) - sorted descending
18+
* - category 3: unknown/unexpected entries
19+
*/
20+
function sortKey(version) {
21+
if (version === 'latest') return [0, 0];
22+
if (version === 'preview') return [1, 0];
23+
24+
const match = version.match(/^v(\d+)(?:\D|$)/);
25+
if (match) {
26+
// Negative value for descending sort within category
27+
return [2, -parseInt(match[1], 10)];
28+
}
29+
30+
// Unknown entries sort last, stable by version name
31+
return [3, version];
32+
}
33+
34+
/**
35+
* Sort versions in the correct order:
36+
* 1. latest
37+
* 2. preview
38+
* 3. v2, v1 (descending)
39+
* 4. unknown entries (alphabetically)
40+
*/
41+
function sortVersions(versions) {
42+
return versions.sort((a, b) => {
43+
const [groupA, valueA] = sortKey(a.version);
44+
const [groupB, valueB] = sortKey(b.version);
45+
46+
if (groupA !== groupB) return groupA - groupB;
47+
if (valueA === valueB) return 0;
48+
return valueA < valueB ? -1 : 1;
49+
});
50+
}
51+
52+
/**
53+
* Merge existing and new versions, removing duplicates
54+
*/
55+
function mergeVersions(existingVersions, newVersions) {
56+
if (!Array.isArray(existingVersions) || !Array.isArray(newVersions)) {
57+
throw new Error('Both existing and new versions files must be a JSON array.');
58+
}
59+
60+
const versionMap = new Map();
61+
62+
// Add existing versions
63+
for (const version of existingVersions) {
64+
if (!version || typeof version.version !== 'string') {
65+
throw new Error('Invalid versions entry (missing string "version" property).');
66+
}
67+
versionMap.set(version.version, version);
68+
}
69+
70+
// Add/update with new versions
71+
for (const version of newVersions) {
72+
if (!version || typeof version.version !== 'string') {
73+
throw new Error('Invalid versions entry (missing string "version" property).');
74+
}
75+
versionMap.set(version.version, version);
76+
}
77+
78+
const merged = Array.from(versionMap.values());
79+
return sortVersions(merged);
80+
}
81+
82+
/**
83+
* Main execution
84+
*/
85+
function main() {
86+
const args = process.argv.slice(2);
87+
88+
if (args.length !== 3) {
89+
console.error(
90+
'Usage: merge-versions.mjs <existing-versions-file> <new-versions-file> <output-file>'
91+
);
92+
process.exit(1);
93+
}
94+
95+
const [existingFile, newFile, outputFile] = args;
96+
97+
// Read existing versions
98+
let existingVersions = [];
99+
try {
100+
const content = readFileSync(existingFile, 'utf-8');
101+
existingVersions = JSON.parse(content);
102+
103+
if (!Array.isArray(existingVersions)) {
104+
throw new Error('Existing versions.json must contain an array');
105+
}
106+
107+
console.log(`Loaded ${existingVersions.length} existing versions`);
108+
} catch (error) {
109+
if (error.code === 'ENOENT') {
110+
console.log('No existing versions file found, starting fresh');
111+
} else {
112+
console.error('Error reading existing versions:', error.message);
113+
process.exit(1);
114+
}
115+
}
116+
117+
// Read new versions
118+
let newVersions = [];
119+
try {
120+
const content = readFileSync(newFile, 'utf-8');
121+
newVersions = JSON.parse(content);
122+
123+
if (!Array.isArray(newVersions)) {
124+
throw new Error('New versions.json must contain an array');
125+
}
126+
127+
console.log(`Loaded ${newVersions.length} new versions to deploy`);
128+
} catch (error) {
129+
console.error('Error reading new versions:', error.message);
130+
process.exit(1);
131+
}
132+
133+
// Merge and sort
134+
const mergedVersions = mergeVersions(existingVersions, newVersions);
135+
console.log(`Merged result: ${mergedVersions.length} total versions`);
136+
console.log('Version order:', mergedVersions.map(v => v.version).join(', '));
137+
138+
// Write output
139+
try {
140+
writeFileSync(outputFile, JSON.stringify(mergedVersions, null, 2));
141+
console.log(`Successfully wrote merged versions to ${outputFile}`);
142+
} catch (error) {
143+
console.error('Error writing output:', error.message);
144+
process.exit(1);
145+
}
146+
}
147+
148+
main();

0 commit comments

Comments
 (0)