Basic refactoring.

master
BurnyLlama 2021-08-07 10:46:48 +02:00
parent e5e0599bf6
commit 53bd81a8af
9 changed files with 78 additions and 55 deletions

View File

@ -15,9 +15,10 @@ article > header {
display: grid;
place-items: center;
width: min(100%, 45ch);
width: fit-content;
padding: 1rem 2rem;
margin: 0 auto;
padding: 1rem 4rem;
background-color: var(--grey3);
border-radius: .5rem;
box-shadow: 0 1rem 2rem var(--grey1);

View File

@ -1,8 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% include "templates/defaultTags.njk" %}
<title>{{ serverName }} - Error 404</title>
</head>
<body>

View File

@ -15,29 +15,33 @@ const Config = JSON.parse(ConfigFile)
// Create a server object
const Server = express()
// Some config
// Configure the assets directory
Server.use('/assets', express.static(Config.assetsDir))
// Configure the nunjucks environment (HTML templating)
const njkEnv = njk.configure(
Config.contentDir,
{
autoescape: true,
watch: true,
trimBlocks: true,
lstripBlocks: true,
express: Server
autoescape: true, // Automatically escape HTML aka a '<' will become '&lt;'
watch: true, // Automatically reload all templates if they change on disk.
trimBlocks: true, // Remove trailing newlines from tags
lstripBlocks: true, // Automatically remove leading whitespace from tags
express: Server // Use the express server. (Currently obsolete, I think.)
}
)
// Configure marked (markdown parser)
marked.use({
gfm: true,
renderer: markedRenderer
gfm: true, // Use GitHub formatting?
renderer: markedRenderer // Use my own custom rendering for som tags
})
// Let nunjucks use markdown.
njkMarkdown.register(njkEnv, marked)

16
libs/codeHighlighter.js Normal file
View File

@ -0,0 +1,16 @@
import hljs from 'highlight.js'
export function highlight(code, lang) {
// Check if hljs recognises the language, else assume 'plaintext'.
const language = hljs.getLanguage(lang) ? lang : 'plaintext'
// Highlight it with the corresponding language.
return hljs.highlight(
// Switch out bullet points (•) to spaces (for proper indentation).
code.replace(/•/g, " "), { language })
// Replace newlines with <br> tags.
.value.replace(/\n/g, "<br>")
// Replace spaces with '&nbsp;' to forcefully render them.
.replace(/ /g, "&nbsp;"
)
}

View File

@ -1,13 +1,13 @@
export function parseExternalContext(externalContext) {
// Remove start and end tag
externalContext = externalContext.replace(/%%-\n|-%%\n/g, "")
let parsedContext = {}
externalContext.split("\n").forEach(line => {
// If the line is falsey; leave.
if (!line) return
// Assign properties to parsedContext and give them values.
// Assign properties to parsedContext and give them their corresponding values.
line = line.split(/:/)
parsedContext[line[0]] = line[1].replace(/^\s/, "")
})

26
libs/generateContext.js Normal file
View File

@ -0,0 +1,26 @@
import { JSDOM } from 'jsdom'
import { parseExternalContext } from './externalContext.js'
function generateToc(dom) {
// Get all ToC anchors from the DOM
const tocAnchors = dom.window.document.querySelectorAll(".toc-anchor")
// Generate links to lead to those anvhors.
let tocLinks = []
tocAnchors.forEach(anchor => tocLinks.push(`<a href="#${anchor.name}" class="${anchor.classList[1].replace("-anchor", "")}">${anchor.getAttribute('data-orig-text')}</a>`))
return tocLinks
}
export function generateContext(prerenderedNjk, externalContext = undefined) {
// Create a 'virtual DOM' for analysis.
const dom = new JSDOM(prerenderedNjk)
// Generate respective parts of the context.
return {
serverName: Config.serverName,
tocLinks: generateToc(dom),
externalMeta: externalContext ? parseExternalContext(externalContext) : undefined
}
}

View File

@ -1,15 +1,7 @@
import hljs from 'highlight.js'
function highlight(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext'
return hljs.highlight(
code.replace(/•/g, " "), { language })
.value.replace(/\n/g, "<br>")
.replace(/ /g, "&nbsp;"
)
}
import { highlight } from "./codeHighlighter.js"
export const markedRenderer = {
// Rendering of headings (add an anchor above all headings).
heading(text, level) {
return `
<a name="${text.replace(/\s/g, "-")}" data-orig-text="${text}" class="toc-anchor toc-anchor-h${level}"></a>
@ -19,6 +11,7 @@ export const markedRenderer = {
`
},
// Render code properly, and syntax highlight it.
code(code, lang, escaped) {
return `
<pre>

View File

@ -1,19 +1,21 @@
import fs from 'fs'
import { mdRenderer, njkRenderer } from './siteRenderer.js'
// Handle all request and try to find a corresponding file/template.
export function requestHandler(req, res, Config) {
// Check for njk files first
if (fs.existsSync(`./${Config.contentDir}/pages/${req.path}.njk`))
return res.send(njkRenderer(`./${Config.contentDir}/pages/${req.path}.njk`))
if (fs.existsSync(`./${Config.contentDir}/pages/${req.path}/index.njk`))
return res.send(njkRenderer(`./${Config.contentDir}/pages/${req.path}/index.njk`))
// Secondly search for markdown
if (fs.existsSync(`./${Config.contentDir}/pages/${req.path}.md`))
return res.send(mdRenderer(`./${Config.contentDir}/pages/${req.path}.md`))
if (fs.existsSync(`./${Config.contentDir}/pages/${req.path}/index.md`))
return res.send(mdRenderer(`./${Config.contentDir}/pages/${req.path}/index.md`))
// If no matching file is found, return a 404 error.
return res.status(404).send(njkRenderer(`./${Config.contentDir}/errors/404.njk`))
}

View File

@ -1,38 +1,19 @@
import fs from 'fs'
import njk from 'nunjucks'
import { JSDOM } from 'jsdom'
import { parseExternalContext } from './externalContext.js'
import { generateContext } from './generateContext.js'
// Load in config
const ConfigFile = fs.readFileSync('./config.json')
const Config = JSON.parse(ConfigFile)
function generateToc(dom) {
const tocAnchors = dom.window.document.querySelectorAll(".toc-anchor")
let tocLinks = []
// This basically creates a proper link for the ToC. :)))
tocAnchors.forEach(anchor => tocLinks.push(`<a href="#${anchor.name}" class="${anchor.classList[1].replace("-anchor", "")}">${anchor.getAttribute('data-orig-text')}</a>`))
return tocLinks
}
function generateContext(renderedNjk, externalContext = undefined) {
const dom = new JSDOM(renderedNjk)
return {
serverName: Config.serverName,
tocLinks: generateToc(dom),
externalMeta: externalContext ? parseExternalContext(externalContext) : undefined
}
}
export function njkRenderer(path) {
// Read in the template
const njkFile = fs.readFileSync(path).toString()
const renderedNjk = njk.renderString(njkFile)
const context = generateContext(renderedNjk)
// Pre-render it for analysis while rendering context
const prerenderedNjk = njk.renderString(njkFile)
// Generate proper context and make a final render of the template.
const context = generateContext(prerenderedNjk)
return njk.renderString(njkFile, context)
}
@ -45,10 +26,11 @@ export function mdRenderer(path) {
const externalMarkdown = externalMarkdownFile.replace(/^%%-\n[\S\s]*-%%\n/, "").replace(/```\w*[\s\S]*?```/g, match => match.replace(/ /g, "•"))
const externalContext = externalMarkdownFile.match(/^%%-\n[\S\s]*-%%\n/)[0]
const renderedNjk = njk.renderString(njkFile, { externalMarkdown })
// Pre-render the template for analysis during context generation.
const prerenderedNjk = njk.renderString(njkFile, { externalMarkdown })
let context = generateContext(renderedNjk, externalContext)
// Generate the context and add the externalMarkdown to the context, then render the template.
let context = generateContext(prerenderedNjk, externalContext)
context.externalMarkdown = externalMarkdown
return njk.renderString(njkFile, context)
}