Skip to content

Commit 89d4ef7

Browse files
Generate language code added
1 parent d856f29 commit 89d4ef7

4 files changed

Lines changed: 78 additions & 2 deletions

File tree

eslint.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ export default defineConfig([
99
{ files: ["**/*.{js,mjs,cjs}"], languageOptions: { globals: globals.browser } },
1010
{ files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"] },
1111

12-
// Node.js config files need Node globals (module, require, process, …)
12+
// Node.js config and generator scripts need Node globals (module, require, process, …)
1313
{
14-
files: ["*.config.js", "*.config.mjs", "*.config.cjs"],
14+
files: ["*.config.js", "*.config.mjs", "*.config.cjs", "generate_*.js"],
1515
languageOptions: { globals: globals.node },
1616
},
1717

generate_language_file.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env node
2+
// Scans a folder of course HTML files and writes a sorted JSON array of all
3+
// Shiki language identifiers found in code blocks to production/data/languages.json.
4+
//
5+
// Usage: node generate_language_file.js <path-to-html-folder>
6+
//
7+
// Recognises both patterns Skilljar produces:
8+
// <pre class="language-terraform"><code data-lang="terraform">
9+
// <pre data-lang="terraform"><code>
10+
11+
const { readFileSync, writeFileSync, readdirSync, statSync } = require("fs");
12+
const { join, extname, resolve } = require("path");
13+
14+
const htmlFolder = process.argv[2];
15+
16+
if (!htmlFolder) {
17+
console.error("Usage: node generate_language_file.js <path-to-html-folder>");
18+
process.exit(1);
19+
}
20+
21+
function walkHtml(dir) {
22+
const files = [];
23+
for (const entry of readdirSync(dir)) {
24+
const full = join(dir, entry);
25+
if (statSync(full).isDirectory()) {
26+
files.push(...walkHtml(full));
27+
} else if (extname(entry) === ".html") {
28+
files.push(full);
29+
}
30+
}
31+
return files;
32+
}
33+
34+
const patterns = [
35+
/class="language-([^"\s]+)"/g,
36+
/data-lang="([^"]+)"/g,
37+
];
38+
39+
const languages = new Set();
40+
41+
for (const file of walkHtml(resolve(htmlFolder))) {
42+
const content = readFileSync(file, "utf-8");
43+
for (const re of patterns) {
44+
re.lastIndex = 0;
45+
let match;
46+
while ((match = re.exec(content)) !== null) {
47+
languages.add(match[1]);
48+
}
49+
}
50+
}
51+
52+
const sorted = [...languages].sort();
53+
const outputPath = join(__dirname, "production/data/languages.json");
54+
55+
writeFileSync(outputPath, JSON.stringify(sorted, null, 2) + "\n");
56+
57+
console.log(`Found ${sorted.length} language(s): ${sorted.join(", ") || "(none)"}`);
58+
console.log(`Written to ${outputPath}`);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"build:js:dev": "esbuild production/theme.mjs --bundle --sourcemap --outfile=dist/bundle.js",
1212
"watch:css": "postcss production/style.css -o dist/bundle.css --watch --map",
1313
"watch:js": "esbuild production/theme.mjs --bundle --sourcemap --outfile=dist/bundle.js --watch",
14+
"generate:langs": "node generate_language_file.js",
1415
"build": "npm run lint && npm run build:css && npm run build:js",
1516
"build:dev": "npm run lint && npm run build:css:dev && npm run build:js:dev",
1617
"dev": "npm run watch:css & npm run watch:js",

production/data/languages.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[
2+
"ansi",
3+
"bash",
4+
"console",
5+
"docker",
6+
"dockerfile",
7+
"go",
8+
"http",
9+
"json",
10+
"markdown",
11+
"markup",
12+
"nginx",
13+
"python",
14+
"terraform",
15+
"text",
16+
"yaml"
17+
]

0 commit comments

Comments
 (0)