feat: migrate Hugo Bootstrap theme to latest Hugo with Tailwind CSS and refactor codebase
* replace Bootstrap-based styling with Tailwind CSS * update theme compatibility for latest Hugo version * refactor templates and partials * fix outdated code and broken components * improve project structure and maintainability * optimize styling and frontend build setup
This commit is contained in:
14
scripts/clearModules.js
Normal file
14
scripts/clearModules.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const fs = require("fs");
|
||||
|
||||
const clearModules = (filePath) => {
|
||||
if (fs.existsSync(filePath)) {
|
||||
let fileContent = fs.readFileSync(filePath, "utf8");
|
||||
fileContent = fileContent.replace(/require\s*\([\s\S]*?\)/, "");
|
||||
fs.writeFileSync(filePath, fileContent, "utf8");
|
||||
} else {
|
||||
console.log("File does not exist.");
|
||||
}
|
||||
};
|
||||
|
||||
clearModules("go.mod");
|
||||
clearModules("exampleSite/go.mod");
|
||||
116
scripts/projectSetup.js
Normal file
116
scripts/projectSetup.js
Normal file
@@ -0,0 +1,116 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// const toggleComment = ({ filepath, regex }) => {
|
||||
// let updatedContent = fs.readFileSync(filepath, "utf8");
|
||||
// const match = updatedContent.match(regex);
|
||||
|
||||
// if (match) {
|
||||
// const matchedContent = match[0];
|
||||
// const hasComment = matchedContent.startsWith("# ");
|
||||
// if (hasComment) {
|
||||
// updatedContent = updatedContent.replace(
|
||||
// regex,
|
||||
// matchedContent.replace("# ", ""),
|
||||
// );
|
||||
// fs.writeFileSync(filepath, updatedContent, "utf8");
|
||||
// } else {
|
||||
// const hasBreakline = matchedContent.includes("\n");
|
||||
// if (hasBreakline) {
|
||||
// const content = matchedContent
|
||||
// .split("\n")
|
||||
// .map((line) => "# " + line)
|
||||
// .join("\n");
|
||||
// updatedContent = updatedContent.replace(regex, content);
|
||||
// fs.writeFileSync(filepath, updatedContent, "utf8");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
const getFolderName = (rootfolder) => {
|
||||
const configPath = path.join(rootfolder, "exampleSite/hugo.toml");
|
||||
const getConfig = fs.readFileSync(configPath, "utf8");
|
||||
const match = getConfig.match(/theme\s*=\s*\[?"([^"\]]+)"\]?/);
|
||||
let selectedTheme = null;
|
||||
if (match && match[1]) {
|
||||
selectedTheme = match[1];
|
||||
}
|
||||
return selectedTheme;
|
||||
};
|
||||
|
||||
const deleteFolder = (folderPath) => {
|
||||
if (fs.existsSync(folderPath)) {
|
||||
fs.rmSync(folderPath, { recursive: true, force: true });
|
||||
}
|
||||
};
|
||||
|
||||
const createNewfolder = (rootfolder, folderName) => {
|
||||
const newFolder = path.join(rootfolder, folderName);
|
||||
fs.mkdirSync(newFolder, { recursive: true });
|
||||
return newFolder;
|
||||
};
|
||||
|
||||
const iterateFilesAndFolders = (rootFolder, { destinationRoot }) => {
|
||||
const directory = path.join(rootFolder);
|
||||
const items = fs.readdirSync(directory, { withFileTypes: true });
|
||||
items.forEach((item) => {
|
||||
if (item.isDirectory()) {
|
||||
createNewfolder(destinationRoot, item.name);
|
||||
iterateFilesAndFolders(path.join(directory, item.name), {
|
||||
currentFolder: item.name,
|
||||
destinationRoot: path.join(destinationRoot, item.name),
|
||||
});
|
||||
} else {
|
||||
const sourceFile = path.join(directory, item.name);
|
||||
const destinationFile = path.join(destinationRoot, item.name);
|
||||
fs.renameSync(sourceFile, destinationFile);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setupProject = () => {
|
||||
const rootfolder = path.join(__dirname, "../");
|
||||
if (!fs.existsSync(path.join(rootfolder, "themes"))) {
|
||||
// remove this part if you don't using theme demo as a module
|
||||
// [
|
||||
// {
|
||||
// filepath: path.join(rootfolder, "exampleSite/hugo.toml"),
|
||||
// regex: /^.*theme\s*=\s*("[^"\]]+"|\S+)/m,
|
||||
// },
|
||||
// {
|
||||
// filepath: path.join(
|
||||
// rootfolder,
|
||||
// "exampleSite/config/_default/module.toml",
|
||||
// ),
|
||||
// regex: /\[\[imports\]\]\s*\r?\npath = "([^"]+)"/,
|
||||
// },
|
||||
// ].forEach(toggleComment);
|
||||
|
||||
const folderList = ["layouts", "assets", "static", "tailwind-plugin"];
|
||||
const folderName = getFolderName(rootfolder);
|
||||
const newfolderName = createNewfolder(
|
||||
path.join(rootfolder, "themes"),
|
||||
folderName,
|
||||
);
|
||||
|
||||
folderList.forEach((folder) => {
|
||||
const source = path.join(rootfolder, folder);
|
||||
const destination = path.join(newfolderName, folder);
|
||||
if (fs.existsSync(source)) {
|
||||
fs.mkdirSync(destination, { recursive: true });
|
||||
iterateFilesAndFolders(source, {
|
||||
currentFolder: folder,
|
||||
destinationRoot: destination,
|
||||
});
|
||||
deleteFolder(source);
|
||||
}
|
||||
});
|
||||
|
||||
const exampleSite = path.join(rootfolder, "exampleSite");
|
||||
iterateFilesAndFolders(exampleSite, { destinationRoot: rootfolder });
|
||||
deleteFolder(exampleSite);
|
||||
}
|
||||
};
|
||||
|
||||
setupProject();
|
||||
91
scripts/removeDarkmode.js
Normal file
91
scripts/removeDarkmode.js
Normal file
@@ -0,0 +1,91 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const rootDirs = ["assets/css", "layouts"];
|
||||
const configFiles = [
|
||||
{
|
||||
filePath: "exampleSite/data/theme.json",
|
||||
patterns: ["colors.darkmode"],
|
||||
},
|
||||
];
|
||||
|
||||
// asset paths
|
||||
const deleteAssetList = [
|
||||
"exampleSite/assets/images/logo-darkmode.png",
|
||||
"layouts/_partials/components/theme-switcher.html",
|
||||
];
|
||||
|
||||
const filePaths = [
|
||||
{
|
||||
filePath: "layouts/_partials/essentials/header.html",
|
||||
patterns: [
|
||||
'{{\\s*partial\\s*"components\\/theme-switcher"\\s*\\([^)]*\\)\\s*}}',
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
filePaths.forEach(({ filePath, patterns }) =>
|
||||
removeDarkModeFromFiles(filePath, patterns),
|
||||
);
|
||||
|
||||
deleteAssetList.forEach((asset) => {
|
||||
try {
|
||||
fs.unlinkSync(asset);
|
||||
console.log(`${path.basename(asset)} deleted successfully!`);
|
||||
} catch (error) {
|
||||
console.error(`${asset} not found`);
|
||||
}
|
||||
});
|
||||
|
||||
rootDirs.forEach(removeDarkModeFromPages);
|
||||
configFiles.forEach(removeDarkMode);
|
||||
|
||||
function removeDarkModeFromFiles(filePath, regexPatterns) {
|
||||
const fileContent = fs.readFileSync(filePath, "utf8");
|
||||
let updatedContent = fileContent;
|
||||
regexPatterns.forEach((pattern) => {
|
||||
const regex = new RegExp(pattern, "g");
|
||||
updatedContent = updatedContent.replace(regex, "");
|
||||
});
|
||||
|
||||
fs.writeFileSync(filePath, updatedContent, "utf8");
|
||||
}
|
||||
|
||||
// like html file
|
||||
function removeDarkModeFromPages(directoryPath) {
|
||||
const files = fs.readdirSync(directoryPath);
|
||||
|
||||
files.forEach((file) => {
|
||||
const filePath = path.join(directoryPath, file);
|
||||
const stats = fs.statSync(filePath);
|
||||
if (stats.isDirectory()) {
|
||||
removeDarkModeFromPages(filePath);
|
||||
} else if (stats.isFile()) {
|
||||
removeDarkModeFromFiles(filePath, [
|
||||
'(?:(?!["])\\S)*dark:(?:(?![,;"])\\S)*',
|
||||
"@apply?(\\s)*;",
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeDarkMode(configFile) {
|
||||
const { filePath, patterns } = configFile;
|
||||
const contentFile = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
||||
patterns.forEach((pattern) => deleteNestedProperty(contentFile, pattern));
|
||||
fs.writeFileSync(filePath, JSON.stringify(contentFile));
|
||||
}
|
||||
|
||||
function deleteNestedProperty(obj, propertyPath) {
|
||||
const properties = propertyPath.split(".");
|
||||
let currentObj = obj;
|
||||
for (let i = 0; i < properties.length - 1; i++) {
|
||||
const property = properties[i];
|
||||
if (currentObj.hasOwnProperty(property)) {
|
||||
currentObj = currentObj[property];
|
||||
} else {
|
||||
return; // Property not found, no need to continue
|
||||
}
|
||||
}
|
||||
delete currentObj[properties[properties.length - 1]];
|
||||
}
|
||||
122
scripts/removeMultilang.js
Normal file
122
scripts/removeMultilang.js
Normal file
@@ -0,0 +1,122 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
// Paths
|
||||
const notFoundPage = "layouts/404.en.html";
|
||||
const menusPath = "exampleSite/config/_default/menus.en.toml";
|
||||
const languagesPath = "exampleSite/config/_default/languages.toml";
|
||||
const hugoConfigPath = "exampleSite/hugo.toml";
|
||||
const developmentDir = "exampleSite/config/development";
|
||||
const i18nDir = "exampleSite/i18n";
|
||||
const englishContentDir = "exampleSite/content/english";
|
||||
const targetContentDir = "exampleSite/content";
|
||||
|
||||
// Helper function to remove directory recursively
|
||||
const removeDirRecursive = (dirPath) => {
|
||||
if (fs.existsSync(dirPath)) {
|
||||
fs.rmSync(dirPath, { recursive: true, force: true });
|
||||
console.log(`✓ Removed directory: ${dirPath}`);
|
||||
} else {
|
||||
console.log(`✗ Directory not found: ${dirPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to remove file
|
||||
const removeFile = (filePath) => {
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`✓ Removed file: ${filePath}`);
|
||||
} else {
|
||||
console.log(`✗ File not found: ${filePath}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to rename file
|
||||
const renameFile = (oldPath, newPath) => {
|
||||
if (fs.existsSync(oldPath)) {
|
||||
fs.renameSync(oldPath, newPath);
|
||||
console.log(`✓ Renamed: ${oldPath} → ${newPath}`);
|
||||
} else {
|
||||
console.log(`✗ File not found: ${oldPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to move directory contents
|
||||
const moveDirContents = (sourceDir, targetDir) => {
|
||||
if (!fs.existsSync(sourceDir)) {
|
||||
console.log(`✗ Source directory not found: ${sourceDir}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure target directory exists
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
const items = fs.readdirSync(sourceDir);
|
||||
|
||||
items.forEach((item) => {
|
||||
const sourcePath = path.join(sourceDir, item);
|
||||
const targetPath = path.join(targetDir, item);
|
||||
|
||||
fs.renameSync(sourcePath, targetPath);
|
||||
console.log(`✓ Moved: ${sourcePath} → ${targetPath}`);
|
||||
});
|
||||
|
||||
// Remove the now-empty source directory
|
||||
fs.rmdirSync(sourceDir);
|
||||
console.log(`✓ Removed empty directory: ${sourceDir}`);
|
||||
};
|
||||
|
||||
// Main function
|
||||
const removeMultilang = () => {
|
||||
console.log("Starting multilanguage removal process...\n");
|
||||
|
||||
// 1. Remove exampleSite/config/development folder
|
||||
console.log("1. Removing development folder...");
|
||||
removeDirRecursive(developmentDir);
|
||||
console.log("");
|
||||
|
||||
// 2. Remove exampleSite/i18n folder
|
||||
console.log("2. Removing i18n folder...");
|
||||
removeDirRecursive(i18nDir);
|
||||
console.log("");
|
||||
|
||||
// 3. Remove languagesPath file
|
||||
console.log("3. Removing languages.toml file...");
|
||||
removeFile(languagesPath);
|
||||
console.log("");
|
||||
|
||||
// 4. Rename menusPath and notFoundPage
|
||||
console.log("4. Renaming files (removing .en)...");
|
||||
renameFile(menusPath, menusPath.replace(".en.", "."));
|
||||
renameFile(notFoundPage, notFoundPage.replace(".en.", "."));
|
||||
console.log("");
|
||||
|
||||
// 5. Remove language configuration from hugo.toml
|
||||
console.log("5. Updating hugo.toml...");
|
||||
if (fs.existsSync(hugoConfigPath)) {
|
||||
let hugoConfig = fs.readFileSync(hugoConfigPath, "utf-8");
|
||||
|
||||
// Remove the language configuration block
|
||||
const languageConfigRegex =
|
||||
/# disable language\ndisableLanguages = \[\n\].*?defaultContentLanguageInSubdir = false\n/s;
|
||||
hugoConfig = hugoConfig.replace(languageConfigRegex, "");
|
||||
|
||||
fs.writeFileSync(hugoConfigPath, hugoConfig);
|
||||
console.log(`✓ Updated: ${hugoConfigPath}`);
|
||||
} else {
|
||||
console.log(`✗ File not found: ${hugoConfigPath}`);
|
||||
}
|
||||
console.log("");
|
||||
|
||||
// 6. Move all folders and files from exampleSite/content/english to exampleSite/content
|
||||
console.log("6. Moving content from english folder to content folder...");
|
||||
moveDirContents(englishContentDir, targetContentDir);
|
||||
console.log("");
|
||||
|
||||
console.log("✓ Multilanguage removal completed successfully!");
|
||||
};
|
||||
|
||||
// Run the script
|
||||
removeMultilang();
|
||||
217
scripts/themeGenerator.js
Normal file
217
scripts/themeGenerator.js
Normal file
@@ -0,0 +1,217 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
/**
|
||||
* Determine the paths based on setup mode (theme vs project)
|
||||
* @returns {Object} Configuration object with paths and mode info
|
||||
*/
|
||||
function determinePaths() {
|
||||
const rootHugoToml = path.join(__dirname, "../hugo.toml");
|
||||
const exampleSiteHugoToml = path.join(__dirname, "../exampleSite/hugo.toml");
|
||||
|
||||
if (fs.existsSync(exampleSiteHugoToml)) {
|
||||
// Theme setup mode - exampleSite structure exists
|
||||
return {
|
||||
hugoTomlPath: exampleSiteHugoToml,
|
||||
themePath: path.join(__dirname, "../exampleSite/data/theme.json"),
|
||||
outputPath: path.join(__dirname, "../assets/css/generated-theme.css"),
|
||||
isThemeSetup: true,
|
||||
};
|
||||
} else if (fs.existsSync(rootHugoToml)) {
|
||||
// Project setup mode - hugo.toml at root
|
||||
try {
|
||||
const hugoTomlContent = fs.readFileSync(rootHugoToml, "utf8");
|
||||
const themeNameMatch = hugoTomlContent.match(
|
||||
/^theme\s*=\s*["'\[]?"?([^"'\]]+)"?[\]"]?/m,
|
||||
);
|
||||
|
||||
if (!themeNameMatch || !themeNameMatch[1]) {
|
||||
throw new Error("Could not extract theme name from hugo.toml");
|
||||
}
|
||||
|
||||
const themeName = themeNameMatch[1];
|
||||
return {
|
||||
hugoTomlPath: rootHugoToml,
|
||||
themePath: path.join(__dirname, "../data/theme.json"),
|
||||
outputPath: path.join(
|
||||
__dirname,
|
||||
`../themes/${themeName}/assets/css/generated-theme.css`,
|
||||
),
|
||||
isThemeSetup: false,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to determine paths: ${error.message}`);
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
"Could not determine setup mode: neither exampleSite/hugo.toml nor root hugo.toml found",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { themePath, outputPath } = determinePaths();
|
||||
|
||||
// Helper to convert color name from snake_case to kebab-case
|
||||
const toKebab = (str) => str.replace(/_/g, "-");
|
||||
|
||||
// Helper to extract a clean font name
|
||||
const findFont = (fontStr) =>
|
||||
fontStr.replace(/\+/g, " ").replace(/:[^:]+/g, "");
|
||||
|
||||
/**
|
||||
* Add color entries to CSS array
|
||||
* @param {Array} cssLines - Array of CSS lines to append to
|
||||
* @param {Object} colors - Color object to process
|
||||
* @param {string} prefix - Optional prefix for color variable names
|
||||
*/
|
||||
function addColorsToCss(cssLines, colors, prefix = "") {
|
||||
Object.entries(colors).forEach(([key, value]) => {
|
||||
const colorName = prefix
|
||||
? `--color-${prefix}-${toKebab(key)}`
|
||||
: `--color-${toKebab(key)}`;
|
||||
cssLines.push(` ${colorName}: ${value};`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate theme CSS from theme.json configuration
|
||||
* @throws {Error} If theme.json is missing or invalid
|
||||
*/
|
||||
function generateThemeCSS() {
|
||||
// Validate that theme.json exists
|
||||
if (!fs.existsSync(themePath)) {
|
||||
throw new Error(`Theme configuration not found: ${themePath}`);
|
||||
}
|
||||
|
||||
try {
|
||||
// Read and parse theme configuration
|
||||
const themeConfig = JSON.parse(fs.readFileSync(themePath, "utf8"));
|
||||
|
||||
// Validate required theme structure
|
||||
if (!themeConfig.colors || !themeConfig.fonts) {
|
||||
throw new Error(
|
||||
"Invalid theme.json: missing 'colors' or 'fonts' section",
|
||||
);
|
||||
}
|
||||
|
||||
// Build CSS using array for better performance
|
||||
const cssLines = [
|
||||
"/**",
|
||||
' * Auto-generated from "data/theme.json"',
|
||||
" * DO NOT EDIT THIS FILE MANUALLY",
|
||||
" * Run: node scripts/themeGenerator.js",
|
||||
" */",
|
||||
"",
|
||||
"@theme {",
|
||||
" /* === Colors === */",
|
||||
];
|
||||
|
||||
// Add default theme colors
|
||||
if (themeConfig.colors.default?.theme_color) {
|
||||
addColorsToCss(cssLines, themeConfig.colors.default.theme_color);
|
||||
}
|
||||
|
||||
// Add default text colors
|
||||
if (themeConfig.colors.default?.text_color) {
|
||||
addColorsToCss(cssLines, themeConfig.colors.default.text_color);
|
||||
}
|
||||
|
||||
// Add darkmode colors (if available)
|
||||
if (themeConfig.colors.darkmode) {
|
||||
cssLines.push("", " /* === Darkmode Colors === */");
|
||||
|
||||
if (themeConfig.colors.darkmode.theme_color) {
|
||||
addColorsToCss(
|
||||
cssLines,
|
||||
themeConfig.colors.darkmode.theme_color,
|
||||
"darkmode",
|
||||
);
|
||||
}
|
||||
|
||||
if (themeConfig.colors.darkmode.text_color) {
|
||||
addColorsToCss(
|
||||
cssLines,
|
||||
themeConfig.colors.darkmode.text_color,
|
||||
"darkmode",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add font families
|
||||
cssLines.push("", " /* === Font Families === */");
|
||||
const fontFamily = themeConfig.fonts.font_family || {};
|
||||
Object.entries(fontFamily)
|
||||
.filter(([key]) => !key.includes("type"))
|
||||
.forEach(([key, font]) => {
|
||||
const fontFallback = fontFamily[`${key}_type`] || "sans-serif";
|
||||
const fontValue = `${findFont(font)}, ${fontFallback}`;
|
||||
cssLines.push(` --font-${toKebab(key)}: ${fontValue};`);
|
||||
});
|
||||
|
||||
// Add font sizes
|
||||
cssLines.push("", " /* === Font Sizes === */");
|
||||
const baseSize = Number(themeConfig.fonts.font_size?.base || 16);
|
||||
const scale = Number(themeConfig.fonts.font_size?.scale || 1.25);
|
||||
|
||||
cssLines.push(` --text-base: ${baseSize}px;`);
|
||||
cssLines.push(` --text-base-sm: ${baseSize * 0.8}px;`);
|
||||
|
||||
let currentSize = scale;
|
||||
for (let i = 6; i >= 1; i--) {
|
||||
cssLines.push(` --text-h${i}: ${currentSize}rem;`);
|
||||
cssLines.push(` --text-h${i}-sm: ${currentSize * 0.9}rem;`);
|
||||
currentSize *= scale;
|
||||
}
|
||||
|
||||
cssLines.push("}");
|
||||
|
||||
// Ensure output directory exists
|
||||
const outputDir = path.dirname(outputPath);
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Write the file
|
||||
fs.writeFileSync(outputPath, cssLines.join("\n") + "\n");
|
||||
console.log("✅ Theme CSS generated successfully at:", outputPath);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to generate theme CSS: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate CSS on startup
|
||||
try {
|
||||
generateThemeCSS();
|
||||
} catch (error) {
|
||||
console.error("❌ Error:", error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check for --watch flag
|
||||
if (process.argv.includes("--watch")) {
|
||||
let debounceTimer;
|
||||
|
||||
const watcher = fs.watch(themePath, (eventType) => {
|
||||
if (eventType === "change") {
|
||||
// Debounce to avoid multiple triggers
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
try {
|
||||
generateThemeCSS();
|
||||
} catch (error) {
|
||||
console.error("❌ Error regenerating theme CSS:", error.message);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on("SIGINT", () => {
|
||||
clearTimeout(debounceTimer);
|
||||
watcher.close();
|
||||
console.log("\n👋 Watcher stopped");
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
console.log("👁️ Watching for changes to:", themePath);
|
||||
}
|
||||
124
scripts/themeSetup.js
Normal file
124
scripts/themeSetup.js
Normal file
@@ -0,0 +1,124 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// const toggleComment = ({ filepath, regex }) => {
|
||||
// let updatedContent = fs.readFileSync(filepath, "utf8");
|
||||
// const match = updatedContent.match(regex);
|
||||
|
||||
// if (match) {
|
||||
// const matchedContent = match[0];
|
||||
// const hasComment = matchedContent.startsWith("# ");
|
||||
// if (hasComment) {
|
||||
// const hasBreakline = matchedContent.includes("\n");
|
||||
// if (hasBreakline) {
|
||||
// updatedContent = updatedContent.replace(
|
||||
// regex,
|
||||
// matchedContent.replace(/# /gm, ""),
|
||||
// );
|
||||
// fs.writeFileSync(filepath, updatedContent, "utf8");
|
||||
// }
|
||||
// } else {
|
||||
// updatedContent = updatedContent.replace(regex, "# " + matchedContent);
|
||||
// fs.writeFileSync(filepath, updatedContent, "utf8");
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
const createNewfolder = (rootfolder, folderName) => {
|
||||
const newFolder = path.join(rootfolder, folderName);
|
||||
fs.mkdirSync(newFolder, { recursive: true });
|
||||
return newFolder;
|
||||
};
|
||||
|
||||
const deleteFolder = (folderPath) => {
|
||||
if (fs.existsSync(folderPath)) {
|
||||
fs.rmSync(folderPath, { recursive: true, force: true });
|
||||
}
|
||||
};
|
||||
|
||||
const getFolderName = (rootfolder) => {
|
||||
const configPath = path.join(rootfolder, "exampleSite/hugo.toml");
|
||||
const getConfig = fs.readFileSync(configPath, "utf8");
|
||||
const match = getConfig.match(/theme\s*=\s*\[?"([^"\]]+)"\]?/);
|
||||
let selectedTheme = null;
|
||||
if (match && match[1]) {
|
||||
selectedTheme = match[1];
|
||||
}
|
||||
return selectedTheme;
|
||||
};
|
||||
|
||||
const iterateFilesAndFolders = (rootFolder, { destinationRoot }) => {
|
||||
const directory = path.join(rootFolder);
|
||||
const items = fs.readdirSync(directory, { withFileTypes: true });
|
||||
items.forEach((item) => {
|
||||
if (item.isDirectory()) {
|
||||
createNewfolder(destinationRoot, item.name);
|
||||
iterateFilesAndFolders(path.join(directory, item.name), {
|
||||
currentFolder: item.name,
|
||||
destinationRoot: path.join(destinationRoot, item.name),
|
||||
});
|
||||
} else {
|
||||
const sourceFile = path.join(directory, item.name);
|
||||
const destinationFile = path.join(destinationRoot, item.name);
|
||||
fs.renameSync(sourceFile, destinationFile);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setupTheme = () => {
|
||||
const rootFolder = path.join(__dirname, "../");
|
||||
|
||||
if (!fs.existsSync(path.join(rootFolder, "exampleSite"))) {
|
||||
// remove this part if you don't using theme demo as a module
|
||||
// [
|
||||
// {
|
||||
// filepath: path.join(rootFolder, "config/_default/module.toml"),
|
||||
// regex: /# \[\[imports\]\]\s*\r?\n# path = "([^"]+)"/,
|
||||
// },
|
||||
// {
|
||||
// filepath: path.join(rootFolder, "hugo.toml"),
|
||||
// regex: /^.*theme\s*=\s*("[^"\]]+"|\S+)/m,
|
||||
// },
|
||||
// ].forEach(toggleComment);
|
||||
|
||||
const includesFiles = [
|
||||
"go.mod",
|
||||
"hugo.toml",
|
||||
"assets",
|
||||
"config",
|
||||
"data",
|
||||
"content",
|
||||
"i18n",
|
||||
"static",
|
||||
"tailwind-plugin",
|
||||
];
|
||||
|
||||
const folder = createNewfolder(rootFolder, "exampleSite");
|
||||
|
||||
fs.readdirSync(rootFolder, { withFileTypes: true }).forEach((file) => {
|
||||
if (includesFiles.includes(file.name)) {
|
||||
if (file.isDirectory()) {
|
||||
const destination = path.join(rootFolder, "exampleSite", file.name);
|
||||
fs.mkdirSync(destination, { recursive: true });
|
||||
iterateFilesAndFolders(path.join(rootFolder, file.name), {
|
||||
destinationRoot: destination,
|
||||
});
|
||||
deleteFolder(path.join(rootFolder, file.name));
|
||||
} else {
|
||||
fs.renameSync(
|
||||
path.join(rootFolder, file.name),
|
||||
path.join(folder, file.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const themes = path.join(rootFolder, "themes");
|
||||
iterateFilesAndFolders(path.join(themes, getFolderName(rootFolder)), {
|
||||
destinationRoot: rootFolder,
|
||||
});
|
||||
deleteFolder(themes);
|
||||
}
|
||||
};
|
||||
|
||||
setupTheme();
|
||||
19
scripts/themeUpdate.js
Normal file
19
scripts/themeUpdate.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const { exec } = require("child_process");
|
||||
|
||||
const repositoryUrl = "https://github.com/zeon-studio/hugoplate";
|
||||
const localDirectory = "./themes/hugoplate";
|
||||
const foldersToFetch = ["assets", "layouts"];
|
||||
const foldersToSkip = ["exampleSite"];
|
||||
|
||||
const fetchFolder = (folder) => {
|
||||
exec(
|
||||
`curl -L ${repositoryUrl}/tarball/main | tar -xz --strip-components=1 --directory=${localDirectory} --exclude=$(curl -sL ${repositoryUrl}/tarball/main | tar -tz | grep -E "/(${foldersToSkip.join(
|
||||
"|",
|
||||
)})/") */${folder}`,
|
||||
);
|
||||
};
|
||||
|
||||
// Fetch each specified folder
|
||||
foldersToFetch.forEach((folder) => {
|
||||
fetchFolder(folder);
|
||||
});
|
||||
Reference in New Issue
Block a user