Initial commit
This commit is contained in:
commit
40cf711943
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
github: maximevaillancourt
|
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Something's broken with the template
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- If you're requesting a new feature or suggesting an idea, please use the "Discussions" tab instead of opening a new issue. Thank you! -->
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- Operating system: [e.g. macOS 11.4]
|
||||||
|
- Ruby version: [e.g. Ruby 2.7.1]
|
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
name: Something else
|
||||||
|
about: Something's wrong, but it's not a bug with the template
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- If you're requesting a new feature or suggesting an idea, please use the "Discussions" tab instead of opening a new issue. Thank you! -->
|
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Generated website directory
|
||||||
|
_site/
|
||||||
|
|
||||||
|
# Sass cache
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Jekyll cache & metadata
|
||||||
|
.jekyll-cache/
|
||||||
|
.jekyll-metadata
|
||||||
|
|
||||||
|
# Notes graph metadata
|
||||||
|
_includes/notes_graph.json
|
||||||
|
|
||||||
|
# Obsidian config
|
||||||
|
.obsidian/
|
11
404.html
Normal file
11
404.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
permalink: 404.html
|
||||||
|
layout: default
|
||||||
|
title: "404"
|
||||||
|
id: "not-found"
|
||||||
|
---
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>Oops, that's a 404. 🙈</h1>
|
||||||
|
<p>Looks like this page doesn't exist. <a href="/">Return home</a> to get a fresh start.</p>
|
||||||
|
</div>
|
10
Gemfile
Normal file
10
Gemfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||||
|
|
||||||
|
gem "jekyll", "~> 4.0"
|
||||||
|
gem "jekyll-last-modified-at", git: "https://github.com/maximevaillancourt/jekyll-last-modified-at", branch: "add-support-for-files-in-git-submodules"
|
||||||
|
gem "webrick", "~> 1.7"
|
||||||
|
gem "nokogiri"
|
86
Gemfile.lock
Normal file
86
Gemfile.lock
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
GIT
|
||||||
|
remote: https://github.com/maximevaillancourt/jekyll-last-modified-at
|
||||||
|
revision: e0c918691db625401ef5850a030da59d0124d356
|
||||||
|
branch: add-support-for-files-in-git-submodules
|
||||||
|
specs:
|
||||||
|
jekyll-last-modified-at (1.3.0)
|
||||||
|
jekyll (>= 3.7, < 5.0)
|
||||||
|
posix-spawn (~> 0.3.9)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
addressable (2.8.0)
|
||||||
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
|
colorator (1.1.0)
|
||||||
|
concurrent-ruby (1.1.7)
|
||||||
|
em-websocket (0.5.2)
|
||||||
|
eventmachine (>= 0.12.9)
|
||||||
|
http_parser.rb (~> 0.6.0)
|
||||||
|
eventmachine (1.2.7)
|
||||||
|
ffi (1.14.2)
|
||||||
|
forwardable-extended (2.6.0)
|
||||||
|
http_parser.rb (0.6.0)
|
||||||
|
i18n (1.8.5)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
jekyll (4.2.0)
|
||||||
|
addressable (~> 2.4)
|
||||||
|
colorator (~> 1.0)
|
||||||
|
em-websocket (~> 0.5)
|
||||||
|
i18n (~> 1.0)
|
||||||
|
jekyll-sass-converter (~> 2.0)
|
||||||
|
jekyll-watch (~> 2.0)
|
||||||
|
kramdown (~> 2.3)
|
||||||
|
kramdown-parser-gfm (~> 1.0)
|
||||||
|
liquid (~> 4.0)
|
||||||
|
mercenary (~> 0.4.0)
|
||||||
|
pathutil (~> 0.9)
|
||||||
|
rouge (~> 3.0)
|
||||||
|
safe_yaml (~> 1.0)
|
||||||
|
terminal-table (~> 2.0)
|
||||||
|
jekyll-sass-converter (2.1.0)
|
||||||
|
sassc (> 2.0.1, < 3.0)
|
||||||
|
jekyll-watch (2.2.1)
|
||||||
|
listen (~> 3.0)
|
||||||
|
kramdown (2.3.1)
|
||||||
|
rexml
|
||||||
|
kramdown-parser-gfm (1.1.0)
|
||||||
|
kramdown (~> 2.0)
|
||||||
|
liquid (4.0.3)
|
||||||
|
listen (3.3.3)
|
||||||
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
|
mercenary (0.4.0)
|
||||||
|
mini_portile2 (2.8.0)
|
||||||
|
nokogiri (1.13.10)
|
||||||
|
mini_portile2 (~> 2.8.0)
|
||||||
|
racc (~> 1.4)
|
||||||
|
pathutil (0.16.2)
|
||||||
|
forwardable-extended (~> 2.6)
|
||||||
|
posix-spawn (0.3.15)
|
||||||
|
public_suffix (4.0.6)
|
||||||
|
racc (1.6.1)
|
||||||
|
rb-fsevent (0.10.4)
|
||||||
|
rb-inotify (0.10.1)
|
||||||
|
ffi (~> 1.0)
|
||||||
|
rexml (3.2.5)
|
||||||
|
rouge (3.26.0)
|
||||||
|
safe_yaml (1.0.5)
|
||||||
|
sassc (2.4.0)
|
||||||
|
ffi (~> 1.9)
|
||||||
|
terminal-table (2.0.0)
|
||||||
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||||
|
unicode-display_width (1.7.0)
|
||||||
|
webrick (1.7.0)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
jekyll (~> 4.0)
|
||||||
|
jekyll-last-modified-at!
|
||||||
|
nokogiri
|
||||||
|
webrick (~> 1.7)
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.2.3
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Released under MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Maxime Vaillancourt.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Digital garden Jekyll template + Searching
|
||||||
|
|
||||||
|
A template based off of [this template](https://github.com/maximevaillancourt/digital-garden-jekyll-template), incorporating a Jekyll search plugin from [here](https://github.com/christian-fei/Simple-Jekyll-Search).
|
||||||
|
|
||||||
|
- Based on Jekyll, a static website generator
|
||||||
|
- Supports Roam-style double bracket link syntax to other notes
|
||||||
|
- Creates backlinks to other notes automatically
|
||||||
|
- Features link previews on hover
|
||||||
|
- Includes graph visualization of the notes and their links
|
||||||
|
- Features a simple and responsive design
|
||||||
|
- Supports Markdown or HTML notes
|
||||||
|
- *NEW:* Supports searching of existing posts.
|
||||||
|
|
||||||
|
|
||||||
|
Source code is available under the [MIT license](LICENSE.md).
|
45
_config.yml
Normal file
45
_config.yml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
title: My digital garden
|
||||||
|
include: ['_pages']
|
||||||
|
exclude: ['_includes/notes_graph.json']
|
||||||
|
# You may need to change the base URL depending on your deploy configuration.
|
||||||
|
# Specifically, when using GitHub Pages, the baseurl should point to where GitHub
|
||||||
|
# Pages deploys your repository (which is usually the repository name).
|
||||||
|
baseurl: ''
|
||||||
|
|
||||||
|
# If you are using a host that cannot resolve URLs that do
|
||||||
|
# not end with .html (such as Neocities), set this to 'true'.
|
||||||
|
use_html_extension: false
|
||||||
|
|
||||||
|
# Set to `true` to open non-internal links in new tabs, or
|
||||||
|
# set to `false` to open non-internal links in current tab.
|
||||||
|
open_external_links_in_new_tab: true
|
||||||
|
|
||||||
|
# Set to `true` to replace tweet URLs with Twitter embeds.
|
||||||
|
# Note that doing so will negatively the reader's privacy
|
||||||
|
# as their browser will communicate with Twitter's servers.
|
||||||
|
embed_tweets: false
|
||||||
|
|
||||||
|
permalink: pretty
|
||||||
|
relative_permalinks: false
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- jekyll-last-modified-at
|
||||||
|
|
||||||
|
sass:
|
||||||
|
sass_dir: _sass
|
||||||
|
style: :compressed
|
||||||
|
|
||||||
|
collections:
|
||||||
|
notes:
|
||||||
|
output: true
|
||||||
|
permalink: /:slug
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
- scope:
|
||||||
|
path: "**/*"
|
||||||
|
values:
|
||||||
|
layout: "default"
|
||||||
|
- scope:
|
||||||
|
path: "_notes/**/*.md"
|
||||||
|
values:
|
||||||
|
layout: "note"
|
1
_includes/footer.html
Normal file
1
_includes/footer.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
This is the footer. Include anything you'd like here, like a link to an <a class="internal-link" href="/about">About</a> page, of a <a class="internal-link" href="/search">Search</a> page.
|
48
_includes/head.html
Normal file
48
_includes/head.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
<link rel="canonical" href="{{ site.url }}{{ page.url }}" />
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.title }}{% endif %}">
|
||||||
|
|
||||||
|
<meta property="og:site_name" content="{{ site.title }}">
|
||||||
|
|
||||||
|
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ site.baseurl }}/styles.css">
|
||||||
|
|
||||||
|
{% if page.excerpt %}
|
||||||
|
<meta property="og:description" content="{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}"/>
|
||||||
|
{% else %}
|
||||||
|
<meta property="og:description" content="{{ site.title | strip_html | strip_newlines | truncate: 160 }}"/>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page.title %}
|
||||||
|
<meta property="og:title" content="{{ page.title }}">
|
||||||
|
<meta property="og:type" content="article">
|
||||||
|
{% else %}
|
||||||
|
<meta property="og:title" content="{{ site.title }}">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page.date %}
|
||||||
|
<meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}">
|
||||||
|
<meta property="article:author" content="{{ site.url }}/">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<meta property="og:url" content="{{ site.url }}{{ page.url }}" />
|
||||||
|
|
||||||
|
{% if page.image %}
|
||||||
|
<meta property="og:image" content="{{ site.url }}{{ page.image }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<title>
|
||||||
|
{% if page.id == "home" %}
|
||||||
|
{{ site.title }}
|
||||||
|
{% else %}
|
||||||
|
{{ page.title }} — {{ site.title }}
|
||||||
|
{% endif %}
|
||||||
|
</title>
|
||||||
|
</head>
|
140
_includes/link-previews.html
Normal file
140
_includes/link-previews.html
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<!-- That file is not particularly elegant. This will need a refactor at some point. -->
|
||||||
|
<style>
|
||||||
|
content a.internal-link {
|
||||||
|
border-color: #8b88e6;
|
||||||
|
background-color: #efefff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tooltip-wrapper {
|
||||||
|
background: white;
|
||||||
|
padding: 1em;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
width: 400px;
|
||||||
|
height: 250px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
box-shadow: 0 5px 10px rgba(0,0,0,0.1);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 100ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tooltip-wrapper:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image: linear-gradient(to bottom, rgba(255,255,255, 0), rgba(255,255,255, 1) 90%);
|
||||||
|
width: 100%;
|
||||||
|
height: 75px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div style="opacity: 0; display: none;" id='tooltip-wrapper'>
|
||||||
|
<div id='tooltip-content'>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<iframe style="display: none; height: 0; width: 0;" id='link-preview-iframe' src="">
|
||||||
|
</iframe>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var opacityTimeout;
|
||||||
|
var contentTimeout;
|
||||||
|
var transitionDurationMs = 100;
|
||||||
|
|
||||||
|
var iframe = document.getElementById('link-preview-iframe')
|
||||||
|
var tooltipWrapper = document.getElementById('tooltip-wrapper')
|
||||||
|
var tooltipContent = document.getElementById('tooltip-content')
|
||||||
|
|
||||||
|
var linkHistories = {};
|
||||||
|
|
||||||
|
function hideTooltip() {
|
||||||
|
opacityTimeout = setTimeout(function() {
|
||||||
|
tooltipWrapper.style.opacity = 0;
|
||||||
|
contentTimeout = setTimeout(function() {
|
||||||
|
tooltipContent.innerHTML = '';
|
||||||
|
tooltipWrapper.style.display = 'none';
|
||||||
|
}, transitionDurationMs + 1);
|
||||||
|
}, transitionDurationMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTooltip(event) {
|
||||||
|
var elem = event.target;
|
||||||
|
var elem_props = elem.getClientRects()[elem.getClientRects().length - 1];
|
||||||
|
var top = window.pageYOffset || document.documentElement.scrollTop
|
||||||
|
|
||||||
|
if (event.target.host === window.location.host) {
|
||||||
|
if (!linkHistories[event.target.href]) {
|
||||||
|
iframe.src = event.target.href
|
||||||
|
iframe.onload = function() {
|
||||||
|
tooltipContentHtml = ''
|
||||||
|
tooltipContentHtml += '<div style="font-weight: bold;">' + iframe.contentWindow.document.querySelector('h1').innerHTML + '</div>'
|
||||||
|
tooltipContentHtml += iframe.contentWindow.document.querySelector('content').innerHTML
|
||||||
|
|
||||||
|
tooltipContent.innerHTML = tooltipContentHtml
|
||||||
|
linkHistories[event.target.href] = tooltipContentHtml
|
||||||
|
|
||||||
|
tooltipWrapper.style.display = 'block';
|
||||||
|
setTimeout(function() {
|
||||||
|
tooltipWrapper.style.opacity = 1;
|
||||||
|
}, 1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tooltipContent.innerHTML = linkHistories[event.target.href]
|
||||||
|
tooltipWrapper.style.display = 'block';
|
||||||
|
setTimeout(function() {
|
||||||
|
tooltipWrapper.style.opacity = 1;
|
||||||
|
}, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tooltipWrapper.style.left = elem_props.left - (tooltipWrapper.offsetWidth / 2) + (elem_props.width / 2) + "px";
|
||||||
|
if ((window.innerHeight - elem_props.top) < (tooltipWrapper.offsetHeight)) {
|
||||||
|
tooltipWrapper.style.top = elem_props.top + top - tooltipWrapper.offsetHeight - 10 + "px";
|
||||||
|
} else if ((window.innerHeight - elem_props.top) > (tooltipWrapper.offsetHeight)) {
|
||||||
|
tooltipWrapper.style.top = elem_props.top + top + 35 + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((elem_props.left + (elem_props.width / 2)) < (tooltipWrapper.offsetWidth / 2)) {
|
||||||
|
tooltipWrapper.style.left = "10px";
|
||||||
|
} else if ((document.body.clientWidth - elem_props.left - (elem_props.width / 2)) < (tooltipWrapper.offsetWidth / 2)) {
|
||||||
|
tooltipWrapper.style.left = document.body.clientWidth - tooltipWrapper.offsetWidth - 20 + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupListeners(linkElement) {
|
||||||
|
linkElement.addEventListener('mouseleave', function(_event) {
|
||||||
|
hideTooltip();
|
||||||
|
});
|
||||||
|
|
||||||
|
tooltipWrapper.addEventListener('mouseleave', function(_event) {
|
||||||
|
hideTooltip();
|
||||||
|
});
|
||||||
|
|
||||||
|
linkElement.addEventListener('touchend', function(_event) {
|
||||||
|
hideTooltip();
|
||||||
|
});
|
||||||
|
|
||||||
|
tooltipWrapper.addEventListener('touchend', function(_event) {
|
||||||
|
hideTooltip();
|
||||||
|
});
|
||||||
|
|
||||||
|
linkElement.addEventListener('mouseenter', function(event) {
|
||||||
|
clearTimeout(opacityTimeout);
|
||||||
|
clearTimeout(contentTimeout);
|
||||||
|
showTooltip(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
tooltipWrapper.addEventListener('mouseenter', function(event) {
|
||||||
|
clearTimeout(opacityTimeout);
|
||||||
|
clearTimeout(contentTimeout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('{{ include.wrapperQuerySelector }} a').forEach(setupListeners);
|
||||||
|
</script>
|
3
_includes/nav.html
Normal file
3
_includes/nav.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<a class="internal-link" href="{{ site.baseurl }}/"><b>{{ site.title }}</b></a>
|
||||||
|
</div>
|
306
_includes/notes_graph.html
Normal file
306
_includes/notes_graph.html
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
<style>
|
||||||
|
.links line {
|
||||||
|
stroke: #ccc;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodes circle {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: #8b88e6;
|
||||||
|
transition: all 0.15s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text text {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: #333;
|
||||||
|
text-shadow: -1px -1px 0 #fafafabb, 1px -1px 0 #fafafabb, -1px 1px 0 #fafafabb, 1px 1px 0 #fafafabb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodes [active],
|
||||||
|
.text [active] {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactive {
|
||||||
|
opacity: 0.1;
|
||||||
|
transition: all 0.15s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#graph-wrapper {
|
||||||
|
background: #fcfcfc;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="graph-wrapper">
|
||||||
|
<script>
|
||||||
|
window.addEventListener("load", loadGraph);
|
||||||
|
|
||||||
|
function loadGraph() {
|
||||||
|
var oScript = document.createElement("script");
|
||||||
|
oScript.src = "https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js";
|
||||||
|
oScript.crossOrigin = 'anonymous';
|
||||||
|
oScript.integrity =
|
||||||
|
"sha512-FHsFVKQ/T1KWJDGSbrUhTJyS1ph3eRrxI228ND0EGaEp6v4a/vGwPWd3Dtd/+9cI7ccofZvl/wulICEurHN1pg==";
|
||||||
|
document.body.appendChild(oScript);
|
||||||
|
oScript.onload = () => {
|
||||||
|
const MINIMAL_NODE_SIZE = 8;
|
||||||
|
const MAX_NODE_SIZE = 12;
|
||||||
|
const ACTIVE_RADIUS_FACTOR = 1.5;
|
||||||
|
const STROKE = 1;
|
||||||
|
const FONT_SIZE = 16;
|
||||||
|
const TICKS = 200;
|
||||||
|
const FONT_BASELINE = 40;
|
||||||
|
const MAX_LABEL_LENGTH = 50;
|
||||||
|
|
||||||
|
const graphData = {% include notes_graph.json %}
|
||||||
|
let nodesData = graphData.nodes;
|
||||||
|
let linksData = graphData.edges;
|
||||||
|
|
||||||
|
const nodeSize = {};
|
||||||
|
|
||||||
|
const updateNodeSize = () => {
|
||||||
|
nodesData.forEach((el) => {
|
||||||
|
let weight =
|
||||||
|
3 *
|
||||||
|
Math.sqrt(
|
||||||
|
linksData.filter((l) => l.source.id === el.id || l.target.id === el.id)
|
||||||
|
.length + 1
|
||||||
|
);
|
||||||
|
if (weight < MINIMAL_NODE_SIZE) {
|
||||||
|
weight = MINIMAL_NODE_SIZE;
|
||||||
|
} else if (weight > MAX_NODE_SIZE) {
|
||||||
|
weight = MAX_NODE_SIZE;
|
||||||
|
}
|
||||||
|
nodeSize[el.id] = weight;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClick = (d) => {
|
||||||
|
window.location = d.path
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMouseover = function (d) {
|
||||||
|
const relatedNodesSet = new Set();
|
||||||
|
linksData
|
||||||
|
.filter((n) => n.target.id == d.id || n.source.id == d.id)
|
||||||
|
.forEach((n) => {
|
||||||
|
relatedNodesSet.add(n.target.id);
|
||||||
|
relatedNodesSet.add(n.source.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.attr("class", (node_d) => {
|
||||||
|
if (node_d.id !== d.id && !relatedNodesSet.has(node_d.id)) {
|
||||||
|
return "inactive";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
||||||
|
link.attr("class", (link_d) => {
|
||||||
|
if (link_d.source.id !== d.id && link_d.target.id !== d.id) {
|
||||||
|
return "inactive";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
||||||
|
link.attr("stroke-width", (link_d) => {
|
||||||
|
if (link_d.source.id === d.id || link_d.target.id === d.id) {
|
||||||
|
return STROKE * 4;
|
||||||
|
}
|
||||||
|
return STROKE;
|
||||||
|
});
|
||||||
|
text.attr("class", (text_d) => {
|
||||||
|
if (text_d.id !== d.id && !relatedNodesSet.has(text_d.id)) {
|
||||||
|
return "inactive";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMouseout = function (d) {
|
||||||
|
node.attr("class", "");
|
||||||
|
link.attr("class", "");
|
||||||
|
text.attr("class", "");
|
||||||
|
link.attr("stroke-width", STROKE);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sameNodes = (previous, next) => {
|
||||||
|
if (next.length !== previous.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = new Map();
|
||||||
|
for (const node of previous) {
|
||||||
|
map.set(node.id, node.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const node of next) {
|
||||||
|
const found = map.get(node.id);
|
||||||
|
if (!found || found !== node.title) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const sameEdges = (previous, next) => {
|
||||||
|
if (next.length !== previous.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const set = new Set();
|
||||||
|
for (const edge of previous) {
|
||||||
|
set.add(`${edge.source.id}-${edge.target.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const edge of next) {
|
||||||
|
if (!set.has(`${edge.source.id}-${edge.target.id}`)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const graphWrapper = document.getElementById('graph-wrapper')
|
||||||
|
const element = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
|
element.setAttribute("width", graphWrapper.getBoundingClientRect().width);
|
||||||
|
element.setAttribute("height", window.innerHeight * 0.8);
|
||||||
|
graphWrapper.appendChild(element);
|
||||||
|
|
||||||
|
const reportWindowSize = () => {
|
||||||
|
element.setAttribute("width", window.innerWidth);
|
||||||
|
element.setAttribute("height", window.innerHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onresize = reportWindowSize;
|
||||||
|
|
||||||
|
const svg = d3.select("svg");
|
||||||
|
const width = Number(svg.attr("width"));
|
||||||
|
const height = Number(svg.attr("height"));
|
||||||
|
let zoomLevel = 1;
|
||||||
|
|
||||||
|
const simulation = d3
|
||||||
|
.forceSimulation(nodesData)
|
||||||
|
.force("forceX", d3.forceX().x(width / 2))
|
||||||
|
.force("forceY", d3.forceY().y(height / 2))
|
||||||
|
.force("charge", d3.forceManyBody())
|
||||||
|
.force(
|
||||||
|
"link",
|
||||||
|
d3
|
||||||
|
.forceLink(linksData)
|
||||||
|
.id((d) => d.id)
|
||||||
|
.distance(70)
|
||||||
|
)
|
||||||
|
.force("center", d3.forceCenter(width / 2, height / 2))
|
||||||
|
.force("collision", d3.forceCollide().radius(80))
|
||||||
|
.stop();
|
||||||
|
|
||||||
|
const g = svg.append("g");
|
||||||
|
let link = g.append("g").attr("class", "links").selectAll(".link");
|
||||||
|
let node = g.append("g").attr("class", "nodes").selectAll(".node");
|
||||||
|
let text = g.append("g").attr("class", "text").selectAll(".text");
|
||||||
|
|
||||||
|
const resize = () => {
|
||||||
|
if (d3.event) {
|
||||||
|
const scale = d3.event.transform;
|
||||||
|
zoomLevel = scale.k;
|
||||||
|
g.attr("transform", scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
const zoomOrKeep = (value) => (zoomLevel >= 1 ? value / zoomLevel : value);
|
||||||
|
|
||||||
|
const font = Math.max(Math.round(zoomOrKeep(FONT_SIZE)), 1);
|
||||||
|
|
||||||
|
text.attr("font-size", (d) => font);
|
||||||
|
text.attr("y", (d) => d.y - zoomOrKeep(FONT_BASELINE) + 8);
|
||||||
|
link.attr("stroke-width", zoomOrKeep(STROKE));
|
||||||
|
node.attr("r", (d) => {
|
||||||
|
return zoomOrKeep(nodeSize[d.id]);
|
||||||
|
});
|
||||||
|
svg
|
||||||
|
.selectAll("circle")
|
||||||
|
.filter((_d, i, nodes) => d3.select(nodes[i]).attr("active"))
|
||||||
|
.attr("r", (d) => zoomOrKeep(ACTIVE_RADIUS_FACTOR * nodeSize[d.id]));
|
||||||
|
};
|
||||||
|
|
||||||
|
const ticked = () => {
|
||||||
|
node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
|
||||||
|
text
|
||||||
|
.attr("x", (d) => d.x)
|
||||||
|
.attr("y", (d) => d.y - (FONT_BASELINE - nodeSize[d.id]) / zoomLevel);
|
||||||
|
link
|
||||||
|
.attr("x1", (d) => d.source.x)
|
||||||
|
.attr("y1", (d) => d.source.y)
|
||||||
|
.attr("x2", (d) => d.target.x)
|
||||||
|
.attr("y2", (d) => d.target.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
const restart = () => {
|
||||||
|
updateNodeSize();
|
||||||
|
node = node.data(nodesData, (d) => d.id);
|
||||||
|
node.exit().remove();
|
||||||
|
node = node
|
||||||
|
.enter()
|
||||||
|
.append("circle")
|
||||||
|
.attr("r", (d) => {
|
||||||
|
return nodeSize[d.id];
|
||||||
|
})
|
||||||
|
.on("click", onClick)
|
||||||
|
.on("mouseover", onMouseover)
|
||||||
|
.on("mouseout", onMouseout)
|
||||||
|
.merge(node);
|
||||||
|
|
||||||
|
link = link.data(linksData, (d) => `${d.source.id}-${d.target.id}`);
|
||||||
|
link.exit().remove();
|
||||||
|
link = link.enter().append("line").attr("stroke-width", STROKE).merge(link);
|
||||||
|
|
||||||
|
text = text.data(nodesData, (d) => d.label);
|
||||||
|
text.exit().remove();
|
||||||
|
text = text
|
||||||
|
.enter()
|
||||||
|
.append("text")
|
||||||
|
.text((d) => shorten(d.label.replace(/_*/g, ""), MAX_LABEL_LENGTH))
|
||||||
|
.attr("font-size", `${FONT_SIZE}px`)
|
||||||
|
.attr("text-anchor", "middle")
|
||||||
|
.attr("alignment-baseline", "central")
|
||||||
|
.on("click", onClick)
|
||||||
|
.on("mouseover", onMouseover)
|
||||||
|
.on("mouseout", onMouseout)
|
||||||
|
.merge(text);
|
||||||
|
|
||||||
|
node.attr("active", (d) => isCurrentPath(d.path) ? true : null);
|
||||||
|
text.attr("active", (d) => isCurrentPath(d.path) ? true : null);
|
||||||
|
|
||||||
|
simulation.nodes(nodesData);
|
||||||
|
simulation.force("link").links(linksData);
|
||||||
|
simulation.alpha(1).restart();
|
||||||
|
simulation.stop();
|
||||||
|
|
||||||
|
for (let i = 0; i < TICKS; i++) {
|
||||||
|
simulation.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
ticked();
|
||||||
|
};
|
||||||
|
|
||||||
|
const zoomHandler = d3.zoom().scaleExtent([0.2, 3]).on("zoom", resize);
|
||||||
|
|
||||||
|
zoomHandler(svg);
|
||||||
|
restart();
|
||||||
|
|
||||||
|
function isCurrentPath(notePath) {
|
||||||
|
return window.location.pathname.includes(notePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
function shorten(str, maxLen, separator = ' ') {
|
||||||
|
if (str.length <= maxLen) return str;
|
||||||
|
return str.substr(0, str.lastIndexOf(separator, maxLen)) + '...';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</div>
|
13
_layouts/default.html
Normal file
13
_layouts/default.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
{% include head.html %}
|
||||||
|
<body>
|
||||||
|
<nav>{% include nav.html %}</nav>
|
||||||
|
<div class="wrapper">
|
||||||
|
<main>{{ content }}</main>
|
||||||
|
<footer>{% include footer.html %}</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include link-previews.html wrapperQuerySelector="content" %}
|
||||||
|
</body>
|
||||||
|
</html>
|
47
_layouts/note.html
Normal file
47
_layouts/note.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<div>
|
||||||
|
<h1>{{ page.title }}</h1>
|
||||||
|
<time datetime="{{ page.last_modified_at | date_to_xmlschema }}">{% if page.type != 'pages' %}
|
||||||
|
Last updated on {{ page.last_modified_at | date: "%B %-d, %Y" }}
|
||||||
|
{% endif %}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="notes-entry-container">
|
||||||
|
<content>
|
||||||
|
{{ content }}
|
||||||
|
<p>This line appears after every note.</p>
|
||||||
|
</content>
|
||||||
|
|
||||||
|
<side style="font-size: 0.9em">
|
||||||
|
<h3 style="margin-bottom: 1em">Notes mentioning this note</h3>
|
||||||
|
{% if page.backlinks.size > 0 %}
|
||||||
|
<div style="display: grid; grid-gap: 1em; grid-template-columns: repeat(1fr);">
|
||||||
|
{% for backlink in page.backlinks %}
|
||||||
|
<div class="backlink-box">
|
||||||
|
<a class="internal-link" href="{{ site.baseurl }}{{ backlink.url }}{%- if site.use_html_extension -%}.html{%- endif -%}">{{ backlink.title }}</a><br>
|
||||||
|
<div style="font-size: 0.9em">{{ backlink.excerpt | strip_html | truncatewords: 20 }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<div style="font-size: 0.9em">
|
||||||
|
<p>
|
||||||
|
There are no notes linking to this note.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</side>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Here are all the notes in this garden, along with their links, visualized as a graph.</p>
|
||||||
|
|
||||||
|
{% include notes_graph.html %}
|
7
_layouts/page.html
Normal file
7
_layouts/page.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
<content>
|
||||||
|
{{ content }}
|
||||||
|
</content>
|
5
_notes/accents.md
Normal file
5
_notes/accents.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Bon appétit!
|
||||||
|
---
|
||||||
|
|
||||||
|
Page titles with accents are supported.
|
21
_notes/animals/cats.md
Normal file
21
_notes/animals/cats.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: A note about cats
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a second note with a poem with cats.
|
||||||
|
|
||||||
|
Here's a link to a note that explains why it's important to [[move your body every day]].
|
||||||
|
|
||||||
|
> I like my pillow, my fancy bed,
|
||||||
|
>
|
||||||
|
> My cat tree and the bathroom sink.
|
||||||
|
>
|
||||||
|
> Each has its time and fills a need,
|
||||||
|
>
|
||||||
|
> but a box is best when I want to think.
|
||||||
|
|
||||||
|
You can create as many notes as you want.
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur et risus at ipsum pharetra pellentesque vel in massa. Nam ornare, velit sed pulvinar gravida, justo ipsum eleifend augue, id porta velit eros vestibulum odio. Vestibulum dignissim malesuada sapien, eu volutpat lacus pellentesque et. Curabitur dui nisi, sagittis ut tempor ac, scelerisque in diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum vitae euismod ex. Morbi lacinia iaculis tempor.
|
||||||
|
|
||||||
|
Nunc porttitor lacus ullamcorper mauris porttitor feugiat. Vestibulum condimentum lacus vitae orci lobortis pellentesque in ac dolor. Nullam libero justo, suscipit id suscipit vel, tincidunt vitae lectus. Phasellus gravida iaculis ligula, at pharetra urna. Nunc vel tellus eleifend, aliquet magna non, condimentum est. Pellentesque vulputate posuere felis eget sodales. Cras finibus tortor porta libero bibendum, vel bibendum orci luctus. Donec ac eros vitae erat malesuada imperdiet at tempor turpis.
|
5
_notes/animals/tigers.md
Normal file
5
_notes/animals/tigers.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Tigers
|
||||||
|
---
|
||||||
|
|
||||||
|
This is yet another note, this one about tigers.
|
7
_notes/consistency.md
Normal file
7
_notes/consistency.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Consistency is key
|
||||||
|
---
|
||||||
|
|
||||||
|
Show up. Do the work. Be consistent.
|
||||||
|
|
||||||
|
Then go take a look at the [[Your first note|first note]].
|
11
_notes/move your body every day.md
Executable file
11
_notes/move your body every day.md
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
Move your body every day. Benefits include:
|
||||||
|
|
||||||
|
- Improved sleep quality
|
||||||
|
- Less risk of chronic disease
|
||||||
|
- Increased productivity
|
||||||
|
- Reduced anxiety
|
||||||
|
|
||||||
|
The "every day" part is important, because [[consistency]] is key to most things worth doing.
|
126
_notes/your-first-note.md
Normal file
126
_notes/your-first-note.md
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
title: Your first seed
|
||||||
|
---
|
||||||
|
|
||||||
|
### Welcome!
|
||||||
|
|
||||||
|
This is your first note. You'll find it in the [`notes/`](https://github.com/maximevaillancourt/digital-garden-jekyll-template/tree/master/_notes) directory.
|
||||||
|
|
||||||
|
### Link syntax
|
||||||
|
|
||||||
|
To link to another note, you can use multiple syntaxes. The following four use the "double-bracket" notation ([view the Markdown source file](https://github.com/maximevaillancourt/digital-garden-jekyll-template/blob/master/_notes/your-first-note.md#link-syntax) to see the underlying syntax).
|
||||||
|
|
||||||
|
- Using the note title: [[a note about cats]]
|
||||||
|
- Using the note's filename: [[cats]]
|
||||||
|
- Using the note's title, with a label: [[A note about cats|link to the note about cats using the note title]]
|
||||||
|
- Using the note's filename, with a label: [[cats|link to the note about cats using the note's filename]]
|
||||||
|
|
||||||
|
You can organize notes in subdirectories and link them normally. For example, the links above all point to the `_notes/animals/cats.md` file. Here's another example: [[tigers]].
|
||||||
|
|
||||||
|
Non-latin languages are supported: [[안녕하세요]]; so are accents/diacritics: [[bon appétit!]]
|
||||||
|
|
||||||
|
Dashes and underscores in file names are supported, and may be omitted in the bracket link syntax. As an example, the `your-first-note.md` file can be linked to with [[your first note]] or [[your-first-note]], or even [[yOuR-FiRsT Note]].
|
||||||
|
|
||||||
|
In all cases, if the double-bracket link does not point to a valid note, the double brackets will still be shown, like this: [[there is no note that matches this link]].
|
||||||
|
|
||||||
|
Alternatively, you can use regular [Markdown syntax](https://www.markdownguide.org/getting-started/) for links, with a relative link to the other note, like this: [this is a Markdown link to the note about cats](/cats){: .internal-link}. Don't forget to use the `.internal-link` class to make sure the link is styled as an internal link (without the little arrow).
|
||||||
|
|
||||||
|
Since the Web is all about HTML, you can always use plain HTML if you want, like this: <a class="internal-link" href="/cats">This is a link to the note about cats with HTML</a>.
|
||||||
|
|
||||||
|
Of course, you can also link to external websites, like this: [this is a link to Wikipedia](https://wikipedia.org/). Again, you can use plain HTML if you prefer. Footnotes are also supported and will be treated like internal links.[^1] You can point to other notes in your footnotes.[^2]
|
||||||
|
|
||||||
|
[^1]: This is a footnote. For more information about using footnotes, check out the [Markdown Guide](https://www.markdownguide.org/extended-syntax/#footnotes).
|
||||||
|
[^2]: This is another footnote that links to the note about [[cats]]. You may also point to [[notes that do not exist]] if you wish.
|
||||||
|
|
||||||
|
### Tweet embedding
|
||||||
|
|
||||||
|
Note: This behavior is disabled by default for privacy reasons. See "Site configuration" section below to enable it.
|
||||||
|
|
||||||
|
You may include a tweet URL on its own line (like below), and it would be replaced with an official Twitter embed if the site configuration demands it.
|
||||||
|
|
||||||
|
https://twitter.com/jack/status/20
|
||||||
|
|
||||||
|
### Media embedding
|
||||||
|
|
||||||
|
You may embed media files within a note using HTML5 media tags. Here's an example for an audio file:
|
||||||
|
|
||||||
|
"Jazzy Frenchy" by Benjamin Tissot from bensound.com
|
||||||
|
<audio controls>
|
||||||
|
<source src="/assets/jazzyfrenchy.mp3" type="audio/mpeg">
|
||||||
|
Your browser does not support the audio element.
|
||||||
|
</audio>
|
||||||
|
|
||||||
|
### Site configuration
|
||||||
|
|
||||||
|
Some behavior is configurable by tweaking the `_config.yml` file.
|
||||||
|
|
||||||
|
**`use_html_extension`**: if you use a static host that doesn't support URLs that don't end with `.html` (such as Neocities), try changing the `use_html_extension` value to `true` in the `_config.yml` file and restart the Jekyll server (or re-build the site). This adds a `.html` extension to note URLs and may resolve issues with links. If you're still having trouble, I recommend using Netlify to host your digital garden: it's free, easy to use, and fully supports this template's features out of the box.
|
||||||
|
|
||||||
|
**`open_external_links_in_new_tab`**: when set to `true`, this makes external links open in new tabs. Set to `false` to open all links in the current tab.
|
||||||
|
|
||||||
|
**`embed_tweets`**: when set to `true`, tweet URLs on their own lines will be replaced with a Twitter embed. Default value is `false`.
|
||||||
|
|
||||||
|
### Automatic bi-directional links
|
||||||
|
|
||||||
|
Notice in the "Notes mentioning this note" section that there is another note linking to this note. This is a bi-directional link, and those are automatically created when you create links to other notes.
|
||||||
|
|
||||||
|
### Link previews
|
||||||
|
|
||||||
|
If you're on a device with mouse support, try hovering your mouse on internal links to preview the notes: [[a note about cats]].
|
||||||
|
|
||||||
|
Links that have been previewed will be cached to avoid redundant requests.
|
||||||
|
|
||||||
|
### Images and other Markdown goodies
|
||||||
|
|
||||||
|
Finally, because you have the full power of Markdown in this template, you can use regular Markdown syntax for various formatting options.
|
||||||
|
|
||||||
|
Lists work as expected:
|
||||||
|
|
||||||
|
- List element A
|
||||||
|
- List element B
|
||||||
|
- List element C
|
||||||
|
|
||||||
|
1. List element
|
||||||
|
2. List element
|
||||||
|
3. List element
|
||||||
|
|
||||||
|
If you'd like to quote other people, consider using quote blocks:
|
||||||
|
|
||||||
|
> Lorem ipsum dolor sit amet
|
||||||
|
|
||||||
|
And of course, images look great:
|
||||||
|
|
||||||
|
<img src="/assets/image.jpg"/>
|
||||||
|
|
||||||
|
You can also ==highlight some content== by wrapping it with `==`.
|
||||||
|
|
||||||
|
Non-latin languages are supported too: ==你好==, ==안녕하세요==, ==こんにちは==.
|
||||||
|
|
||||||
|
### Code syntax highlighting
|
||||||
|
|
||||||
|
You can add code blocks with full syntax color highlighting by wrapping code snippet in triple backticks and specifying the type of the code (`js`, `rb`, `sh`, etc.):
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Here's a bit of JavaScript:
|
||||||
|
console.log('hello!')
|
||||||
|
```
|
||||||
|
|
||||||
|
```rb
|
||||||
|
# And now some Ruby
|
||||||
|
def foo(bar)
|
||||||
|
"baz"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ cat /dev/urandom | grep "the answer to life" # shell scripts look nice too
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Next steps
|
||||||
|
|
||||||
|
This digital garden template is free, open-source, and [available on GitHub here](https://github.com/maximevaillancourt/digital-garden-jekyll-template).
|
||||||
|
|
||||||
|
The easiest way to build your own digital garden based on this template is to read this [step-by-step guide explaining how to set this up from scratch](https://maximevaillancourt.com/blog/setting-up-your-own-digital-garden-with-jekyll).
|
||||||
|
|
||||||
|
Go forth, have fun, and learn new something every day! ✌️
|
6
_notes/안녕하세요.md
Normal file
6
_notes/안녕하세요.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: 안녕하세요
|
||||||
|
---
|
||||||
|
|
||||||
|
This template supports any language. Come as you are! :)
|
||||||
|
|
9
_pages/about.md
Normal file
9
_pages/about.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: About
|
||||||
|
permalink: /about
|
||||||
|
---
|
||||||
|
|
||||||
|
*This is an about page.*
|
||||||
|
|
||||||
|
Feel free to tell the world about what you love! 😍
|
22
_pages/index.md
Normal file
22
_pages/index.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: Home
|
||||||
|
id: home
|
||||||
|
permalink: /
|
||||||
|
---
|
||||||
|
|
||||||
|
# Welcome! 🌱
|
||||||
|
|
||||||
|
<p style="padding: 3em 1em; background: #f5f7ff; border-radius: 4px;">
|
||||||
|
Take a look at <span style="font-weight: bold">[[Your first note]]</span> to get started on your exploration.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
This digital garden template is free, open-source, and [available on GitHub here](https://github.com/maximevaillancourt/digital-garden-jekyll-template).
|
||||||
|
|
||||||
|
The easiest way to get started is to read this [step-by-step guide explaining how to set this up from scratch](https://maximevaillancourt.com/blog/setting-up-your-own-digital-garden-with-jekyll).
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
max-width: 46em;
|
||||||
|
}
|
||||||
|
</style>
|
23
_pages/search.md
Normal file
23
_pages/search.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: Search
|
||||||
|
permalink: /search
|
||||||
|
---
|
||||||
|
|
||||||
|
<input type="text" id="search-input" placeholder="Search blog posts..">
|
||||||
|
|
||||||
|
<div id="results-container"></div>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/simple-jekyll-search@latest/dest/simple-jekyll-search.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.simpleJekyllSearch = new SimpleJekyllSearch({
|
||||||
|
searchInput: document.getElementById('search-input'),
|
||||||
|
resultsContainer: document.getElementById('results-container'),
|
||||||
|
json:'{{ site.baseurl }}/search.json',
|
||||||
|
searchResultTemplate: '<div class="search-result-box"><a class="internal-link" href="{url}?query={query}" title="{desc}">{title}</a><br><div class="search-excerpt">{excerpt}</div></div>',
|
||||||
|
// searchResultTemplate: '<li><a href="{url}?query={query}" title="{desc}">{title}</a></li>',
|
||||||
|
noResultsText: '<div class="search-result-box">No results found</div>',
|
||||||
|
limit: 10
|
||||||
|
});
|
||||||
|
</script>
|
111
_plugins/bidirectional_links_generator.rb
Normal file
111
_plugins/bidirectional_links_generator.rb
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class BidirectionalLinksGenerator < Jekyll::Generator
|
||||||
|
def generate(site)
|
||||||
|
graph_nodes = []
|
||||||
|
graph_edges = []
|
||||||
|
|
||||||
|
all_notes = site.collections['notes'].docs
|
||||||
|
all_pages = site.pages
|
||||||
|
|
||||||
|
all_docs = all_notes + all_pages
|
||||||
|
|
||||||
|
link_extension = !!site.config["use_html_extension"] ? '.html' : ''
|
||||||
|
|
||||||
|
# Convert all Wiki/Roam-style double-bracket link syntax to plain HTML
|
||||||
|
# anchor tag elements (<a>) with "internal-link" CSS class
|
||||||
|
all_docs.each do |current_note|
|
||||||
|
all_docs.each do |note_potentially_linked_to|
|
||||||
|
note_title_regexp_pattern = Regexp.escape(
|
||||||
|
File.basename(
|
||||||
|
note_potentially_linked_to.basename,
|
||||||
|
File.extname(note_potentially_linked_to.basename)
|
||||||
|
)
|
||||||
|
).gsub('\_', '[ _]').gsub('\-', '[ -]').capitalize
|
||||||
|
|
||||||
|
title_from_data = note_potentially_linked_to.data['title']
|
||||||
|
if title_from_data
|
||||||
|
title_from_data = Regexp.escape(title_from_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
new_href = "#{site.baseurl}#{note_potentially_linked_to.url}#{link_extension}"
|
||||||
|
anchor_tag = "<a class='internal-link' href='#{new_href}'>\\1</a>"
|
||||||
|
|
||||||
|
# Replace double-bracketed links with label using note title
|
||||||
|
# [[A note about cats|this is a link to the note about cats]]
|
||||||
|
current_note.content.gsub!(
|
||||||
|
/\[\[#{note_title_regexp_pattern}\|(.+?)(?=\])\]\]/i,
|
||||||
|
anchor_tag
|
||||||
|
)
|
||||||
|
|
||||||
|
# Replace double-bracketed links with label using note filename
|
||||||
|
# [[cats|this is a link to the note about cats]]
|
||||||
|
current_note.content.gsub!(
|
||||||
|
/\[\[#{title_from_data}\|(.+?)(?=\])\]\]/i,
|
||||||
|
anchor_tag
|
||||||
|
)
|
||||||
|
|
||||||
|
# Replace double-bracketed links using note title
|
||||||
|
# [[a note about cats]]
|
||||||
|
current_note.content.gsub!(
|
||||||
|
/\[\[(#{title_from_data})\]\]/i,
|
||||||
|
anchor_tag
|
||||||
|
)
|
||||||
|
|
||||||
|
# Replace double-bracketed links using note filename
|
||||||
|
# [[cats]]
|
||||||
|
current_note.content.gsub!(
|
||||||
|
/\[\[(#{note_title_regexp_pattern})\]\]/i,
|
||||||
|
anchor_tag
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# At this point, all remaining double-bracket-wrapped words are
|
||||||
|
# pointing to non-existing pages, so let's turn them into disabled
|
||||||
|
# links by greying them out and changing the cursor
|
||||||
|
current_note.content = current_note.content.gsub(
|
||||||
|
/\[\[([^\]]+)\]\]/i, # match on the remaining double-bracket links
|
||||||
|
<<~HTML.delete("\n") # replace with this HTML (\\1 is what was inside the brackets)
|
||||||
|
<span title='There is no note that matches this link.' class='invalid-link'>
|
||||||
|
<span class='invalid-link-brackets'>[[</span>
|
||||||
|
\\1
|
||||||
|
<span class='invalid-link-brackets'>]]</span></span>
|
||||||
|
HTML
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Identify note backlinks and add them to each note
|
||||||
|
all_notes.each do |current_note|
|
||||||
|
# Nodes: Jekyll
|
||||||
|
notes_linking_to_current_note = all_notes.filter do |e|
|
||||||
|
e.content.include?(current_note.url)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Nodes: Graph
|
||||||
|
graph_nodes << {
|
||||||
|
id: note_id_from_note(current_note),
|
||||||
|
path: "#{site.baseurl}#{current_note.url}#{link_extension}",
|
||||||
|
label: current_note.data['title'],
|
||||||
|
} unless current_note.path.include?('_notes/index.html')
|
||||||
|
|
||||||
|
# Edges: Jekyll
|
||||||
|
current_note.data['backlinks'] = notes_linking_to_current_note
|
||||||
|
|
||||||
|
# Edges: Graph
|
||||||
|
notes_linking_to_current_note.each do |n|
|
||||||
|
graph_edges << {
|
||||||
|
source: note_id_from_note(n),
|
||||||
|
target: note_id_from_note(current_note),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
File.write('_includes/notes_graph.json', JSON.dump({
|
||||||
|
edges: graph_edges,
|
||||||
|
nodes: graph_nodes,
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_id_from_note(note)
|
||||||
|
note.data['title'].bytes.join
|
||||||
|
end
|
||||||
|
end
|
22
_plugins/embed_tweets.rb
Normal file
22
_plugins/embed_tweets.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
class TweetEmbedGenerator < Jekyll::Generator
|
||||||
|
def generate(site)
|
||||||
|
return if !site.config["embed_tweets"]
|
||||||
|
|
||||||
|
all_notes = site.collections['notes'].docs
|
||||||
|
all_pages = site.pages
|
||||||
|
all_docs = all_notes + all_pages
|
||||||
|
|
||||||
|
all_docs.each do |current_note|
|
||||||
|
current_note.content.gsub!(
|
||||||
|
/^https?:\/\/twitter\.com\/(?:#!\/)?(\w+)\/status(es)?\/(\d+)$/i,
|
||||||
|
<<~HTML
|
||||||
|
<blockquote class="twitter-tweet">
|
||||||
|
This tweet could not be embedded. <a href="#{'\0'}">View it on Twitter instead.</a>
|
||||||
|
</blockquote>
|
||||||
|
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||||
|
HTML
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
18
_plugins/empty_front_matter_note_injector.rb
Normal file
18
_plugins/empty_front_matter_note_injector.rb
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
EMPTY_FRONT_MATTER = <<~JEKYLL
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
JEKYLL
|
||||||
|
|
||||||
|
# Inject empty front matter in notes that don't have any
|
||||||
|
Jekyll::Hooks.register :site, :after_init do |site|
|
||||||
|
Dir.glob(site.collections['notes'].relative_directory + '/**/*.md').each do |filename|
|
||||||
|
raw_note_content = File.read(filename)
|
||||||
|
unless raw_note_content.start_with?('---')
|
||||||
|
raw_note_content.prepend(EMPTY_FRONT_MATTER)
|
||||||
|
File.write(filename, raw_note_content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
18
_plugins/markdown-highlighter.rb
Normal file
18
_plugins/markdown-highlighter.rb
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Turns ==something== in Markdown to <mark>something</mark> in output HTML
|
||||||
|
|
||||||
|
Jekyll::Hooks.register [:notes], :post_convert do |doc|
|
||||||
|
replace(doc)
|
||||||
|
end
|
||||||
|
|
||||||
|
Jekyll::Hooks.register [:pages], :post_convert do |doc|
|
||||||
|
# jekyll considers anything at the root as a page,
|
||||||
|
# we only want to consider actual pages
|
||||||
|
next unless doc.path.start_with?('_pages/')
|
||||||
|
replace(doc)
|
||||||
|
end
|
||||||
|
|
||||||
|
def replace(doc)
|
||||||
|
doc.content.gsub!(/==+([^ ](.*?)?[^ .=]?)==+/, "<mark>\\1</mark>")
|
||||||
|
end
|
28
_plugins/open_external_links_in_new_tab.rb
Normal file
28
_plugins/open_external_links_in_new_tab.rb
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# If the configuration sets `open_external_links_in_new_tab` to a truthy value,
|
||||||
|
# add 'target=_blank' to anchor tags that don't have `internal-link` class
|
||||||
|
|
||||||
|
# frozen_string_literal: true
|
||||||
|
require 'nokogiri'
|
||||||
|
|
||||||
|
Jekyll::Hooks.register [:notes], :post_convert do |doc|
|
||||||
|
convert_links(doc)
|
||||||
|
end
|
||||||
|
|
||||||
|
Jekyll::Hooks.register [:pages], :post_convert do |doc|
|
||||||
|
# jekyll considers anything at the root as a page,
|
||||||
|
# we only want to consider actual pages
|
||||||
|
next unless doc.path.start_with?('_pages/')
|
||||||
|
convert_links(doc)
|
||||||
|
end
|
||||||
|
|
||||||
|
def convert_links(doc)
|
||||||
|
open_external_links_in_new_tab = !!doc.site.config["open_external_links_in_new_tab"]
|
||||||
|
|
||||||
|
if open_external_links_in_new_tab
|
||||||
|
parsed_doc = Nokogiri::HTML(doc.content)
|
||||||
|
parsed_doc.css("a:not(.internal-link):not(.footnote):not(.reversefootnote)").each do |link|
|
||||||
|
link.set_attribute('target', '_blank')
|
||||||
|
end
|
||||||
|
doc.content = parsed_doc.inner_html
|
||||||
|
end
|
||||||
|
end
|
76
_sass/_code.scss
Normal file
76
_sass/_code.scss
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
.highlight {
|
||||||
|
background: #f8f8f8;
|
||||||
|
padding: 1px 1em;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 1em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
overflow: auto;
|
||||||
|
margin: 1em -1em;
|
||||||
|
code{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.highlight {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||||
|
.highlight .k { font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { font-weight: bold } /* Operator */
|
||||||
|
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||||
|
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||||
|
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||||
|
.highlight .go { color: #888888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||||
|
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #009999 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #d14 } /* Literal.String */
|
||||||
|
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #008080 } /* Name.Constant */
|
||||||
|
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||||
|
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||||
|
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
338
_sass/_normalize.scss
Normal file
338
_sass/_normalize.scss
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background on active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57-
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers.
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10.
|
||||||
|
* 2. Remove the padding in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
162
_sass/_style.scss
Normal file
162
_sass/_style.scss
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
$color-primary: hsl(0, 0%, 10%);
|
||||||
|
$color-text: hsl(0, 0%, 20%);
|
||||||
|
$color-subtext: hsl(0, 0%, 30%);
|
||||||
|
$color-border: hsl(0, 0%, 85%);
|
||||||
|
$color-box-background: mix($color-primary, white, 4%);
|
||||||
|
$border-radius: 4px;
|
||||||
|
$font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
||||||
|
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
||||||
|
|
||||||
|
body {
|
||||||
|
box-sizing: content-box;
|
||||||
|
font-family: $font-family;
|
||||||
|
margin: 0 auto;
|
||||||
|
line-height: 1.7;
|
||||||
|
padding: 4vh 6vw;
|
||||||
|
overflow-x: hidden;
|
||||||
|
color: $color-text;
|
||||||
|
font-size: 1rem;
|
||||||
|
max-width: 63em;
|
||||||
|
|
||||||
|
@media (min-width: 820px) {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time {
|
||||||
|
display: block;
|
||||||
|
color: $color-subtext;
|
||||||
|
margin: 0.5em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin: 2em 0;
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: mix($color-text, white, 80%);
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-height: 75vh;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
padding: 1.5em;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.88em;
|
||||||
|
background: $color-box-background;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
margin: 1.5em 0;
|
||||||
|
background: $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
transition: background 300ms;
|
||||||
|
padding: 0 0.1em;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid $color-border;
|
||||||
|
color: $color-primary;
|
||||||
|
&:hover {
|
||||||
|
color: black !important;
|
||||||
|
background: #fffaf1;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
position: relative;
|
||||||
|
top: -0.5em;
|
||||||
|
font-size: 0.7em;
|
||||||
|
content: "↗";
|
||||||
|
color: #aaaaaa;
|
||||||
|
}
|
||||||
|
&.internal-link:after,
|
||||||
|
&.footnote:after,
|
||||||
|
&.reversefootnote:after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
background: #ffe8bc !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
margin: 1em 0 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes-entry-container {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 2em;
|
||||||
|
grid-template-areas:
|
||||||
|
"content"
|
||||||
|
"side";
|
||||||
|
|
||||||
|
@media (min-width: 700px) {
|
||||||
|
grid-template-columns: 3fr 1fr;
|
||||||
|
grid-template-areas: "content side";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.backlink-box, .search-result-box {
|
||||||
|
background: $color-box-background;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-box {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-input {
|
||||||
|
width: 100%;
|
||||||
|
background: $color-box-background;
|
||||||
|
border: 0px;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-input:focus {
|
||||||
|
background: $color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 0.1em 0.2em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid-link {
|
||||||
|
color: #444444;
|
||||||
|
cursor: help;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 0 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid-link-brackets {
|
||||||
|
color: #ccc;
|
||||||
|
cursor: help;
|
||||||
|
}
|
BIN
assets/image.jpg
Normal file
BIN
assets/image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 641 KiB |
BIN
assets/jazzyfrenchy.mp3
Normal file
BIN
assets/jazzyfrenchy.mp3
Normal file
Binary file not shown.
3
netlify.toml
Normal file
3
netlify.toml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[build]
|
||||||
|
command = "jekyll build --trace"
|
||||||
|
publish = "_site"
|
16
search.json
Normal file
16
search.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
layout: none
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{% for post in site.notes %}
|
||||||
|
{
|
||||||
|
"title" : "{{ post.title | escape }}",
|
||||||
|
"category" : "{{ post.category }}",
|
||||||
|
"tags" : "{{ post.tags | join: ', ' }}",
|
||||||
|
"url" : "{{ site.baseurl }}{{ post.url }}",
|
||||||
|
"date" : "{{ post.date }}",
|
||||||
|
"content" : "{{ post.content | strip_html | strip_newlines | smartify }}",
|
||||||
|
"excerpt" : "{{ post.content | strip_html | strip_newlines | smartify | truncatewords: 20 }}"
|
||||||
|
} {% unless forloop.last %},{% endunless %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
6
styles.scss
Normal file
6
styles.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
@import "../_sass/normalize";
|
||||||
|
@import "../_sass/code";
|
||||||
|
@import "../_sass/style";
|
Loading…
x
Reference in New Issue
Block a user