diff options
Diffstat (limited to '.eleventy.js')
-rw-r--r-- | .eleventy.js | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/.eleventy.js b/.eleventy.js new file mode 100644 index 0000000..2ffec7d --- /dev/null +++ b/.eleventy.js @@ -0,0 +1,95 @@ +const fs = require("fs"); +const hljs = require("highlight.js"); +const twemoji = require("twemoji"); +const { DateTime } = require("luxon"); +const utils = require("markdown-it/lib/common/utils"); + +const excerptMinimumLength = 280; +const excerptSeparator = "<!--more-->" + +function extractExcerpt(doc) { + if (doc.data.readOnline) return "[[ No Excerpt Available ]]"; + if (doc.data.excerpt) return doc.data.excerpt; + + if (!doc.hasOwnProperty("templateContent")) { + console.warn("Failed to extract excerpt: Document has no property `templateContent`."); + return ""; + } + + const content = doc.templateContent; + if (content.includes(excerptSeparator)) + return content.substring(0, content.indexOf(excerptSeparator)).trim(); + else if (content.length <= excerptMinimumLength) return content.trim(); + + const excerptEnd = findExcerptEnd(content); + return content.substring(0, excerptEnd).trim(); +} + +function findExcerptEnd(content, skipLength = 0) { + if (content === "") return 0; + const paragraphEnd = content.indexOf("</p>", skipLength) + 4; + return paragraphEnd + ((paragraphEnd < excerptMinimumLength)? + findExcerptEnd(content.substring(paragraphEnd), paragraphEnd):0); +} + +function demark(content) { + return content.replace(/<mark>(.*?)<\/mark>/gis, (m,a) => "█".repeat(a.length)) +} + +module.exports = (cfg) => { + cfg.addPlugin(require("@11ty/eleventy-plugin-rss")); + cfg.addFilter("excerpt", post => extractExcerpt(post)); + cfg.addFilter("demark", content => demark(content)); + cfg.addFilter("date", (date, fmt) => + DateTime.fromJSDate(date).toFormat(fmt)); + cfg.addPassthroughCopy({"static": "./"}); + cfg.setDataDeepMerge(true); + + cfg.addFilter("fixAnchors", (c,u) => + c.replace(/<a class="header-anchor" href="/g, "$&"+u)); + + const md = require("markdown-it")({ + typographer: true, html: true, + highlight: (str, lang) => { + if (lang && hljs.getLanguage(lang)) { try { + return '<pre class="hljs"><code>' + + hljs.highlight(str, { language: lang, ignoreIllegals: true }).value + + '</code></pre>'; + } catch (__) {} } + return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'; + } + + }).use(require("markdown-it-anchor"), { + permalink: true, permalinkBefore: true, permalinkSymbol: "#"}) + .use(require("markdown-it-emoji"), {shortcuts: {}}) + .use(require("markdown-it-mark")); + + md.renderer.rules.emoji = (token, i) => + `<span class="emoji-container emoji_${token[i].markup}" ` + + `title="${token[i].markup}">${twemoji.parse(token[i].content)}</span>`; + md.renderer.rules.code_block = (tokens, i, options, env, slf) => + `<pre${slf.renderAttrs(tokens[i])}><code>` + + utils.escapeHtml(tokens[i].content.replace(/ /g, "\xA0"))+'</code></pre>\n'; + + cfg.setLibrary("md", md); + + cfg.setBrowserSyncConfig({callbacks: { + ready: (e,b) => b.addMiddleware("*", (req, res) => { + res.writeHead(404, { "Content-Type": "text/html; charset=UTF-8" }); + res.write(fs.readFileSync("build/404.html")); + res.end(); + }) + }}); + + return { + templateFormats: ["md", "njk"], + markdownTemplateEngine: "njk", + dir: { + input: "posts", + output: "build", + data: "../globals", + layouts: "../layouts", + includes: "../includes", + }, + }; +}; |