From 92d49c2c54df84480b9d4c9b1cace5c657752ba6 Mon Sep 17 00:00:00 2001 From: Utsob Roy Date: Thu, 19 Jan 2023 15:31:35 +0600 Subject: [PATCH] A custom content taggification (#45) * a custom content taggification --- .eleventy.js | 489 +++++++++++++++------------- package-lock.json | 11 - package.json | 1 - src/site/_includes/layouts/note.njk | 2 +- src/site/index.njk | 2 +- 5 files changed, 266 insertions(+), 239 deletions(-) diff --git a/.eleventy.js b/.eleventy.js index 16e0897..6144b6b 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,241 +1,280 @@ const slugify = require("@sindresorhus/slugify"); const markdownIt = require("markdown-it"); -const fs = require('fs'); -const matter = require('gray-matter'); -const faviconPlugin = require('eleventy-favicon'); -const tocPlugin = require('eleventy-plugin-toc'); -const {parse} = require("node-html-parser") +const fs = require("fs"); +const matter = require("gray-matter"); +const faviconPlugin = require("eleventy-favicon"); +const tocPlugin = require("eleventy-plugin-toc"); +const { parse } = require("node-html-parser"); -const {headerToId, namedHeadingsFilter} = require("./src/helpers/utils") +const { headerToId, namedHeadingsFilter } = require("./src/helpers/utils"); -module.exports = function(eleventyConfig) { - - let markdownLib = markdownIt({ - breaks: true, - html: true - }) - .use(require("markdown-it-footnote")) - .use(require("markdown-it-hashtag"), { - hashtagRegExp: `[^\\s!@\\#\\$%\\^&\\*\\(\\)=\\+\\.,\\[\\{\\]\\};:'"\\?><]+`, - preceding: "^|\\s", - }) - .use(function(md){ - md.renderer.rules.hashtag_open = function(tokens, idx) { - return '' - } - }) - .use(require('markdown-it-mathjax3'), { - tex: { - inlineMath: [ - ["$", "$"] - ] - }, - options: { - skipHtmlTags: { '[-]': ['pre'] } - } - }) - .use(require("markdown-it-attrs")) - .use(require('markdown-it-task-checkbox'), { - disabled: true, - divWrap: false, - divClass: 'checkbox', - idPrefix: 'cbx_', - ulClass: 'task-list', - liClass: 'task-list-item' - }) - .use(require('markdown-it-plantuml'), { - openMarker: '```plantuml', - closeMarker: '```' - }) - .use(namedHeadingsFilter) - .use(function(md) { - //https://github.com/DCsunset/markdown-it-mermaid-plugin - const origFenceRule = md.renderer.rules.fence || function(tokens, idx, options, env, self) { - return self.renderToken(tokens, idx, options, env, self); - }; - md.renderer.rules.fence = (tokens, idx, options, env, slf) => { - const token = tokens[idx]; - if (token.info === 'mermaid') { - const code = token.content.trim(); - return `
${code}
`; - } - if (token.info === 'transclusion') { - const code = token.content.trim(); - return `
${md.render(code)}
`; - } - if (token.info.startsWith("ad-")) { - const code = token.content.trim(); - if (code && code.toLowerCase().startsWith("title:")) { - const title = code.substring(6, code.indexOf("\n")); - const titleDiv = title ? `
${title}
` : ''; - - return `
${titleDiv}\n
${md.render(code.slice(code.indexOf("\n")))}
`; - } - - const title = `
${ - token.info.charAt(3).toUpperCase()}${token.info.substring(4).toLowerCase() - }
` - - return `
${title}\n
${md.render(code)}
`; - } - - // Other languages - return origFenceRule(tokens, idx, options, env, slf); - }; - - - - const defaultImageRule = md.renderer.rules.image || function(tokens, idx, options, env, self) { - return self.renderToken(tokens, idx, options, env, self); - }; - md.renderer.rules.image = (tokens, idx, options, env, self) => { - const imageName = tokens[idx].content; - const [fileName, width] = imageName.split("|"); - if (width) { - const widthIndex = tokens[idx].attrIndex('width'); - const widthAttr = `${width}px`; - if (widthIndex < 0) { - tokens[idx].attrPush(['width', widthAttr]); - } else { - tokens[idx].attrs[widthIndex][1] = widthAttr; - } - } - - return defaultImageRule(tokens, idx, options, env, self); - }; - - - const defaultLinkRule = md.renderer.rules.link_open || function(tokens, idx, options, env, self) { - return self.renderToken(tokens, idx, options, env, self); - }; - md.renderer.rules.link_open = function(tokens, idx, options, env, self) { - const aIndex = tokens[idx].attrIndex('target'); - const classIndex = tokens[idx].attrIndex('class'); - - if (aIndex < 0) { - tokens[idx].attrPush(['target', '_blank']); - } else { - tokens[idx].attrs[aIndex][1] = '_blank'; - } - - if (classIndex < 0) { - tokens[idx].attrPush(['class', 'external-link']); - } else { - tokens[idx].attrs[classIndex][1] = 'external-link'; - } - - return defaultLinkRule(tokens, idx, options, env, self); - }; - - }); - - eleventyConfig.setLibrary("md", markdownLib); - - eleventyConfig.addFilter('link', function(str) { - return str && str.replace(/\[\[(.*?\|.*?)\]\]/g, function(match, p1) { - //Check if it is an embedded excalidraw drawing or mathjax javascript - if (p1.indexOf("],[") > -1 || p1.indexOf('"$"') > -1) { - return match; - } - const [fileLink, linkTitle] = p1.split("|"); - - let fileName = fileLink; - let header = ""; - let headerLinkPath = ""; - if (fileLink.includes("#")) { - [fileName, header] = fileLink.split("#"); - headerLinkPath = `#${headerToId(header)}`; - } - - let permalink = `/notes/${slugify(fileName)}`; - const title = linkTitle ? linkTitle : fileName; - let deadLink = false; - - try { - const startPath = './src/site/notes/'; - const fullPath = fileName.endsWith('.md') ? - `${startPath}${fileName}` - :`${startPath}${fileName}.md`; - const file = fs.readFileSync(fullPath, 'utf8'); - const frontMatter = matter(file); - if (frontMatter.data.permalink) { - permalink = frontMatter.data.permalink; - } - } catch { - deadLink = true; - } - - return `
${title}`; - }); +module.exports = function (eleventyConfig) { + let markdownLib = markdownIt({ + breaks: true, + html: true, + }) + .use(require("markdown-it-footnote")) + .use(function (md) { + md.renderer.rules.hashtag_open = function (tokens, idx) { + return ''; + }; }) + .use(require("markdown-it-mathjax3"), { + tex: { + inlineMath: [["$", "$"]], + }, + options: { + skipHtmlTags: { "[-]": ["pre"] }, + }, + }) + .use(require("markdown-it-attrs")) + .use(require("markdown-it-task-checkbox"), { + disabled: true, + divWrap: false, + divClass: "checkbox", + idPrefix: "cbx_", + ulClass: "task-list", + liClass: "task-list-item", + }) + .use(require("markdown-it-plantuml"), { + openMarker: "```plantuml", + closeMarker: "```", + }) + .use(namedHeadingsFilter) + .use(function (md) { + //https://github.com/DCsunset/markdown-it-mermaid-plugin + const origFenceRule = + md.renderer.rules.fence || + function (tokens, idx, options, env, self) { + return self.renderToken(tokens, idx, options, env, self); + }; + md.renderer.rules.fence = (tokens, idx, options, env, slf) => { + const token = tokens[idx]; + if (token.info === "mermaid") { + const code = token.content.trim(); + return `
${code}
`; + } + if (token.info === "transclusion") { + const code = token.content.trim(); + return `
${md.render(code)}
`; + } + if (token.info.startsWith("ad-")) { + const code = token.content.trim(); + if (code && code.toLowerCase().startsWith("title:")) { + const title = code.substring(6, code.indexOf("\n")); + const titleDiv = title + ? `
${title}
` + : ""; - eleventyConfig.addFilter('highlight', function(str) { - return str && str.replace(/\=\=(.*?)\=\=/g, function(match, p1) { - return `${p1}`; - }); - }); + return `
${titleDiv}\n
${md.render( + code.slice(code.indexOf("\n")) + )}
`; + } + const title = `
${token.info + .charAt(3) + .toUpperCase()}${token.info + .substring(4) + .toLowerCase()}
`; - eleventyConfig.addTransform('callout-block', function(str) { - const parsed = parse(str); - - const transformCalloutBlocks = (blockquotes = parsed.querySelectorAll("blockquote")) => { - for (const blockquote of blockquotes) { - transformCalloutBlocks(blockquote.querySelectorAll("blockquote")) - - let content = blockquote.innerHTML; - - let titleDiv = ""; - let calloutType = ""; - let isCollapsable; - let isCollapsed; - const calloutMeta = /\[!(\w*)\](\+|\-){0,1}(\s?.*)/; - if (!content.match(calloutMeta)) { - continue; - } - - content = content.replace(calloutMeta, function(metaInfoMatch, callout, collapse, title) { - isCollapsable = Boolean(collapse); - isCollapsed = collapse === "-" - const titleText = title.replace(/(<\/{0,1}\w+>)/, "") ? title : `${callout.charAt(0).toUpperCase()}${callout.substring(1).toLowerCase()}` - const fold = isCollapsable ? `
` : `` - - calloutType = callout; - titleDiv = `
${titleText}
${fold}
` - return ""; - }); - - blockquote.tagName = "div"; - blockquote.classList.add("callout"); - blockquote.classList.add(isCollapsable ? "is-collapsible" : "") - blockquote.classList.add(isCollapsed ? "is-collapsed" : "") - blockquote.setAttribute("data-callout", calloutType.toLowerCase()); - blockquote.innerHTML = `${titleDiv}\n
${content}
`; - } + return `
${title}\n
${md.render( + code + )}
`; } - transformCalloutBlocks(); - - return str && parsed.innerHTML; + // Other languages + return origFenceRule(tokens, idx, options, env, slf); + }; + + const defaultImageRule = + md.renderer.rules.image || + function (tokens, idx, options, env, self) { + return self.renderToken(tokens, idx, options, env, self); + }; + md.renderer.rules.image = (tokens, idx, options, env, self) => { + const imageName = tokens[idx].content; + const [fileName, width] = imageName.split("|"); + if (width) { + const widthIndex = tokens[idx].attrIndex("width"); + const widthAttr = `${width}px`; + if (widthIndex < 0) { + tokens[idx].attrPush(["width", widthAttr]); + } else { + tokens[idx].attrs[widthIndex][1] = widthAttr; + } + } + + return defaultImageRule(tokens, idx, options, env, self); + }; + + const defaultLinkRule = + md.renderer.rules.link_open || + function (tokens, idx, options, env, self) { + return self.renderToken(tokens, idx, options, env, self); + }; + md.renderer.rules.link_open = function (tokens, idx, options, env, self) { + const aIndex = tokens[idx].attrIndex("target"); + const classIndex = tokens[idx].attrIndex("class"); + + if (aIndex < 0) { + tokens[idx].attrPush(["target", "_blank"]); + } else { + tokens[idx].attrs[aIndex][1] = "_blank"; + } + + if (classIndex < 0) { + tokens[idx].attrPush(["class", "external-link"]); + } else { + tokens[idx].attrs[classIndex][1] = "external-link"; + } + + return defaultLinkRule(tokens, idx, options, env, self); + }; }); - eleventyConfig.addPassthroughCopy("src/site/img"); - eleventyConfig.addPlugin(faviconPlugin, { destination: 'dist' }); - eleventyConfig.addPlugin(tocPlugin, {ul:true, tags: ['h1','h2', 'h3', 'h4', 'h5', 'h6']}); - eleventyConfig.addFilter('jsonify', function (variable) { - return JSON.stringify(variable) || '""'; - }); + eleventyConfig.setLibrary("md", markdownLib); - return { - dir: { - input: "src/site", - output: "dist", - data: `_data` - }, - templateFormats: ["njk", "md", "11ty.js", "css"], - htmlTemplateEngine: "njk", - markdownTemplateEngine: "njk", - passthroughFileCopy: true, + eleventyConfig.addFilter("link", function (str) { + return ( + str && + str.replace(/\[\[(.*?\|.*?)\]\]/g, function (match, p1) { + //Check if it is an embedded excalidraw drawing or mathjax javascript + if (p1.indexOf("],[") > -1 || p1.indexOf('"$"') > -1) { + return match; + } + const [fileLink, linkTitle] = p1.split("|"); + + let fileName = fileLink; + let header = ""; + let headerLinkPath = ""; + if (fileLink.includes("#")) { + [fileName, header] = fileLink.split("#"); + headerLinkPath = `#${headerToId(header)}`; + } + + let permalink = `/notes/${slugify(fileName)}`; + const title = linkTitle ? linkTitle : fileName; + let deadLink = false; + + try { + const startPath = "./src/site/notes/"; + const fullPath = fileName.endsWith(".md") + ? `${startPath}${fileName}` + : `${startPath}${fileName}.md`; + const file = fs.readFileSync(fullPath, "utf8"); + const frontMatter = matter(file); + if (frontMatter.data.permalink) { + permalink = frontMatter.data.permalink; + } + } catch { + deadLink = true; + } + + return `
${title}`; + }) + ); + }); + + eleventyConfig.addFilter("highlight", function (str) { + return ( + str && + str.replace(/\=\=(.*?)\=\=/g, function (match, p1) { + return `${p1}`; + }) + ); + }); + + eleventyConfig.addFilter("taggify", function (str) { + return ( + str && + str.replace( + /(^|\s|\>)(#[^\s!@#$%^&*()=+\.\/,\[{\]};:'"?><]+)(?!([^<]*>))/g, + function (match, precede, tag) { + return `${precede}${tag}`; + } + ) + ); + }); + + eleventyConfig.addTransform("callout-block", function (str) { + const parsed = parse(str); + + const transformCalloutBlocks = ( + blockquotes = parsed.querySelectorAll("blockquote") + ) => { + for (const blockquote of blockquotes) { + transformCalloutBlocks(blockquote.querySelectorAll("blockquote")); + + let content = blockquote.innerHTML; + + let titleDiv = ""; + let calloutType = ""; + let isCollapsable; + let isCollapsed; + const calloutMeta = /\[!(\w*)\](\+|\-){0,1}(\s?.*)/; + if (!content.match(calloutMeta)) { + continue; + } + + content = content.replace( + calloutMeta, + function (metaInfoMatch, callout, collapse, title) { + isCollapsable = Boolean(collapse); + isCollapsed = collapse === "-"; + const titleText = title.replace(/(<\/{0,1}\w+>)/, "") + ? title + : `${callout.charAt(0).toUpperCase()}${callout + .substring(1) + .toLowerCase()}`; + const fold = isCollapsable + ? `
` + : ``; + + calloutType = callout; + titleDiv = `
${titleText}
${fold}
`; + return ""; + } + ); + + blockquote.tagName = "div"; + blockquote.classList.add("callout"); + blockquote.classList.add(isCollapsable ? "is-collapsible" : ""); + blockquote.classList.add(isCollapsed ? "is-collapsed" : ""); + blockquote.setAttribute("data-callout", calloutType.toLowerCase()); + blockquote.innerHTML = `${titleDiv}\n
${content}
`; + } }; + transformCalloutBlocks(); + + return str && parsed.innerHTML; + }); + + eleventyConfig.addPassthroughCopy("src/site/img"); + eleventyConfig.addPlugin(faviconPlugin, { destination: "dist" }); + eleventyConfig.addPlugin(tocPlugin, { + ul: true, + tags: ["h1", "h2", "h3", "h4", "h5", "h6"], + }); + eleventyConfig.addFilter("jsonify", function (variable) { + return JSON.stringify(variable) || '""'; + }); + + return { + dir: { + input: "src/site", + output: "dist", + data: `_data`, + }, + templateFormats: ["njk", "md", "11ty.js", "css"], + htmlTemplateEngine: "njk", + markdownTemplateEngine: "njk", + passthroughFileCopy: true, + }; }; diff --git a/package-lock.json b/package-lock.json index 2442ab2..3359222 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,6 @@ "markdown-it": "^13.0.1", "markdown-it-attrs": "^4.1.6", "markdown-it-footnote": "^3.0.3", - "markdown-it-hashtag": "^0.4.0", "markdown-it-mathjax3": "^4.3.1", "markdown-it-plantuml": "^1.4.1", "markdown-it-task-checkbox": "^1.0.6" @@ -3490,11 +3489,6 @@ "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==" }, - "node_modules/markdown-it-hashtag": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/markdown-it-hashtag/-/markdown-it-hashtag-0.4.0.tgz", - "integrity": "sha512-+VCMH+f4/Ud5wPEtcAMrlLbUrrGViwR9JvjPy//X3Z7ZG1j5nQuHtDLTGZfMhkqYTMY+cTZgZkVNBsXMfU93Yg==" - }, "node_modules/markdown-it-mathjax3": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz", @@ -9183,11 +9177,6 @@ "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==" }, - "markdown-it-hashtag": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/markdown-it-hashtag/-/markdown-it-hashtag-0.4.0.tgz", - "integrity": "sha512-+VCMH+f4/Ud5wPEtcAMrlLbUrrGViwR9JvjPy//X3Z7ZG1j5nQuHtDLTGZfMhkqYTMY+cTZgZkVNBsXMfU93Yg==" - }, "markdown-it-mathjax3": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz", diff --git a/package.json b/package.json index 2da80c7..8b839ee 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "markdown-it": "^13.0.1", "markdown-it-attrs": "^4.1.6", "markdown-it-footnote": "^3.0.3", - "markdown-it-hashtag": "^0.4.0", "markdown-it-mathjax3": "^4.3.1", "markdown-it-plantuml": "^1.4.1", "markdown-it-task-checkbox": "^1.0.6" diff --git a/src/site/_includes/layouts/note.njk b/src/site/_includes/layouts/note.njk index 355765b..fd70688 100644 --- a/src/site/_includes/layouts/note.njk +++ b/src/site/_includes/layouts/note.njk @@ -37,7 +37,7 @@ permalink: "notes/{{ page.fileSlug | slugify }}/" {% endif %} - {{ content | link | highlight | safe}} + {{ content | link | taggify | highlight | safe}} {% if settings.dgShowBacklinks === true or settings.dgShowLocalGraph === true or settings.dgShowToc === true%} diff --git a/src/site/index.njk b/src/site/index.njk index ed0f11e..e6372b8 100644 --- a/src/site/index.njk +++ b/src/site/index.njk @@ -35,7 +35,7 @@ {%- for garden in collections.gardenEntry -%} - {{garden.templateContent | link | highlight | safe }} + {{garden.templateContent | link | taggify | highlight | safe }} {%- endfor -%}