1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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",
},
};
};
|