parent
01a7933793
commit
d3746d8117
926 changed files with 4771 additions and 29409 deletions
134
scripts/extract-theme-css.mjs
Normal file
134
scripts/extract-theme-css.mjs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
const websiteRoot = path.join(repoRoot, "website");
|
||||
const cssRoot = path.join(repoRoot, "css");
|
||||
|
||||
const themeCssPath = path.join(cssRoot, "theme.css");
|
||||
const siteCssPath = path.join(cssRoot, "site.css");
|
||||
|
||||
function read(filePath) {
|
||||
return fs.readFileSync(filePath, "utf8");
|
||||
}
|
||||
|
||||
function write(filePath, value) {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
fs.writeFileSync(filePath, value);
|
||||
}
|
||||
|
||||
function walkHtml(dir) {
|
||||
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
return walkHtml(fullPath);
|
||||
}
|
||||
return entry.isFile() && entry.name.endsWith(".html") ? [fullPath] : [];
|
||||
});
|
||||
}
|
||||
|
||||
function extractStyle(html, id) {
|
||||
return html.match(new RegExp(`<style\\b[^>]*id=["']${id}["'][^>]*>([\\s\\S]*?)<\\/style>`))?.[1].trim() ?? "";
|
||||
}
|
||||
|
||||
function extractAnonymousShortcodeCss(html) {
|
||||
return (
|
||||
Array.from(html.matchAll(/<style\s+type=["']text\/css["']>([\s\S]*?)<\/style>/g))
|
||||
.map((match) => match[1].trim())
|
||||
.find((body) => body.includes(".su-column-size-1-4")) ?? ""
|
||||
);
|
||||
}
|
||||
|
||||
function buildCssFiles() {
|
||||
const aboutHtml = read(path.join(websiteRoot, "about.html"));
|
||||
const indexHtml = read(path.join(websiteRoot, "index.html"));
|
||||
|
||||
const aboutTheme = extractStyle(aboutHtml, "parabola-style-inline-css");
|
||||
const indexTheme = extractStyle(indexHtml, "parabola-style-inline-css");
|
||||
if (!aboutTheme || !indexTheme) {
|
||||
return false;
|
||||
}
|
||||
const marker = "/* Parabola Custom CSS */";
|
||||
const indexExtra = indexTheme.includes(marker)
|
||||
? indexTheme.slice(0, indexTheme.indexOf(marker)).replace(aboutTheme.slice(0, aboutTheme.indexOf(marker)), "").trim()
|
||||
: "";
|
||||
|
||||
const customBackground = extractStyle(aboutHtml, "custom-background-css");
|
||||
const headerFix = extractStyle(aboutHtml, "site-custom-css");
|
||||
const shortcodeCss = extractAnonymousShortcodeCss(aboutHtml);
|
||||
|
||||
write(
|
||||
themeCssPath,
|
||||
[
|
||||
"/* Extracted from the exported Parabola inline theme settings. */",
|
||||
aboutTheme,
|
||||
"",
|
||||
].join("\n")
|
||||
);
|
||||
|
||||
write(
|
||||
siteCssPath,
|
||||
[
|
||||
"/* Shared site fixes extracted from repeated inline styles. */",
|
||||
customBackground,
|
||||
"",
|
||||
headerFix,
|
||||
"",
|
||||
"/* Shortcodes Ultimate column rule used by exported content. */",
|
||||
shortcodeCss,
|
||||
"",
|
||||
"/* Homepage slider/frontpage settings from the original export. */",
|
||||
indexExtra,
|
||||
"",
|
||||
]
|
||||
.filter((section) => section !== "")
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensureThemeLinks(html) {
|
||||
if (html.includes("href='/css/theme.css'") || html.includes('href="/css/theme.css"')) {
|
||||
return html;
|
||||
}
|
||||
|
||||
const links = [
|
||||
"<link rel='stylesheet' id='familyfedie-theme-css' href='/css/theme.css' type='text/css' media='all' />",
|
||||
"<link rel='stylesheet' id='familyfedie-site-css' href='/css/site.css' type='text/css' media='all' />",
|
||||
].join("\n");
|
||||
|
||||
return html.replace(
|
||||
/(<link rel=['"]stylesheet['"] id=['"]parabola-style-css['"][^>]*>\s*)/,
|
||||
`$1${links}\n`
|
||||
);
|
||||
}
|
||||
|
||||
function removeExtractedInlineStyles(html) {
|
||||
return html
|
||||
.replace(/\n?<style\b[^>]*id=["']parabola-style-inline-css["'][^>]*>[\s\S]*?<\/style>\s*/g, "\n")
|
||||
.replace(/\n?<style\b[^>]*id=["']custom-background-css["'][^>]*>[\s\S]*?<\/style>\s*/g, "\n")
|
||||
.replace(/\n?<style\b[^>]*id=["']site-custom-css["'][^>]*>[\s\S]*?<\/style>\s*/g, "\n")
|
||||
.replace(/\n?<style\s+type=["']text\/css["']>\s*\.su-column-size-1-4\{[\s\S]*?<\/style>\s*/g, "\n");
|
||||
}
|
||||
|
||||
const wroteCssFiles = buildCssFiles();
|
||||
|
||||
let updated = 0;
|
||||
|
||||
for (const filePath of walkHtml(websiteRoot)) {
|
||||
const original = read(filePath);
|
||||
const next = removeExtractedInlineStyles(ensureThemeLinks(original));
|
||||
|
||||
if (next !== original) {
|
||||
write(filePath, next);
|
||||
updated += 1;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
wroteCssFiles
|
||||
? "Extracted repeated inline CSS to css/theme.css and css/site.css."
|
||||
: "Inline theme CSS was already extracted; kept existing css/theme.css and css/site.css."
|
||||
);
|
||||
console.log(`Updated ${updated} HTML files.`);
|
||||
Loading…
Add table
Add a link
Reference in a new issue