Compare commits

...

2 Commits

Author SHA1 Message Date
7a7b894bd5 Added settings API. 2023-08-04 19:52:57 +02:00
7415e9d529 Use templates instead of direct sources. 2023-08-04 17:40:20 +02:00
8 changed files with 355 additions and 232 deletions

4
.gitignore vendored
View File

@ -130,4 +130,8 @@ dist
.yarn/install-state.gz
.pnp.*
# Project-related files
config.yml
src/_settings.scss
src/main.scss
out/

View File

@ -1,21 +1,66 @@
import sass from "sass"
import fs from "fs"
import { log } from "console"
import YAML from "yaml"
import parseTemplate from "./parseTemplate.js"
const { css } = sass.compile(
"./src/main.scss",
{ style: "compressed" }
)
export default function buildNebulosa(debug) {
log("Generating Nebulosa CSS...")
const now = new Date()
.toISOString()
.replace(/\.\S+/g, "")
.replace(/:/g, ".")
.replace(/T/g, "_")
log("Reading config...")
if (!fs.existsSync("./config.yml")) {
log("No config file found!")
log("Copying 'example-config.yml' to 'config.yml'...")
fs.copyFileSync("./example-config.yml", "config.yml")
}
const config = YAML.parse(fs.readFileSync("./config.yml").toString())
if (!fs.existsSync("./out"))
fs.mkdirSync("./out")
log("Reading templates...")
const templateFiles = fs.readdirSync("./src/templates")
const templates = templateFiles.map(
fileName => {
return {
fileName,
content: fs.readFileSync(`./src/templates/${fileName}`).toString()
}
}
)
fs.writeFileSync(
`./out/${now}.css`,
"/* Generated using Nebulosa CSS. https://git.qwik.space/BurnyLlama/nebulosa-css */\n" + css
)
log("Executing templates...")
templates.forEach(
template => {
const compiledTemplate = parseTemplate(template.content, config)
fs.writeFileSync(`./src/${template.fileName}`, compiledTemplate)
}
)
log("Compiling SCSS...")
const { css } = sass.compile(
"./src/main.scss",
{ style: "compressed" }
)
const now = new Date()
.toISOString()
.replace(/\.\S+/g, "")
.replace(/:/g, ".")
.replace(/T/g, "_")
const outFileName = debug ? "./out/main.css" : `./out/${now}.css`
if (!fs.existsSync("./out"))
fs.mkdirSync("./out")
log("Writing file...")
fs.writeFileSync(
outFileName,
"/* Generated using Nebulosa CSS. https://git.qwik.space/BurnyLlama/nebulosa-css */\n" + css
)
log(`Saved config file to ./out/${now}.css`)
}
// If the file is run directly from the commandline, build Nebulosa.
if (import.meta.url === `file://${process.argv[0]}`) {
buildNebulosa(false)
}

45
dev.js
View File

@ -2,7 +2,7 @@ import chokidar from "chokidar"
import express from "express"
import fs from "fs"
import njk from "nunjucks"
import sass from "sass"
import buildNebulosa from "./build.js"
const server = express()
@ -17,35 +17,24 @@ njk.configure(
}
)
chokidar.watch("./src").on("change", () => {
console.log("Detected changes in SCSS! Recompiling...")
// Do an initial build of Nebulosa, then watch for changes...
buildNebulosa(true)
chokidar
.watch(["./src", "./config.yml", "./example-config.yml"])
.on(
"change",
() => {
console.log("Detected changes in SCSS or config! Recompiling...")
try {
const { css } = sass.compile(
"./src/main.scss",
{
sourceMap: false,
alertColor: true,
style: "compressed"
try {
buildNebulosa(true)
console.log("Saved!")
} catch (error) {
console.log("Error while compiling!")
console.error(error)
}
)
console.log("Compile done! Saving changes...")
if (!fs.existsSync("./out"))
fs.mkdirSync("./out")
fs.writeFileSync(
"./out/main.css",
css
)
console.log("Saved!")
} catch (error) {
console.log("Error while compiling!")
console.error(error)
}
})
}
)
server.use("/assets", express.static("./out"))

View File

@ -20,7 +20,8 @@
"chokidar": "^3.5.3",
"express": "^4.18.2",
"nunjucks": "^3.2.3",
"sass": "^1.58.3"
"sass": "^1.58.3",
"yaml": "^2.3.1"
},
"devDependencies": {
"eslint": "^8.35.0"

69
parseTemplate.js Normal file
View File

@ -0,0 +1,69 @@
import { log, error } from "console"
/**
* Flattens an object into a 1 level deep object.
* { a: { b: 1, c: 2 } } --> { "a.b": 1, "a.c": 2 }
* @param {Object} object
* @return {Object}
*/
function flattenObject(object) {
let finalObject = {}
for (const key in object) {
// Skip if key isn't own.
if (!Object.prototype.hasOwnProperty.call(object, key))
continue
if (typeof object[key] === "object" && object[key] !== null) {
const flattenedObject = flattenObject(object[key])
for (const innerKey in flattenedObject) {
// Skip if key isn't own.
if (!Object.prototype.hasOwnProperty.call(flattenedObject, innerKey))
continue
finalObject[`${key}.${innerKey}`] = flattenedObject[innerKey]
}
} else {
finalObject[key] = object[key]
}
}
return finalObject
}
export default function parseTemplate(template, data) {
const flattenedData = flattenObject(data)
log("Loaded config:")
return template
// Syntax: {{ variableName }}
// Does: Inserts a variable, if it exists.
.replace(
/{{\s*(.+)\s*}}/gm,
(match, variableName) => {
if (flattenedData[variableName] === undefined || flattenedData[variableName] === null) {
error(`Error: ${variableName} is not defined!`)
process.exit(1)
}
log(`${variableName} = ${flattenedData[variableName]}`)
return flattenedData[variableName]
}
)
// Syntax:
// {% if variableName %}
// <code to include>
// {% endif %}
// Does: includes <code to include> if variableName exists and is true.
.replace(
/^{%\s*if\s*(.+)\s*%}$([\s\S]*?)^{%\s*endif\s*%}$/gm,
(match, variableName, codeBlock) => {
if (flattenedData[variableName] === undefined || flattenedData[variableName] === null) {
error(`Error: ${variableName} is not defined!`)
process.exit(1)
}
log(`${variableName} = ${flattenedData[variableName]}`)
return flattenedData[variableName] ? codeBlock : ""
}
)
}

File diff suppressed because it is too large Load Diff