Spaces:
Running
Running
const path = require("path"); | |
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); | |
const CopyPlugin = require("copy-webpack-plugin"); | |
const Handlebars = require("handlebars"); | |
const fs = require("fs"); | |
const COLOR_KEYS = ["color", "bgColor", "fillcolor"]; | |
const FRAGMENTS_PATH = "src/fragments"; | |
// Transform the color names into colors defined in colors.mjs | |
const transformDataColors = async (data, path) => { | |
const {getNamedColor} = await import('./src/colors.mjs'); | |
// if not json file, return | |
if (!path.endsWith(".json")) { | |
return data; | |
} | |
const parsedData = JSON.parse(data); | |
// Change the color of the data | |
const deepIterateAndSetColor = (key, val) => { | |
if (val === null) { | |
return null; | |
} | |
if (val == undefined) { | |
return undefined; | |
} | |
if (Array.isArray(val)) { | |
return val.map(item => deepIterateAndSetColor(key, item)); | |
} | |
if (typeof val === "object") { | |
return Object.entries(val).reduce((newObj, [key, value]) => { | |
newObj[key] = deepIterateAndSetColor(key, value); | |
return newObj; | |
}, {}); | |
} | |
if (COLOR_KEYS.includes(key)) { | |
const [colorName, opacity, ...rest] = val.trim().split(/\s+/); | |
const floatOpacity = parseFloat(opacity); | |
const newColor = getNamedColor(colorName, floatOpacity); | |
if (newColor !== undefined && rest.length === 0 && !isNaN(floatOpacity)) { | |
console.log(`key: ${key} in file ${path} changed from ${val} to ${newColor}`); | |
return newColor; | |
} else { | |
return val; | |
} | |
} | |
return val; | |
}; | |
return JSON.stringify(deepIterateAndSetColor(undefined, parsedData)) | |
}; | |
// Load the fragments from the fragments directory and caches it | |
const loadFragmentsMap = (() => { | |
let cachedFragments = null; | |
return async () => { | |
if (cachedFragments === null) { | |
cachedFragments = {}; | |
const walkDir = (dir, basePath = '') => { | |
const files = fs.readdirSync(dir); | |
files.forEach(file => { | |
const filePath = path.join(dir, file); | |
const relativePath = path.join(basePath, file); | |
if (fs.statSync(filePath).isDirectory()) { | |
walkDir(filePath, relativePath); | |
} else { | |
const dottedPath = relativePath.replace(/\\/g, '-').replace(/\//g, '-').replace(/\./g, '-'); | |
cachedFragments[dottedPath] = fs.readFileSync(filePath, "utf8"); | |
} | |
}); | |
}; | |
walkDir(FRAGMENTS_PATH); | |
} | |
return cachedFragments; | |
}; | |
})(); | |
const transformHandlebars = async (data, path) => { | |
const fragments = await loadFragmentsMap(); | |
console.log(`Available fragments: ${Object.keys(fragments).join(', ')}`); | |
// Load the template file | |
const template = Handlebars.compile(data.toString('utf8')); | |
const html = template(fragments); | |
return html; | |
}; | |
module.exports = { | |
entry: { | |
distill: "./src/distill.js", | |
main: "./src/index.js", | |
}, | |
output: { | |
filename: "[name].bundle.js", // The output file | |
path: path.resolve(__dirname, "dist"), // Output directory | |
}, | |
module: { | |
rules: [ | |
// { test: /\.css$/, use: ["style-loader", "css-loader"] }, | |
{ | |
test: /\.(js|mjs)$/, | |
exclude: /node_modules/, | |
use: { | |
loader: "babel-loader", | |
options: { | |
presets: ["@babel/preset-env"], | |
}, | |
}, | |
}, | |
], | |
}, | |
plugins: [ | |
new CleanWebpackPlugin(), | |
new CopyPlugin({ | |
patterns: [ | |
{ | |
from: "assets", | |
to: "assets", | |
transform: transformDataColors, | |
}, | |
{ from: "src/style.css", to: "style.css" }, | |
{ from: "src/bibliography.bib", to: "bibliography.bib" }, | |
{ | |
from: "src/**/*.html.handlebars", | |
to: ({context, absoluteFilename}) => { | |
const contextWithSrc = `${context}/src`; | |
const relativePath = absoluteFilename.replace(contextWithSrc, '').replace(/^\//, ''); | |
const htmlPath = relativePath.replace(/\.handlebars$/, ''); | |
return htmlPath; | |
}, | |
transform: transformHandlebars, | |
noErrorOnMissing: true | |
}, | |
], | |
}), | |
], | |
devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'eval-source-map', | |
devServer: { | |
static: "./dist", // Serve files from the 'dist' directory | |
open: process.env.NODE_ENV !== 'production', // Automatically open the browser unless in production | |
hot: process.env.NODE_ENV !== 'production', // Enable hot module replacement unless in production | |
}, | |
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', | |
}; | |
console.log(process.env.NODE_ENV) |