Skip to content

Commit 7213c38

Browse files
committed
feat: add tools configuration and HTML header extraction utility
1 parent 5192340 commit 7213c38

3 files changed

Lines changed: 80 additions & 0 deletions

File tree

tools/getAllHeaderNames.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { readFile, readdir as readDir } from "fs/promises"
2+
import { join } from "path"
3+
import child from "child_process"
4+
5+
const TAGS_IGNORED = ["viewport"]
6+
7+
/**
8+
* To decode HTML entities in a string
9+
* This method was generously provided by Claude Sonnet 4.5
10+
* @param text The text containing HTML entities
11+
* @returns The decoded text
12+
*/
13+
const decodeHtmlEntities = (text: string): string => {
14+
const entities: Record<string, string> = {
15+
'&amp;': '&',
16+
'&lt;': '<',
17+
'&gt;': '>',
18+
'&quot;': '"',
19+
'&apos;': "'",
20+
'&nbsp;': ' ',
21+
// Add more as needed
22+
}
23+
24+
return text
25+
.replace(/&[a-z]+;/gi, (match) => entities[match] || match)
26+
.replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(Number(dec)))
27+
.replace(/&#x([0-9a-f]+);/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
28+
}
29+
30+
// Building the project first to ensure headers are up to date
31+
child.execSync("yarn build")
32+
33+
const files = await readDir("./dist/", { withFileTypes: true, recursive: true })
34+
35+
const htmlFiles = files
36+
.map((f) => {
37+
if (f.isFile() && f.name.endsWith(".html")) {
38+
return join(f.parentPath, f.name)
39+
} else {
40+
return null
41+
}
42+
})
43+
.filter((f) => f !== null)
44+
45+
const metaTags = new Map<string, { name: string; value: string }[]>()
46+
47+
for (const filePath of htmlFiles) {
48+
const content = await readFile(`./${filePath}`, "utf-8")
49+
50+
const metaTagRegex = /<meta\s+(?:name|property)="([^"]+)"\s+content="([^"]+)"\s*\/?>/g
51+
const tags: { name: string; value: string }[] = []
52+
let match: RegExpExecArray | null
53+
while ((match = metaTagRegex.exec(content)) !== null) {
54+
if (TAGS_IGNORED.includes(match[1])) continue
55+
tags.push({ name: match[1], value: match[2] })
56+
}
57+
metaTags.set(filePath, tags)
58+
}
59+
60+
metaTags.forEach((tags, filePath) => {
61+
console.log(`File: ${filePath}`)
62+
tags.forEach((tag) => {
63+
console.log(` ${tag.name}: ${decodeHtmlEntities(tag.value)}`)
64+
})
65+
console.log("") // Empty line between files
66+
})

tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
},
77
{
88
"path": "./tsconfig.app.json"
9+
},
10+
{
11+
"path": "./tsconfig.tools.json"
912
}
1013
]
1114
}

tsconfig.tools.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "@tsconfig/node22/tsconfig.json",
3+
"include": ["tools/**/*"],
4+
"compilerOptions": {
5+
"noEmit": true,
6+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tools.tsbuildinfo",
7+
"module": "ESNext",
8+
"moduleResolution": "Bundler",
9+
"types": ["node"]
10+
}
11+
}

0 commit comments

Comments
 (0)