diff --git a/assets/css/article.css b/assets/css/article.css
index 3a4c5a6..bf99285 100644
--- a/assets/css/article.css
+++ b/assets/css/article.css
@@ -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);
diff --git a/content/errors/404.njk b/content/errors/404.njk
index 72498fe..93e56b5 100644
--- a/content/errors/404.njk
+++ b/content/errors/404.njk
@@ -1,8 +1,7 @@
-
-
+ {% include "templates/defaultTags.njk" %}
{{ serverName }} - Error 404
diff --git a/index.js b/index.js
index 93aafe6..f928620 100644
--- a/index.js
+++ b/index.js
@@ -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 '<'
+ 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)
diff --git a/libs/codeHighlighter.js b/libs/codeHighlighter.js
new file mode 100644
index 0000000..7b1a51a
--- /dev/null
+++ b/libs/codeHighlighter.js
@@ -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
tags.
+ .value.replace(/\n/g, "
")
+ // Replace spaces with ' ' to forcefully render them.
+ .replace(/ /g, " "
+ )
+}
\ No newline at end of file
diff --git a/libs/externalContext.js b/libs/externalContext.js
index 8e5d2dc..dc82a1a 100644
--- a/libs/externalContext.js
+++ b/libs/externalContext.js
@@ -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/, "")
})
diff --git a/libs/generateContext.js b/libs/generateContext.js
new file mode 100644
index 0000000..5f35ef8
--- /dev/null
+++ b/libs/generateContext.js
@@ -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(`${anchor.getAttribute('data-orig-text')}`))
+
+ 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
+ }
+}
+
diff --git a/libs/markedRenderer.js b/libs/markedRenderer.js
index 3c17982..a19789b 100644
--- a/libs/markedRenderer.js
+++ b/libs/markedRenderer.js
@@ -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, "
")
- .replace(/ /g, " "
- )
-}
+import { highlight } from "./codeHighlighter.js"
export const markedRenderer = {
+ // Rendering of headings (add an anchor above all headings).
heading(text, level) {
return `
@@ -19,6 +11,7 @@ export const markedRenderer = {
`
},
+ // Render code properly, and syntax highlight it.
code(code, lang, escaped) {
return `
diff --git a/libs/requestHandler.js b/libs/requestHandler.js
index 8dd7787..4cb0d58 100644
--- a/libs/requestHandler.js
+++ b/libs/requestHandler.js
@@ -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`))
}
\ No newline at end of file
diff --git a/libs/siteRenderer.js b/libs/siteRenderer.js
index 259a277..e86e008 100644
--- a/libs/siteRenderer.js
+++ b/libs/siteRenderer.js
@@ -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(`${anchor.getAttribute('data-orig-text')}`))
-
- 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)
}
\ No newline at end of file