Skip to content

Commit f46efaf

Browse files
Add initial build-unversioned-docs script.
This copies over and adds the correct permalinks to the selected version content. Currently moving `v2` -> `unversioned`.
1 parent 6615bb6 commit f46efaf

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-3
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ packages/lit-dev-content/site/fonts/manrope
1111
packages/lit-dev-content/temp
1212
packages/lit-dev-content/samples/js
1313
packages/lit-dev-content/src/public-vars.ts
14+
# The unversioned docs are generated by:
15+
#
16+
# `npm run build:unversioned-docs -w lit-dev-content`
17+
packages/lit-dev-content/site/docs/unversioned
1418

1519
packages/lit-dev-api/api-data/*/repo/
1620
packages/lit-dev-api/api-data/*/INSTALLED

packages/lit-dev-content/.eleventy.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ const DEV = ENV.eleventyMode === 'dev';
4242

4343
const cspInlineScriptHashes = new Set();
4444

45+
/**
46+
* @param {import("@11ty/eleventy/src/UserConfig")} eleventyConfig
47+
* @returns {ReturnType<import("@11ty/eleventy/src/defaultConfig")>}
48+
*/
4549
module.exports = function (eleventyConfig) {
4650
// https://github.com/JordanShurmer/eleventy-plugin-toc#readme
4751
eleventyConfig.addPlugin(pluginTOC, {
@@ -194,7 +198,19 @@ ${content}
194198

195199
eleventyConfig.addCollection('docs-v2', function (collection) {
196200
const docs = collection
197-
.getFilteredByGlob(['site/docs/*', 'site/docs/!(v1)/**'])
201+
.getFilteredByGlob(['site/docs/v2/**'])
202+
.sort(sortDocs);
203+
for (const page of docs) {
204+
documentByUrl.set(page.url, page);
205+
}
206+
return docs;
207+
});
208+
209+
// Collection that contains the built duplicate docs for the current
210+
// recommended version of Lit.
211+
eleventyConfig.addCollection('docs-unversioned', function (collection) {
212+
const docs = collection
213+
.getFilteredByGlob(['site/docs/unversioned/**'])
198214
.sort(sortDocs);
199215
for (const page of docs) {
200216
documentByUrl.set(page.url, page);
@@ -487,8 +503,10 @@ ${content}
487503
ENV.eleventyOutDir + '/docs/*/index.html',
488504
ENV.eleventyOutDir + '/docs/v1/introduction.html',
489505
ENV.eleventyOutDir + '/docs/v1/*/index.html',
506+
ENV.eleventyOutDir + '/docs/v2/introduction.html',
507+
ENV.eleventyOutDir + '/docs/v2/*/index.html',
490508
],
491-
{ignore: ENV.eleventyOutDir + '/docs/v1/index.html'}
509+
{ignore: ENV.eleventyOutDir + '/docs/(v1|v2)/index.html'}
492510
)
493511
).filter(
494512
// TODO(aomarks) This is brittle, we need a way to annotate inside an md

packages/lit-dev-content/package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"build:ts": "wireit",
1313
"build:rollup": "wireit",
1414
"build:samples": "wireit",
15+
"build:unversioned-docs": "wireit",
1516
"dev:build": "wireit",
1617
"dev:serve": "wireit",
1718
"prod:build": "wireit",
@@ -21,7 +22,8 @@
2122
"build": {
2223
"command": "LITDEV_ENV=local NODE_OPTIONS=--experimental-vm-modules eleventy",
2324
"dependencies": [
24-
"prod:build:assets"
25+
"prod:build:assets",
26+
"build:unversioned-docs"
2527
],
2628
"files": [
2729
"site/**",
@@ -135,6 +137,15 @@
135137
"output": [
136138
"samples/js/**"
137139
]
140+
},
141+
"build:unversioned-docs": {
142+
"command": "node ../lit-dev-tools-esm/lib/build-unversioned-docs.js",
143+
"dependencies": [
144+
"../lit-dev-tools-esm:build"
145+
],
146+
"output": [
147+
"site/docs/unversioned"
148+
]
138149
}
139150
},
140151
"devDependencies": {
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/**
2+
* @license
3+
* Copyright 2023 Google LLC
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
import {fileURLToPath} from 'url';
8+
import * as pathlib from 'path';
9+
import * as fs from 'fs';
10+
import * as fsPromise from 'fs/promises';
11+
12+
const THIS_DIR = pathlib.dirname(fileURLToPath(import.meta.url));
13+
const REPO_ROOT = pathlib.resolve(THIS_DIR, '..', '..', '..');
14+
const CONTENT_PKG = pathlib.resolve(REPO_ROOT, 'packages', 'lit-dev-content');
15+
const SITE_JSON = pathlib.resolve(CONTENT_PKG, 'site', 'site.json');
16+
17+
interface SiteJSON {
18+
selectedVersion: 'v1' | 'v2';
19+
}
20+
21+
type EleventyFrontMatterData = string[];
22+
23+
const SITE_SELECTED_VERSION = (
24+
JSON.parse(fs.readFileSync(SITE_JSON, 'utf8')) as SiteJSON
25+
).selectedVersion;
26+
const SELECTED_VERSION_CONTENT = pathlib.resolve(
27+
CONTENT_PKG,
28+
'site',
29+
'docs',
30+
SITE_SELECTED_VERSION
31+
);
32+
console.log(SELECTED_VERSION_CONTENT);
33+
const UNVERSIONED_VERSION_LOCATION = pathlib.resolve(
34+
CONTENT_PKG,
35+
'site',
36+
'docs',
37+
'unversioned'
38+
);
39+
40+
/**
41+
* This script builds our unversioned latest documentation for lit.dev. It
42+
* locates the current selectedVersion of Lit to show from `site.json`, then
43+
* copies that documentation from the versioned subdirectory into an unversioned
44+
* subdirectory.
45+
*
46+
* The following transforms are then applied on the files:
47+
* - Permalink frontmatter is added to strip the version from the URL. E.g.,
48+
* /docs/v2/* becomes /docs/*.
49+
* - Versioned cross links are detected and made unversioned.
50+
*/
51+
const buildAndTransformUnverionedDocs = async () => {
52+
const walk = async (dirPath: string): Promise<void> => {
53+
const entries = await fsPromise.readdir(dirPath, {withFileTypes: true});
54+
await Promise.all(
55+
entries.map(async (entry) => {
56+
const childPath = pathlib.join(dirPath, entry.name);
57+
if (entry.isDirectory()) {
58+
return walk(childPath);
59+
} else {
60+
transformFile(childPath);
61+
}
62+
})
63+
);
64+
};
65+
66+
await walk(SELECTED_VERSION_CONTENT);
67+
};
68+
69+
/**
70+
* Transform the given versioned content file and copy it to the unversioned
71+
* directory.
72+
*/
73+
async function transformFile(path: string) {
74+
let fileContents = fs.readFileSync(path, {encoding: 'utf8'});
75+
const relativeChildPath = pathlib.relative(SELECTED_VERSION_CONTENT, path);
76+
const ext = pathlib.extname(relativeChildPath);
77+
let unversionedLocation = pathlib.join(
78+
UNVERSIONED_VERSION_LOCATION,
79+
relativeChildPath
80+
);
81+
82+
if (ext === '.md') {
83+
const fileName = pathlib.basename(unversionedLocation, '.md');
84+
const [frontMatterData, restOfFile] = getFrontMatterData(fileContents);
85+
const existingPermalink = frontMatterData.findIndex((val) =>
86+
val.includes('permalink:')
87+
);
88+
if (existingPermalink !== -1) {
89+
throw new Error(
90+
'Unhandled case: Handle this by transforming the permalink here.'
91+
);
92+
}
93+
if (fileName === 'index') {
94+
frontMatterData.push(
95+
`permalink: docs/${relativeChildPath.slice(0, -3)}.html`
96+
);
97+
} else {
98+
frontMatterData.push(
99+
`permalink: docs/${relativeChildPath.slice(0, -3)}/index.html`
100+
);
101+
}
102+
103+
fileContents = writeFrontMatter(frontMatterData) + restOfFile;
104+
} else if (ext === '.json') {
105+
if (
106+
pathlib.basename(unversionedLocation, '.json') === SITE_SELECTED_VERSION
107+
) {
108+
unversionedLocation = pathlib.join(
109+
pathlib.dirname(unversionedLocation),
110+
'unversioned.json'
111+
);
112+
fileContents = JSON.stringify({
113+
collection: 'docs-unversioned',
114+
selectedversion: SITE_SELECTED_VERSION,
115+
});
116+
}
117+
} else if (ext === '.html') {
118+
if (pathlib.basename(unversionedLocation, '.html') === 'api') {
119+
const [frontMatterData, _] = getFrontMatterData(fileContents);
120+
const transformedFrontMatter = frontMatterData.map((line) => {
121+
return line.replace(`/${SITE_SELECTED_VERSION}/`, '/');
122+
});
123+
fileContents = writeFrontMatter(transformedFrontMatter);
124+
} else {
125+
throw new Error(`Unhandled html document: '${path}'`);
126+
}
127+
} else {
128+
throw new Error(`Unhandled extension '${ext}' for '${path}'`);
129+
}
130+
131+
fs.mkdirSync(pathlib.dirname(unversionedLocation), {recursive: true});
132+
fs.writeFileSync(unversionedLocation, fileContents);
133+
}
134+
135+
/**
136+
* Retrieve the 11ty frontmatter from our docs. This is not a full fledged YAML
137+
* parser.
138+
*/
139+
function getFrontMatterData(
140+
fileData: string
141+
): [EleventyFrontMatterData, string] {
142+
const splitFile = fileData.split('---');
143+
const frontMatterData = splitFile[1].split('\n').slice(1, -1);
144+
const restOfFile = splitFile.slice(2).join('---');
145+
return [frontMatterData, restOfFile];
146+
}
147+
148+
function writeFrontMatter(frontmatter: EleventyFrontMatterData): string {
149+
return '---\n' + frontmatter.join('\n') + '\n---';
150+
}
151+
152+
buildAndTransformUnverionedDocs();

0 commit comments

Comments
 (0)