diff --git a/.eleventy.js b/.eleventy.js
index 4c1ee82..1e981d1 100644
--- a/.eleventy.js
+++ b/.eleventy.js
@@ -3,6 +3,10 @@ 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 {headerToId, namedHeadingsFilter} = require("./src/helpers/utils")
+
module.exports = function(eleventyConfig) {
let markdownLib = markdownIt({
@@ -184,6 +188,7 @@ module.exports = function(eleventyConfig) {
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);
});
@@ -201,47 +206,3 @@ module.exports = function(eleventyConfig) {
};
};
-
-function headerToId(heading) {
- return slugify(heading);
-}
-
-//https://github.com/rstacruz/markdown-it-named-headings/blob/master/index.js
-function namedHeadingsFilter(md, options) {
- md.core.ruler.push('named_headings', namedHeadings.bind(null, md));
-}
-
-function namedHeadings(md, state) {
-
- var ids = {}
-
- state.tokens.forEach(function(token, i) {
- if (token.type === 'heading_open') {
- var text = md.renderer.render(state.tokens[i + 1].children, md.options)
- var id = headerToId(text);
- var uniqId = uncollide(ids, id)
- ids[uniqId] = true
- setAttr(token, 'id', uniqId)
- }
- })
-}
-
-function uncollide(ids, id) {
- if (!ids[id]) return id
- var i = 1
- while (ids[id + '-' + i]) { i++ }
- return id + '-' + i
-}
-
-function setAttr(token, attr, value, options) {
- var idx = token.attrIndex(attr)
-
- if (idx === -1) {
- token.attrPush([attr, value])
- } else if (options && options.append) {
- token.attrs[idx][1] =
- token.attrs[idx][1] + ' ' + value
- } else {
- token.attrs[idx][1] = value
- }
-}
diff --git a/package-lock.json b/package-lock.json
index 70d2bca..2a4b6cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"axios": "^0.26.1",
"dotenv": "^10.0.0",
"eleventy-favicon": "^1.1.2",
+ "eleventy-plugin-toc": "^1.1.5",
"fs-file-tree": "^1.1.1",
"gray-matter": "^4.0.3",
"lunr": "^2.3.9",
@@ -1729,6 +1730,14 @@
"to-ico": "^1.1.5"
}
},
+ "node_modules/eleventy-plugin-toc": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/eleventy-plugin-toc/-/eleventy-plugin-toc-1.1.5.tgz",
+ "integrity": "sha512-Fo5AZZSBH8CKvz0axJQA9nmnTFOflAMFrngaKER4rOz3C6oDwqxK8N+kNFepmIsieTPkrH+iREWLJ+/9j5JjUg==",
+ "dependencies": {
+ "cheerio": "^1.0.0-rc.10"
+ }
+ },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -7649,6 +7658,14 @@
"to-ico": "^1.1.5"
}
},
+ "eleventy-plugin-toc": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/eleventy-plugin-toc/-/eleventy-plugin-toc-1.1.5.tgz",
+ "integrity": "sha512-Fo5AZZSBH8CKvz0axJQA9nmnTFOflAMFrngaKER4rOz3C6oDwqxK8N+kNFepmIsieTPkrH+iREWLJ+/9j5JjUg==",
+ "requires": {
+ "cheerio": "^1.0.0-rc.10"
+ }
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
diff --git a/package.json b/package.json
index ed31bfa..af9b980 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"axios": "^0.26.1",
"dotenv": "^10.0.0",
"eleventy-favicon": "^1.1.2",
+ "eleventy-plugin-toc": "^1.1.5",
"fs-file-tree": "^1.1.1",
"gray-matter": "^4.0.3",
"lunr": "^2.3.9",
diff --git a/src/helpers/constants.js b/src/helpers/constants.js
index b6ed90a..110be22 100644
--- a/src/helpers/constants.js
+++ b/src/helpers/constants.js
@@ -5,5 +5,6 @@ exports.ALL_NOTE_SETTINGS= [
"dgShowLocalGraph",
"dgShowInlineTitle",
"dgShowFileTree",
- "dgEnableSearch"
+ "dgEnableSearch",
+ "dgShowToc"
];
\ No newline at end of file
diff --git a/src/helpers/utils.js b/src/helpers/utils.js
new file mode 100644
index 0000000..03ddd38
--- /dev/null
+++ b/src/helpers/utils.js
@@ -0,0 +1,47 @@
+const slugify = require("@sindresorhus/slugify");
+
+function headerToId(heading) {
+ return slugify(heading);
+}
+
+function namedHeadings(md, state) {
+
+ var ids = {}
+
+ state.tokens.forEach(function(token, i) {
+ if (token.type === 'heading_open') {
+ var text = md.renderer.render(state.tokens[i + 1].children, md.options)
+ var id = headerToId(text);
+ var uniqId = uncollide(ids, id)
+ ids[uniqId] = true
+ setAttr(token, 'id', uniqId)
+ }
+ })
+}
+
+function uncollide(ids, id) {
+ if (!ids[id]) return id
+ var i = 1
+ while (ids[id + '-' + i]) { i++ }
+ return id + '-' + i
+}
+
+function setAttr(token, attr, value, options) {
+ var idx = token.attrIndex(attr)
+
+ if (idx === -1) {
+ token.attrPush([attr, value])
+ } else if (options && options.append) {
+ token.attrs[idx][1] =
+ token.attrs[idx][1] + ' ' + value
+ } else {
+ token.attrs[idx][1] = value
+ }
+}
+
+//https://github.com/rstacruz/markdown-it-named-headings/blob/master/index.js
+exports.namedHeadingsFilter = function (md, options) {
+ md.core.ruler.push('named_headings', namedHeadings.bind(null, md));
+}
+
+exports.headerToId = headerToId;
\ No newline at end of file
diff --git a/src/site/_includes/components/graphScript.njk b/src/site/_includes/components/graphScript.njk
index 0fd67bf..8ed2d14 100644
--- a/src/site/_includes/components/graphScript.njk
+++ b/src/site/_includes/components/graphScript.njk
@@ -117,7 +117,7 @@
ctx.textBaseline = 'top';
ctx.fillText(label, node.x, node.y + nodeR + 2);
})
- .linkColor(() => getCssVar("--text-normal"))
+ .linkColor(() => getCssVar("--text-muted") || getCssVar("--text-normal"))
.graphData(gData)
.onNodeClick(node => {
window.location = node.url;
diff --git a/src/site/_includes/components/sidebar.njk b/src/site/_includes/components/sidebar.njk
index 3ba90e9..bcd70e9 100644
--- a/src/site/_includes/components/sidebar.njk
+++ b/src/site/_includes/components/sidebar.njk
@@ -5,32 +5,53 @@
{%if settings.dgShowLocalGraph === true%}
-
Interactive graph
+
Connected Pages
- {%endif%}
+ {%endif%}
- {%if settings.dgShowBacklinks === true %}
-
-
Links to this page
- {%- if backlinks.length === 0 -%}
-
- No backlinks
+ {%if settings.dgShowToc === true%}
+ {%set tocHtml= (content and (content|toc)) %}
+ {%if tocHtml %}
+
+
+
+ {{ tocHtml | safe }}
+
- {%- endif -%}
+ {%endif%}
- {%- for backlink in backlinks -%}
-
-
{{backlink.title}}
+ {%endif%}
+
+ {%if settings.dgShowBacklinks === true %}
+
+
Pages mentioning this page
+
+
+ {%- if backlinks.length === 0 -%}
+
+ No other pages mentions this page
+
+ {%- endif -%}
+
+ {%- for backlink in backlinks -%}
+
+ {%- endfor -%}
+
+
- {%- endfor -%}
+ {%endif%}
+
- {%endif%}
-
-
-
+
-{%if settings.dgShowLocalGraph === true %}
- {%include "components/graphScript.njk"%}
-{% endif %}
+ {%if settings.dgShowLocalGraph === true %}
+ {%include "components/graphScript.njk"%}
+ {% endif %}
\ No newline at end of file
diff --git a/src/site/_includes/layouts/note.njk b/src/site/_includes/layouts/note.njk
index 8201b25..4c09231 100644
--- a/src/site/_includes/layouts/note.njk
+++ b/src/site/_includes/layouts/note.njk
@@ -27,7 +27,7 @@ permalink: "notes/{{ page.fileSlug | slugify }}/"
{% endif %}
{{ content | link | highlight | safe}}
- {% if settings.dgShowBacklinks === true or settings.dgShowLocalGraph === true%}
+ {% if settings.dgShowBacklinks === true or settings.dgShowLocalGraph === true or settings.dgShowToc === true%}
{%include "components/sidebar.njk"%}
{% endif %}
diff --git a/src/site/index.11tydata.js b/src/site/index.11tydata.js
index af1e457..21c20e0 100644
--- a/src/site/index.11tydata.js
+++ b/src/site/index.11tydata.js
@@ -4,6 +4,11 @@ const settings = require("../helpers/constants");
const wikilink = /\[\[(.*?\|.*?)\]\]/g
+const markdownIt = require("markdown-it");
+const md = markdownIt({
+ html: true,
+}).use(require("../helpers/utils").namedHeadingsFilter);
+
function caselessCompare(a, b) {
return a.toLowerCase() === b.toLowerCase();
}
@@ -111,6 +116,13 @@ module.exports = {
return currentnote.data.page.fileSlug;
}
return "";
+ },
+ content: (data) => {
+ const currentnote = data.collections.gardenEntry && data.collections.gardenEntry[0];
+ if (currentnote && currentnote.template && currentnote.template.frontMatter && currentnote.template.frontMatter.content) {
+ return md.render(currentnote.template.frontMatter.content);
+ }
+ return "";
}
}
}
\ No newline at end of file
diff --git a/src/site/index.njk b/src/site/index.njk
index 9dddb70..d2b1019 100644
--- a/src/site/index.njk
+++ b/src/site/index.njk
@@ -24,7 +24,7 @@
{%- endfor -%}
- {%if settings.dgShowBacklinks === true or settings.dgShowLocalGraph === true%}
+ {% if settings.dgShowBacklinks === true or settings.dgShowLocalGraph === true or settings.dgShowToc === true%}
{%include "components/sidebar.njk" %}
{%endif%}
diff --git a/src/site/notes/notes.11tydata.js b/src/site/notes/notes.11tydata.js
index fad1677..ff26d7d 100644
--- a/src/site/notes/notes.11tydata.js
+++ b/src/site/notes/notes.11tydata.js
@@ -99,6 +99,6 @@ module.exports = {
noteSettings[setting] = settingValue;
});
return noteSettings;
- }
+ }
}
}
\ No newline at end of file
diff --git a/src/site/styles/digital-garden-base.scss b/src/site/styles/digital-garden-base.scss
index 44e43b4..c21d45a 100644
--- a/src/site/styles/digital-garden-base.scss
+++ b/src/site/styles/digital-garden-base.scss
@@ -6,6 +6,7 @@
body {
overflow-x: hidden;
}
+
.content {
max-width: 800px;
margin: auto;
@@ -72,14 +73,13 @@ ul.task-list {
.sidebar {
position: fixed;
top: 50%;
- transform: translateY(-50%);
+ transform: translateY(calc(-50% + 75px));
right: 0;
height: 100%;
min-width: 25px;
display: flex;
z-index: 3;
max-width: 350px;
- margin-top: 75px;
}
.expand-line {
@@ -92,11 +92,67 @@ ul.task-list {
padding-right: 20px;
width: 100%;
overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ height: 87%;
+}
+
+.toc {
+ padding-right: 5px;
+ background-color: var(--background-primary);
+ padding: 10px;
+ border-radius: 10px;
+}
+
+.toc-container {
+ font-size: 1rem;
+ max-height: 220px;
+ overflow-y: auto;
+ margin-bottom:10px;
+ border-left: 1px solid var(--text-accent);
+ ul {
+ list-style-type: none;
+ padding-inline-start: 15px !important;
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ ul:not(:first-child) {
+ margin-bottom:3px;
+ }
+
+ li{
+ padding-top: 4px;
+ &::before{
+ content: '# ' !important;
+ color: var(--text-accent);
+ font-size: 0.8rem;
+ }
+ a{
+ text-decoration: none;
+ &:hover{
+ text-decoration: underline;
+ }
+ }
+ }
+}
+
+.toc-title-container {
+ display: flex;
+ justify-content: flex-start;
+ .toc-title {
+ font-size: 1.2rem !important;
+ color: var(--h6-color);
+ width: fit-content;
+ padding: 3px 7px 3px 0;
+ border-radius: 10px 10px 0 0;
+ }
}
.backlinks {
- margin-top: 50px;
- background-color: var(--background-secondary);
+ flex: 1;
+ margin-top: 10px;
+ background-color: var(--background-primary);
border-radius: 10px;
padding: 10px;
@@ -107,20 +163,37 @@ ul.task-list {
}
}
+.backlink-list {
+ border-left: 1px solid var(--text-accent);
+ max-height: 200px;
+ overflow-y: auto;
+ overflow-x:hidden;
+}
+
.backlink-card {
- padding-bottom: 4px;
+ padding-bottom: 8px;
border-radius: 4px;
width: 100%;
font-size: 1rem;
+ margin-left: 10px;
+ color: var(--text-accent);
+ i {
+ font-size: 0.8rem;
+ }
}
-.graph{
- .graph-title{
+.no-backlinks-message{
+ font-size: 0.8rem;
+ color: var(--text-normal);
+}
+
+.graph {
+ .graph-title {
width: fit-content;
background-color: var(--background-secondary);
margin: 10px 0 0 0;
- padding: 12px;
- font-size: 18px !important;
+ padding: 3px 7px;
+ font-size: 1.2rem !important;
border-radius: 10px 10px 0 0;
color: var(--h6-color);
}
@@ -141,9 +214,10 @@ ul.task-list {
margin-top: 50px;
}
- .graph{
+ .graph {
display: none;
}
+
.backlinks {
margin-top: 0;
}
@@ -152,24 +226,24 @@ ul.task-list {
.filetree-sidebar {
margin: 0;
z-index: 10;
- padding: 10px;
- top:0px;
- left:0;
- position: fixed;
- height: 100%;
- background-color: var(--background-secondary);
- color: var(--text-muted);
- overflow-y:auto;
+ padding: 10px;
+ top: 0px;
+ left: 0;
+ position: fixed;
+ height: 100%;
+ background-color: var(--background-secondary);
+ color: var(--text-muted);
+ overflow-y: auto;
width: 250px;
}
.empty-navbar {
- display: flex;
- justify-content: flex-end;
+ display: flex;
+ justify-content: flex-end;
margin-bottom: -60px;
@media(max-width: 800px) {
- justify-content: center;
+ justify-content: center;
}
.search-button {
@@ -191,12 +265,12 @@ ul.task-list {
align-items: center;
.navbar-inner {
- display: flex;
- align-items: center;
+ display: flex;
+ align-items: center;
cursor: pointer;
}
- .search-button{
+ .search-button {
@media(max-width: 800px) {
min-width: 120px;
@@ -207,6 +281,11 @@ ul.task-list {
.notelink {
padding: 5px 0 5px 25px;
+ a{
+ &:hover {
+ text-decoration: underline !important;
+ }
+ }
}
.foldername-wrapper {
@@ -219,31 +298,31 @@ ul.task-list {
}
.filelist {
- border-left: 1px solid var(--text-accent);
}
-.notelink.active-note{
- a{
+.notelink.active-note {
+ a {
color: var(--text-accent);
}
+
color: var(--text-accent);
background-color: var(--background-primary);
transform: translateX(10px);
}
-.fullpage-overlay{
- background-color: rgba(0,0,0,0.5);
- position: absolute;
- top:0;
- right:0;
- left:0;
- bottom:0;
+.fullpage-overlay {
+ background-color: rgba(0, 0, 0, 0.5);
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
z-index: 5
}
.search-container {
- background-color: rgba(0,0,0,0.5);
+ background-color: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
right: 0;
@@ -279,6 +358,7 @@ ul.task-list {
color: var(--text-primary);
}
+
.search-box input:focus {
outline: none;
}
@@ -317,6 +397,7 @@ ul.task-list {
color: var(--text-secondary);
margin-right: 20px;
}
+
.search-link {
display: block;
margin-bottom: 4px;
@@ -333,14 +414,16 @@ ul.task-list {
margin: 10px 65px;
border: 1px solid var(--text-normal);
cursor: pointer;
- >span{
+
+ >span {
padding: 3px 3px 3px 10px;
}
- >i{
+
+ >i {
margin-left: 10px;
}
- &:hover{
+ &:hover {
border: 1px solid var(--text-accent);
}