Compare commits

..

129 Commits

Author SHA1 Message Date
952502e690 Re-enable syntax highlighting in light mode
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-04-12 17:56:03 -07:00
388a4f1589 style: Fix inconsistent indentation in SCSS files for clarity 2025-04-05 19:54:25 -07:00
806d3a318f Switch TODO to be a quote syntax to avoid shortcodes
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-03-30 23:11:35 -07:00
b06b695653 Use mutable variables instead of scratch where possible
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-03-30 22:45:24 -07:00
4ff04221b0 Adjust summaries to account for Hugo breaking changes
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-03-02 18:59:45 -08:00
c5c57405b0 Update to newer Hugo release
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-03-02 13:39:41 -08:00
2beded7c14 Remove bold inconsolata font
A few bold keywords aren't worth the font

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-02-23 14:13:25 -08:00
2b7645a572 Generate instances of variable fonts
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2025-02-23 11:28:05 -08:00
98a9d78273 Generate source offset in HTML
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-12-26 12:33:59 -08:00
0cdd2fbf64 Bundle fonts instead of using Google fonts, and patch in missing math symbols
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-12-26 11:50:13 -08:00
431d4b0990 Add new internal ref shortcodes
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-12-25 19:03:05 -08:00
9536c9fb25 Allow stripping leading whitespace from code blocks
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-12-25 19:02:44 -08:00
85ea55402e Add side-by-side shortcode
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-11-28 20:41:05 -08:00
7a263ce2e5 Do not wrap text around icon on small screens
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-11-26 19:51:40 -08:00
8b8d3c7fd0 Implement collapsing consecutive posts in a series
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-11-25 19:15:07 -08:00
dde3fb61ae Move all bergamot partials and shortcodes into theme
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-09-15 20:09:47 -07:00
378a6f2ae1 Load custom JS scripts if page specifies them
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-09-15 20:03:05 -07:00
aae8912c08 Add support for custom input modes
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-09-15 19:48:32 -07:00
84278b2e91 Update theme with missing file 2024-09-15 16:39:00 -07:00
3a281dfa8a Load presets from front matter + allow both bundled and global bergamot files
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-09-15 16:18:48 -07:00
dee7579b29 Move bergamot widget into blog theme
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-09-15 15:28:31 -07:00
acaa00754b Fix sidenotes bleeding into text inline
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-07-16 14:30:26 -07:00
c00867d46b Markdown-ify sidenote labels
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-07-06 17:36:38 -07:00
8c3d93bc2d Add a 'draft link' shortcode
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-07-06 17:25:02 -07:00
f931e6eceb Properly close placeholder div
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-27 22:31:56 -07:00
acf86b8d76 Add a placeholder for "next in series" if the series is ongoing
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-26 19:48:55 -07:00
a5cda19e5e Remove unused whitespace in seriesnav.html
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-26 19:35:23 -07:00
7c085b4d39 Always link to root RSS feed on every page
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-26 19:21:46 -07:00
5b5b971538 Make headings clickable
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:53:17 -07:00
f4e0bed9cd Avoid line breaking inside figures
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:43:13 -07:00
109ff6ce95 Expand sidenotes inline in print
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:42:47 -07:00
99247db83d Disable margin content in print
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:41:36 -07:00
ce4161db0d Switch it to a block comment
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:26:44 -07:00
2c57790c59 Add a comment describing the feather situation
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:26:15 -07:00
1bc7cba988 Add logic to disable showing non-inline CSS
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:23:06 -07:00
ed270bc915 Hide checkboxes and icons when no CSS in head is loaded
This seems to help in Firefox's reader mode.
Also adjust images to not be huge without CSS.

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 19:21:46 -07:00
8b6874ec75 Allow disabling external-links-in-new-tab
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-24 17:51:46 -07:00
6921dbbd08 Disable down link icons since they're buggy
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-23 17:24:28 -07:00
a622d4d77c Add a border around images in figures
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-23 17:24:14 -07:00
1a9d9f33cf Use proper link concatenation
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-23 14:17:15 -07:00
7e8a89ccd2 Make fullwide images actually fullwide
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-23 13:54:08 -07:00
7b3ef86744 Write up and down arrows on internal links to headings
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-23 13:52:43 -07:00
60041d1d37 Restore whitespace to tag list
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 22:44:28 -07:00
2a77e0d308 Remove trailing whitespace from icon partial
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 22:42:49 -07:00
9abee96bd2 Fix double-used navigation ID and odd centering issue
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 22:28:49 -07:00
13eeadf6f0 Avoid using global 'page' variable in partial
This seems to have an undesired effect when called from a shortcode

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 22:17:43 -07:00
f677a3731c Add a series nav shortcode to display navigation early
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 22:03:33 -07:00
a8549922c3 Trim more whitespace from template
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 21:57:25 -07:00
db9433bda1 Extract series navigation into a partial
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 21:56:00 -07:00
25e9057dd8 Use ... instead of '. . .' in truncated summaries
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 17:31:00 -07:00
e431a4f22b Add an external link marker to external links
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-19 17:30:46 -07:00
a4bff7623d Don't re-print the name of series when listing pages
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-16 19:41:27 -07:00
b282843b40 Add a 'name in series' helper to re-use logic
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-16 19:35:31 -07:00
b1d4dd7a32 Adjust post.html to take a dict
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-16 19:35:07 -07:00
df22cb2b87 Use data from hosts.json to pull in link anchors
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-09 18:50:00 -07:00
4b19da5006 Reduce whitespace in templates and avoid polluting the page scratch
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-09 18:36:54 -07:00
ec7b58c8ec Avoid passing in .Site-variables to geturl.html
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-06-09 18:14:53 -07:00
97e965feec Add a nicer comment color in dark mode
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-27 18:57:58 -07:00
5bfbaf397b Allow both 'agda' and 'Agda' in highlight groups
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-23 00:56:51 -07:00
5e6b28a9a6 Insert series meta for Agda post-processing
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-22 22:41:47 -07:00
d088d79d3f Display base path and file path even if lines aren't set in highlight group
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-22 17:06:17 -07:00
1aeb600750 Set 'bestPath' to empty by default instead of nil
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-22 16:35:04 -07:00
3ccb5e8c65 Nicely stylize links in code blocks
This is mostly for Agda rendering.

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-22 15:25:42 -07:00
e531ebd992 Also include the base path and the file path in highlight groups
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 21:44:59 -07:00
8a5bbf460b Trim whitespace in more places
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 21:42:35 -07:00
48bdf9ef08 Remove newlines from group dict info
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 21:31:37 -07:00
b1334455ea Track the best path for a submodule that was added
For Agda, this is a proxy for 'root directory' of a project

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 20:59:08 -07:00
a6425c7510 Always add line numbers (why not?), but specially tag Agda blocks
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 20:41:10 -07:00
52ea5abbc8 For Agda code blocks, thread through line numbers
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 20:39:28 -07:00
67da389005 Break up code creating highlight groups and pass in line numbers
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 20:39:21 -07:00
a6a14c3909 Allow "group" partial to accept custom attributes
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-21 20:38:42 -07:00
b9a91e76ce Highlight linked paragraphs 2024-05-21 19:04:34 -07:00
00431109ac Improve the series navigation links
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-20 00:34:52 -07:00
e4dccd4f48 Add support for series navigation links
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-20 00:27:25 -07:00
f3bf27d4a1 Remove newlines from 'codeurl'
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-16 16:16:43 -07:00
77b8d5e65b Draw from 'data/' for submodule links
I didn't know about https://gohugo.io/templates/data-templates/

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-16 15:52:15 -07:00
e2fb9362f6 Tweak formattng of tables
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-14 20:32:22 -07:00
038c8e0ac6 Enable bold Raleway loading
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-14 20:31:23 -07:00
2c13bf93cb Add a shortcode to just get the URL of a code file
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-05-12 18:58:28 -07:00
9c9ced66c3 Allow hiding code in code blocks 2024-03-11 23:20:35 -07:00
9b9a6dca5f Decorate blockquotes a bit
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-03-11 15:50:22 -07:00
4a5dfac221 Tweak code CSS a bit to make it nicer
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2024-02-02 21:05:26 -08:00
a613c68f01 Remove crossorigin attribute from katex.min.css
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-12-30 19:25:15 -08:00
991cccb9f6 Make button contrast not burn your eyes. 2023-12-30 16:31:16 -08:00
0502cf93b6 Move link transitions into however effects to avoid transition from browser default color. 2023-12-30 16:15:40 -08:00
4608853c9b Remove 'site url' from theme parameters since it's a site property 2023-12-30 16:01:37 -08:00
973be263dc Defer some heavier CSS until later to help page loading times.
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-12-30 16:00:57 -08:00
1f64536c30 Add comments to HTML 2023-12-30 15:46:36 -08:00
ae107a445a Remove analytics slug since it's specific to sites 2023-12-30 14:47:09 -08:00
c1c83a8ca2 Use unminified normalize since the npm package doesn't have a minified version 2023-12-30 14:46:17 -08:00
4f457874f3 Remove KaTeX CSS URL in local mode since it's already loaded above
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-12-30 14:30:44 -08:00
f5be44887b Extract more CSS/JS into static files on static.danilafe.com 2023-12-30 14:30:27 -08:00
0d721d48a4 Use a protocol-independent // instead of https://. 2023-12-30 14:29:31 -08:00
d570c8f421 Factor GitHub URL and resume link into configuration
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-12-30 14:27:37 -08:00
282b18f9a0 Add defaults for required site params to theme config.toml
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-12-30 14:01:19 -08:00
c728748106 Extract hardcoded URL to danilafe.com into a site param. 2023-12-30 13:58:56 -08:00
e82879434e Add support for plausible analytics 2023-12-30 13:12:01 -08:00
098767e766 Use static.danilafe.com to host KaTeX CSS/Fonts, and make that configurable.
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-11-29 22:13:59 -08:00
5aa54c1ce4 Extract input style to common CSS and remove raw uses of var(--x).
The mixin handles the fallback gracefully on browsers where it's not
supported.
2023-11-27 22:17:23 -08:00
abb137514b Tweak the highlight CSS to include more classes.
Specifically, 'kd' (declaration keyword) and 'cm' (multiline comment)

Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2023-11-24 11:03:49 -08:00
b5761d4d81 Add a new shortcode for referencing lines in a GitHub repo
Including Chapel as a submodule would add 1GB to clones.
2023-10-09 14:40:07 -07:00
502190055d Add a details shortcode 2023-06-04 21:54:08 -07:00
7e3099aae3 Make the keywords not grey on dark mode 2023-05-04 21:01:56 -07:00
d1e25ddf19 Add the option to specify discussion rooms on articles 2023-04-15 15:08:08 -07:00
926504ae07 Fix up search CSS a bit more 2023-04-09 22:52:22 -07:00
05f49998e7 Try fix text search on under dark mode 2023-04-09 22:32:16 -07:00
5202c57e2b Fix highlighted code lines in dark mode 2023-03-11 14:56:46 -08:00
0bd55bc58a Add fallbacks to CSS variables for older browsers 2023-03-11 14:07:43 -08:00
c631be65bc Tentatively add a dark mode 2023-03-11 12:08:45 -08:00
9594b699f8 Tweak the series status style 2023-02-19 15:10:25 -08:00
e431d65659 Add series to the article header 2023-01-31 18:54:42 -08:00
7b684a18a9 Tweak series marker colors 2023-01-31 18:54:08 -08:00
5f1871e11c Make post subscripts no longer grey 2023-01-31 17:57:18 -08:00
115057d837 Start working on series pages 2023-01-31 17:43:05 -08:00
e7cada3764 Fix double quote in tags list 2023-01-01 19:36:52 -08:00
efa9da8cd1 Make table of contents lines wrap 2023-01-01 14:32:21 -08:00
84274f5c08 Move the content graph layout into theme 2023-01-01 13:20:04 -08:00
32738ce835 Add more translations 2023-01-01 12:58:41 -08:00
2f4e5f58a0 Remove hardcoded English from tag page content 2023-01-01 12:41:28 -08:00
98ee4bd8f3 Add i18n support to the theme 2023-01-01 12:26:37 -08:00
f56465c5ec Merge branch 'master' of https://dev.danilafe.com/Web-Projects/vanilla-hugo 2022-12-30 13:34:27 -08:00
66d5125b88 Use BaseURL when linking 2022-12-30 13:28:18 -08:00
Danila Fedorin
667440d2e3 Serve KaTeX JS if we're editing live 2022-12-09 15:38:44 -08:00
Danila Fedorin
2a0f0cad49 Add option to offset a sidenote to prevent overlap 2022-12-09 15:36:07 -08:00
Danila Fedorin
fb7910c0a2 Remove unused numberedsidenote shortcode 2022-12-09 15:35:11 -08:00
b5e2821918 Use newer KaTeX version 2022-10-18 19:11:38 -07:00
869f9d12c8 Add a shortcode for folding rows of a table on small screens 2022-09-10 17:20:54 -07:00
c5a28bf7ef Add a new block shortcode 2022-09-10 12:32:10 -07:00
5869d99db1 Tweak dialog styles a bit 2022-08-28 19:09:19 -07:00
85 changed files with 1471 additions and 288 deletions

View File

@@ -0,0 +1,22 @@
LatexListNil @ latexlist(nil, nil) <-;
LatexListCons @ latexlist(cons(?x, ?xs), cons(?l_x, ?l_s)) <- latex(?x, ?l_x), latexlist(?xs, ?l_s);
IntercalateNil @ intercalate(?sep, nil, nil) <-;
IntercalateConsCons @ intercalate(?sep, cons(?x_1, cons(?x_2, ?xs)), cons(?x_1, cons(?sep, ?ys))) <- intercalate(?sep, cons(?x_2, ?xs), ?ys);
IntercalateConsNil @ intercalate(?sep, cons(?x, nil), cons(?x, nil)) <-;
NonEmpty @ nonempty(cons(?x, ?xs)) <-;
LatexInt @ latex(?i, ?l) <- int(?i), tostring(?i, ?l);
LatexFloat @ latex(?f, ?l) <- float(?f), tostring(?f, ?l);
LatexStr @ latex(?s, ?l) <- str(?s), escapestring(?s, ?l_1), latexifystring(?s, ?l_2), join(["\\texttt{\"", ?l_2, "\"}"], ?l);
LatexMeta @ latex(metavariable(?l), ?l) <-;
LatexLit @ latex(lit(?i), ?l) <- latex(?i, ?l);
LatexVar @ latex(var(?s), ?l) <- latex(?s, ?l);
LatexIsInt @ latex(int(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Int}"], ?l);
LatexIsFloat @ latex(float(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Float}"], ?l);
LatexIsNum @ latex(num(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Num}"], ?l);
LatexIsStr @ latex(str(?e), ?l) <- latex(?e, ?l_e), join([?l_e, " \\in \\texttt{Str}"], ?l);
LatexSym @ latex(?s, ?l) <- sym(?s), tostring(?s, ?l_1), join(["\\text{", ?l_1,"}"], ?l);
LatexCall @ latex(?c, ?l) <- call(?c, ?n, ?ts), nonempty(?ts), latexlist(?ts, ?lts_1), intercalate(", ", ?lts_1, ?lts_2), join(?lts_2, ?lts_3), join(["\\text{", ?n, "}", "(", ?lts_3, ")"], ?l);

View File

@@ -0,0 +1,102 @@
const loadedWidgets = {};
const getButtons = (inputGroup) => {
return {
play: inputGroup.querySelector(".bergamot-play"),
reset: inputGroup.querySelector(".bergamot-reset"),
close: inputGroup.querySelector(".bergamot-close"),
}
}
const setRunning = (inputGroup, running) => {
if (inputGroup !== null) {
const buttons = getButtons(inputGroup);
if (buttons.play) buttons.play.classList.toggle("bergamot-hidden", running);
if (buttons.reset) buttons.reset.classList.toggle("bergamot-hidden", !running);
if (buttons.close) buttons.close.classList.toggle("bergamot-hidden", !running);
}
}
// The object language parsing is handling by a separate standalone Elm
// application in the ObjectLanguage module, which has two ports:
//
// * `parseString` requests a string to be parsed
// * `parsedString` returns the parsed string, or null
//
// We want there to be a single global ObjectLanguage object, but it works
// on a "subscription" model (we have to give a callback to its port).
// Configure this callback to invoke `resolve` functions from a list,
// so that callers can just get a promise. This way we aren't continuously
// registering more and more handlers for each parsed string, and we can
// use a convenient promise API.
const parsingPromiseResolvers = {};
const ensureObjectLanguage = () => {
if (!window.Bergamot.ObjectLanguage) {
window.Bergamot.ObjectLanguage = Elm.Bergamot.ObjectLanguage.init({});
window.Bergamot.ObjectLanguage.ports.parsedString.subscribe(({ string, term }) => {
if (string in parsingPromiseResolvers) {
for (const resolver of parsingPromiseResolvers[string]) {
resolver(term);
}
parsingPromiseResolvers[string] = [];
}
});
}
return window.Bergamot.ObjectLanguage;
}
const parseBergamotObjectLanguage = (str) => {
if (!(str in parsingPromiseResolvers)) {
parsingPromiseResolvers[str] = [];
}
return new Promise(resolve => {
parsingPromiseResolvers[str].push(resolve);
ensureObjectLanguage().ports.parseString.send(str);
});
}
window.Bergamot = {};
window.Bergamot.run = (inputGroup, nodeId, inputModes, inputPrompt, rules, renderPreset, input) => {
var app = Elm.Main.init({
node: document.getElementById(nodeId),
flags: {
inputModes,
renderRules: window.Bergamot.renderPresets[renderPreset],
rules, input
}
});
app.ports.convertInput.subscribe(async ({ mode, input }) => {
if (!(mode in window.Bergamot.inputModes)) {
app.ports.receiveConverted.send({ input, result: { error: "Improperly configured desugaring function (this is the website developer's fault)" } });
}
let query = await (window.Bergamot.inputModes[mode])(input);
if (query !== null) {
query = inputPrompt.replace("TERM", query);
app.ports.receiveConverted.send({ input, result: { query } });
} else {
app.ports.receiveConverted.send({ input, result: { error: "Unable to parse object language term" } });
}
});
loadedWidgets[nodeId] = { app, parentNode: inputGroup ? inputGroup.parentElement : null };
setRunning(inputGroup, true);
};
window.Bergamot.runPreset = (inputGroup, nodeId, presetName) => {
const preset = window.Bergamot.presets[presetName];
window.Bergamot.run(inputGroup, nodeId, preset.inputModes, preset.inputPrompt, preset.rules, preset.renderPreset, preset.query || "");
};
window.Bergamot.close = (inputGroup, nodeId) => {
if (!(nodeId in loadedWidgets)) return;
const placeholderDiv = document.createElement('div');
placeholderDiv.id = nodeId;
const widget = loadedWidgets[nodeId];
const elmRoot = widget.parentNode.querySelector(".bergamot-root");
elmRoot.replaceWith(placeholderDiv)
delete loadedWidgets[nodeId];
setRunning(inputGroup, false);
}
window.Bergamot.inputModes = {
"Bergamot Object Language": parseBergamotObjectLanguage
};
window.Bergamot.presets = {};
window.Bergamot.renderPresets = {};

View File

@@ -0,0 +1,31 @@
class KatexExpressionShim extends HTMLElement {
static observedAttributes = ["expression", "katex-options"];
targetSpan;
constructor() {
super();
}
doRender() {
if (!this.targetSpan) return;
const options = this.hasAttribute("katex-options") ?
this.getAttribute("katex-options") : {};
katex.render(
this.getAttribute("expression"),
this.targetSpan,
JSON.parse(options)
);
}
connectedCallback() {
this.targetSpan = document.createElement('span');
this.appendChild(this.targetSpan);
this.doRender();
}
attributeChangedCallback(name, oldValue, newValue) {
this.doRender();
}
}
customElements.define("katex-expression", KatexExpressionShim);

View File

@@ -1,10 +1,5 @@
@import "variables.scss";
$code-color-lineno: grey;
$code-color-keyword: black;
$code-color-type: black;
$code-color-comment: grey;
.highlight-label {
padding: 0.25rem 0.5rem 0.25rem 0.5rem;
border: $code-border;
@@ -20,10 +15,10 @@ $code-color-comment: grey;
}
code {
font-family: $font-code;
background-color: $code-color;
border: $code-border;
padding: 0 0.25rem 0 0.25rem;
font-family: $font-code;
@include var(background-color, code-color);
border: $code-border;
padding: 0 0.25rem 0 0.25rem;
}
pre code {
@@ -37,13 +32,22 @@ pre code {
.lntable {
border-spacing: 0;
padding: 0.5rem 0 0.5rem 0;
background-color: $code-color;
@include var(background-color, code-color);
border-radius: 0;
border: $code-border;
display: block;
overflow: auto;
margin-bottom: 1rem;
a {
color: inherit;
border: none;
&:hover, &:focus {
background-color: rgba($primary-color, 0.25);
}
}
td {
padding: 0;
}
@@ -60,6 +64,12 @@ pre code {
.lntd:last-child {
width: 100%;
}
// Insert padding to match the distance of the line number to its
// border.
.line {
padding-left: $code-lineno-spacing;
}
}
.lntr {
@@ -68,30 +78,39 @@ pre code {
.lnt {
display: block;
padding: 0 1rem 0 1rem;
color: $code-color-lineno;
padding: 0 $code-lineno-spacing 0 $code-lineno-spacing;
@include var(color, code-lineno-color);
border-right: $standard-border;
// Even though only highlighted line table numbers get the 'star',
// insert a corresponding space on non-highlighted ones to keep
// spacing consistent.
&::before {
content: " ";
}
}
.hl {
display: block;
background-color: #fffd99;
@include var(background-color, code-highlight-color);
.lnt::before {
content: "*";
.lnt {
border-left-color: $border-color;
&::before {
content: "*";
}
}
}
}
.kr, .k {
font-weight: bold;
color: $code-color-keyword;
.kr, .kd, .k {
@include var(color, code-keyword-color);
}
.kt {
font-weight: bold;
color: $code-color-type;
@include var(color, code-type-color);
}
.c, .c1 {
color: $code-color-comment;
.c, .c1, .cm {
@include var(color, code-comment-color);
}

45
assets/scss/fonts.scss Normal file
View File

@@ -0,0 +1,45 @@
@mixin font-inconsolata($weight) {
@font-face {
font-family: 'Inconsolata';
font-display: swap;
font-weight: $weight;
src: local('Inconsolata'),
url('../fonts/gen/Inconsolata-#{$weight}.woff2');
}
}
@mixin font-lora {
@font-face {
font-family: 'Lora';
font-display: swap;
src: local('Lora'),
url('../fonts/gen/Lora-Regular.woff2'),
url('../fonts/gen/Lora-Italic.woff2');
}
}
@mixin font-raleway($weight) {
@font-face {
font-family: 'Raleway';
font-display: swap;
font-weight: $weight;
src: local('Raleway'),
url('../fonts/gen/Raleway-#{$weight}.woff2'),
url('../fonts/gen/Raleway-#{$weight}-Italic.woff2');
}
}
@mixin font-stixgeneral {
@font-face {
font-family: 'STIXGeneral';
font-display: swap;
src: local('STIXGeneral-Regular'),
url('../fonts/STIXGeneral-Regular.ttf');
}
}
@include font-inconsolata(400);
@include font-lora();
@include font-raleway(400);
@include font-raleway(700);
@include font-stixgeneral();

View File

@@ -1,16 +1,16 @@
@import "variables.scss";
@import "mixins.scss";
$margin-width: 30rem;
$margin-inner-offset: 0.5rem;
$margin-outer-offset: 1rem;
@mixin below-two-margins {
@media screen and
(max-width: $container-width-threshold +
2 * ($margin-width + $margin-inner-offset + $margin-outer-offset)) {
@content;
}
@media print {
@content;
}
}
@mixin below-one-margin {
@@ -19,6 +19,10 @@ $margin-outer-offset: 1rem;
($margin-width + $margin-inner-offset + $margin-outer-offset)) {
@content;
}
@media print {
@content;
}
}
@mixin margin-content {

View File

@@ -6,8 +6,27 @@
}
@mixin below-container-width {
@media screen and (max-width: $container-width-threshold){
@media screen and (max-width: $container-width-threshold) {
@content;
}
}
@mixin green-shadow {
box-shadow: 0px 0px 5px rgba($primary-color, 0.7);
}
@mixin textual-input {
@include bordered-block;
box-sizing: border-box;
@include var(background-color, background-color);
@include var(color, text-color);
font-family: $font-body;
padding: $input-padding;
&:active, &:focus {
@include green-shadow;
border-color: $primary-color;
}
flex-grow: 1;
}

24
assets/scss/modes.scss Normal file
View File

@@ -0,0 +1,24 @@
:root {
@each $varName, $varDefault in $css-vars {
--#{$varName}: #{$varDefault};
}
}
@media (prefers-color-scheme: dark) {
:root {
--background-color: #{$background-color-dark};
--text-color: white;
--warning-background-color: #{$warning-background-color-dark};
--warning-border-color: #{$warning-border-color-dark};
--target-background-color: #{$target-background-color-dark};
--code-color: #{$code-color-dark};
--code-lineno-color: white;
--code-keyword-color: #{$code-token-color-dark};
--code-comment-color: #{$code-comment-color-dark};
--code-type-color: #{$code-token-color-dark};
--code-highlight-color: #{$code-highlight-color-dark};
}
}

View File

@@ -1,13 +1,8 @@
@import "variables.scss";
@import "mixins.scss";
$search-input-padding: 0.5rem;
$search-element-padding: 0.5rem 1rem 0.5rem 1rem;
@mixin green-shadow {
box-shadow: 0px 0px 5px rgba($primary-color, 0.7);
}
.stork-wrapper {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
@@ -20,24 +15,16 @@ $search-element-padding: 0.5rem 1rem 0.5rem 1rem;
}
input.stork-input {
@include bordered-block;
font-family: $font-body;
padding: $search-input-padding;
&:active, &:focus {
@include green-shadow;
border-color: $primary-color;
}
flex-grow: 1;
@include textual-input;
}
.stork-close-button {
@include bordered-block;
@include var(background-color, background-color);
@include var(color, text-color);
font-family: $font-body;
padding: $search-input-padding;
padding: $input-padding;
background-color: $code-color;
padding-left: 1.5rem;
padding-right: 1.5rem;
@@ -56,7 +43,7 @@ input.stork-input {
padding: $search-element-padding;
}
.stork-message:not(:last-child), .stork-result {
.stork-message:not(:last-child), .stork-result {
border-bottom: $standard-border;
}
@@ -69,11 +56,11 @@ input.stork-input {
list-style: none;
&.selected {
background-color: $code-color;
@include var(background-color, code-color);
}
a:hover {
color: black;
@include var(color, text-color);
}
}

View File

@@ -2,9 +2,6 @@
@import "mixins.scss";
@import "margin.scss";
$sidenote-padding: 1rem;
$sidenote-highlight-border-width: .2rem;
.sidenote {
&:hover {
.sidenote-label {
@@ -51,13 +48,20 @@ $sidenote-highlight-border-width: .2rem;
@mixin hidden-sidenote {
position: static;
margin-top: 1rem;
// Author can override margin inline to shift sidenote, but when displayed
// on mobile (and thus, between text), shifting it would overlap it
// with text, so override the shift.
margin-top: 1rem !important;
margin-bottom: 1rem;
width: 100%;
.sidenote-checkbox:checked ~ & {
display: block;
}
@media print {
display: block;
}
}
@include below-two-margins {

View File

@@ -1,146 +1,172 @@
@import "variables.scss";
@import "mixins.scss";
@import "toc.scss";
@import "modes.scss";
body {
font-family: $font-body;
font-size: 1.0rem;
line-height: 1.5;
margin-bottom: 1rem;
text-align: justify;
@include var(background-color, background-color);
@include var(color, text-color);
font-family: $font-body;
font-size: 1.0rem;
line-height: 1.5;
margin-bottom: 1rem;
text-align: justify;
@include below-container-width {
text-align: left;
}
@include below-container-width {
text-align: left;
}
}
h1, h2, h3, h4, h5, h6 {
margin-bottom: .1rem;
margin-top: .5rem;
font-family: $font-heading;
font-weight: normal;
text-align: center;
margin-bottom: .1rem;
margin-top: .5rem;
font-family: $font-heading;
font-weight: normal;
text-align: center;
&:target {
background-color: lighten(yellow, 30%);
border-radius: 1rem;
}
a {
border-bottom: none;
&:hover {
color: $primary-color;
&:target {
@include var(background-color, target-background-color);
border-radius: 1rem;
}
a {
border-bottom: none;
&:hover {
color: $primary-color;
}
}
}
p {
&:target {
@include var(background-color, target-background-color);
border-radius: 0.25rem;
}
}
}
.container {
position: relative;
margin: auto;
width: 100%;
max-width: $container-width;
box-sizing: border-box;
position: relative;
margin: auto;
width: 100%;
max-width: $container-width;
box-sizing: border-box;
@include below-container-width {
padding: 0 $container-min-padding 0 $container-min-padding;
margin: 0;
max-width: $container-width + 2 * $container-min-padding;
}
@include below-container-width {
padding: 0 $container-min-padding 0 $container-min-padding;
margin: 0;
max-width: $container-width + 2 * $container-min-padding;
}
@include below-two-margins {
left: -($margin-width + $margin-inner-offset + $margin-outer-offset)/2;
}
@include below-two-margins {
left: -($margin-width + $margin-inner-offset + $margin-outer-offset) / 2;
}
@include below-one-margin {
left: 0;
}
@include below-one-margin {
left: 0;
}
}
.button, input[type="submit"] {
padding: 0.5rem;
background-color: $primary-color;
border: none;
color: white;
transition: color 0.25s, background-color 0.25s;
text-align: left;
@include var(color, text-color);
padding: 0.5rem;
border: 1px solid $primary-color;
transition: color 0.25s, background-color 0.25s;
text-align: left;
&:focus {
outline: none;
}
&:focus {
outline: none;
}
&:hover, &:focus {
background-color: white;
color: $primary-color;
}
&:hover, &:focus {
background-color: rgba($primary-color, 0.2);
@include var(color, text-color);
}
}
.input[type="text"], textarea {
@include textual-input;
}
nav {
width: 100%;
margin: 0rem 0rem 1rem 0rem;
width: 100%;
margin: 0rem 0rem 1rem 0rem;
.container {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.container {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
a {
padding: 0.25rem 0.75rem 0.25rem .75rem;
text-decoration: none;
color: black;
display: inline-block;
border-bottom: none;
white-space: nowrap;
}
a {
padding: 0.25rem 0.75rem 0.25rem .75rem;
text-decoration: none;
@include var(color, text-color);
display: inline-block;
border-bottom: none;
white-space: nowrap;
}
}
.post-subscript {
color: #8f8f8f;
text-align: center;
text-align: center;
}
.post-content {
margin-top: .5rem;
margin-top: .5rem;
}
h1 {
font-size: 3.0rem;
font-size: 3.0rem;
}
h2 {
font-size: 2.6rem;
font-size: 2.6rem;
}
h3 {
font-size: 2.2rem;
font-size: 2.2rem;
}
h4 {
font-size: 1.8rem;
font-size: 1.8rem;
}
h5 {
font-size: 1.4rem;
font-size: 1.4rem;
}
h6 {
font-size: 1.0rem;
font-size: 1.0rem;
}
a {
color: black;
text-decoration: none;
border-bottom: .2rem solid $primary-color;
transition: color 0.25s;
@include var(color, text-color);
text-decoration: none;
border-bottom: .2rem solid $primary-color;
&:hover {
color: $primary-color;
}
&:hover {
color: $primary-color;
transition: color 0.25s;
}
&.external-link, &.same-page-link {
.feather {
fill: none;
margin-left: 0.25rem;
position: relative;
top: 0.125em;
}
}
}
.draft-link {
border-bottom: .2rem solid $border-color;
}
img {
max-width: 100%
max-width: 100%;
background-color: white;
}
table {
@@ -149,10 +175,12 @@ table {
padding: 0.5rem;
}
tr {
@include below-container-width {
display: flex;
flex-direction: column;
.fold-table + table {
tr {
@include below-container-width {
display: flex;
flex-direction: column;
}
}
}
@@ -160,6 +188,9 @@ td {
@include below-container-width {
overflow-x: auto;
}
}
td, th {
padding: 0.5rem;
}
@@ -209,9 +240,32 @@ ul.post-list {
display: block;
}
p.post-wordcount {
p.post-status {
margin-bottom: 0.2rem;
margin-top: 0.2rem;
}
p.post-wordcount, p.post-status {
text-align: center;
margin-bottom: 0.6rem;
margin-bottom: 1rem;
}
.series-link {
display: flex;
align-items: center;
margin-top: 1rem;
font-size: 1.1rem;
border-top: $standard-border;
padding-top: 1rem;
.feather {
fill: none;
flex-shrink: 0;
width: 1em;
height: 1em;
margin-right: 0.5em;
}
}
}
@@ -220,7 +274,11 @@ ul.post-list {
}
figure {
break-inside: avoid;
img {
border: $standard-border;
border-radius: 0.5rem;
max-width: 70%;
display: block;
margin: auto;
@@ -249,48 +307,62 @@ figure {
&.medium img {
max-height: 30rem;
}
&.fullwide {
margin-left: 0;
margin-right: 0;
}
}
.twitter-tweet {
margin: auto;
}
.draft-warning {
.warning {
@include bordered-block;
padding: 0.5rem;
background-color: #ffee99;
border-color: #f5c827;
@include var(background-color, warning-background-color);
@include var(border-color, warning-border-color);
}
/*
Note: by absolute default (via inline CSS) feather icons are hidden.
That's because firefox reader mode doesn't play nice with them, and
it seems to ignore all styles in <head>. Then, the inline style
in <head> uses !important to restore the display of icons, but provides
limited styling. Here, we finally apply the full extent of the feather styles.
*/
.feather {
width: 1rem;
height: 1rem;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: currentColor;
width: 1rem;
height: 1rem;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: currentColor;
}
.katex * {
font-family: unset;
font-family: unset;
}
.block {
@include bordered-block;
margin: auto;
padding: 0.5rem;
width: fit-content;
}
.dialog {
.message {
@include bordered-block;
display: block;
padding: 0.75rem;
max-width: 0.8*$container-width;
max-width: 0.8 * $container-width;
margin-top: 0.5rem;
display: flex;
flex-direction: row;
align-items: center;
text-align: left;
.message-sender {
width: 4rem;
margin: 0.5rem;
margin: 0.75rem;
.feather {
width: 2rem;
@@ -298,9 +370,130 @@ figure {
}
}
.message-text {
@include bordered-block;
display: block;
padding: 0.75rem;
}
&.side-answer {
margin-left: auto;
flex-direction: row-reverse;
}
}
}
.series-navigation {
margin-top: 1em;
display: flex;
flex-wrap: wrap;
.wrapper {
flex-grow: 1;
display: flex;
&.previous {
justify-content: left;
}
&.next {
justify-content: right;
}
}
a, .ongoing-placeholder {
@include bordered-block;
padding: 0.5em 1em 0.5em 1em;
font-size: 1.1em;
display: flex;
align-items: center;
margin-top: 1em;
.feather {
height: 1.25em;
width: 1.25em;
fill: none;
&:first-child { margin-right: 0.5em; }
&:last-child { margin-left: 0.5em; }
}
}
.ongoing-placeholder {
border-style: dashed;
}
div.title {
font-weight: bold;
}
}
.series-status {
&.suspended { --status-color: #f9b005; }
&.complete { --status-color: #3dc60b; }
&.ongoing { --status-color: #46a0ff; }
.series-status-keyword {
display: inline-block;
border-bottom: .2rem solid var(--status-color);
margin: 0 0.25rem 0 0.25rem;
}
}
details {
@include bordered-block;
padding: 0.5rem 0.5rem 0 0.5rem;
&[open] {
padding-bottom: 0.5rem;
summary {
border-bottom: $standard-border;
margin-bottom: 0.5rem;
}
}
}
summary {
margin: 0 -0.5rem 0 -0.5rem;
padding: 0.5rem;
padding-top: 0;
}
blockquote {
border-left: (3 * $standard-border-width) solid $primary-color;
margin-left: 0;
padding-left: 1rem;
}
.early-navigation-wrapper {
margin-bottom: 3rem;
}
.side-by-side {
display: flex;
}
.side-by-side-item {
flex-basis: 0;
}
.internal-ref {
text-decoration: underline;
break-inside: avoid;
&:target {
@include var(background-color, target-background-color);
border-radius: 1rem;
.internal-ref-counter {
@include var(background-color, target-background-color);
}
}
}
.internal-ref-counter {
display: inline-block;
border: $standard-border;
border-radius: 0.5rem;
padding: 0 0.25rem 0 0.25rem;
}

View File

@@ -2,9 +2,6 @@
@import "mixins.scss";
@import "margin.scss";
$toc-color: $code-color;
$toc-border-color: $code-border-color;
.table-of-contents {
@include margin-content;
@include margin-content-left;
@@ -12,6 +9,7 @@ $toc-border-color: $code-border-color;
flex-direction: column;
align-items: flex-end;
margin-bottom: 1rem;
text-align: left;
em {
font-style: normal;
@@ -37,12 +35,15 @@ $toc-border-color: $code-border-color;
a {
padding: 0;
white-space: normal;
margin-left: 0.5rem;
text-indent: -0.5rem;
}
div.wrapper {
@include bordered-block;
padding: 1rem;
background-color: $toc-color;
@include var(background-color, code-color);
border-color: $toc-border-color;
box-sizing: border-box;
max-width: 100%;

View File

@@ -1,16 +1,69 @@
$container-width: 45rem;
$container-min-padding: 1rem;
$container-width-threshold: $container-width + 2 * $container-min-padding;
$standard-border-width: .075rem;
$primary-color: #36e281;
$border-color: #bfbfbf;
$code-color: #f0f0f0;
$code-border-color: darken($code-color, 10%);
$background-color: white;
$background-color-dark: #1b1d1f;
$standard-border-width: .075rem;
$standard-border: $standard-border-width solid $border-color;
$font-heading: "Lora", serif;
$font-body: "Raleway", serif;
$font-code: "Inconsolata", monospace;
$font-code: "Inconsolata", monospace, "STIXGeneral";
$standard-border: $standard-border-width solid $border-color;
$warning-background-color: #ffee99;
$warning-border-color: #f5c827;
$warning-background-color-dark: #75640a;
$warning-border-color-dark: $warning-background-color;
$target-background-color: lighten(yellow, 30%);
$target-background-color-dark: #55511c;
$code-color: #f0f0f0;
$code-color-dark: lighten($background-color-dark, 10%);
$code-token-color: darken($primary-color, 25%);
$code-token-color-dark: $primary-color;
$code-highlight-color: #fffd99;
$code-highlight-color-dark: #555538;
$code-border-color: darken($code-color, 10%);
$code-lineno-color: black;
$code-lineno-spacing: 1rem;
$code-comment-color: grey;
$code-comment-color-dark: #68dcff;
$code-border: $standard-border-width solid $code-border-color;
$input-padding: 0.5rem;
$sidenote-padding: 1rem;
$sidenote-highlight-border-width: .2rem;
$margin-width: 30rem;
$margin-inner-offset: 0.5rem;
$margin-outer-offset: 1rem;
$toc-border-color: $code-border-color;
// Default values for CSS variables for fallback.
$css-vars: (
background-color: $background-color,
text-color: black,
warning-background-color: $warning-background-color,
warning-border-color: $warning-border-color,
target-background-color: $target-background-color,
code-color: $code-color,
code-lineno-color: $code-lineno-color,
code-keyword-color: $code-token-color,
code-comment-color: $code-comment-color,
code-type-color: $code-token-color,
code-highlight-color: $code-highlight-color,
);
@mixin var($property, $varName) {
#{$property}: map-get($css-vars, $varName);
#{$property}: var(--#{$varName});
}

69
chatgpt-instance-fonts.py Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""
Instantiate variable fonts at specific weights/styles, producing static TTF files.
No subsetting, no recursive searching—just direct calls with hardcoded axis values.
Requires fontTools >= 4.0.
Genererated by ChatGTP o3-mini-high. Not human-modified.
"""
from fontTools.ttLib import TTFont
from fontTools.varLib.instancer import instantiateVariableFont
def instantiate_variable_font(input_font_path, axis_values, output_font_path):
"""
1) Loads a variable font from `input_font_path`.
2) Instantiates (flattens) it at the specified axis values (e.g. {"wght": 400}).
3) Saves the result as a static TTF at `output_font_path`.
"""
print(f"Instantiating {input_font_path} with axes={axis_values} -> {output_font_path}")
vf = TTFont(input_font_path)
static_font = instantiateVariableFont(vf, axis_values)
static_font.flavor = "woff2"
static_font.save(output_font_path)
def main():
# Inconsolata (Variable)
instantiate_variable_font(
"Inconsolata-VariableFont_wdth,wght.ttf",
{"wght": 400},
"Inconsolata-400.woff2"
)
# Lora (Variable, normal and italic)
instantiate_variable_font(
"Lora-VariableFont_wght.ttf",
{"wght": 400},
"Lora-Regular.woff2"
)
instantiate_variable_font(
"Lora-Italic-VariableFont_wght.ttf",
{"wght": 400},
"Lora-Italic.woff2"
)
# Raleway (Variable, normal and italic)
instantiate_variable_font(
"Raleway-VariableFont_wght.ttf",
{"wght": 400},
"Raleway-400.woff2"
)
instantiate_variable_font(
"Raleway-VariableFont_wght.ttf",
{"wght": 700},
"Raleway-700.woff2"
)
instantiate_variable_font(
"Raleway-Italic-VariableFont_wght.ttf",
{"wght": 400},
"Raleway-400-Italic.woff2"
)
instantiate_variable_font(
"Raleway-Italic-VariableFont_wght.ttf",
{"wght": 700},
"Raleway-700-Italic.woff2"
)
if __name__ == "__main__":
main()

7
config.toml Normal file
View File

@@ -0,0 +1,7 @@
[params]
katexCssUrl = "//static.danilafe.com/katex/katex.min.css"
katexJsUrl = "//static.danilafe.com/katex/katex.min.js"
normalizeCssUrl = "//static.danilafe.com/normalize/normalize.css"
visNetworkJsUrl = "//static.danilafe.com/vis-network/vis-network.min.js"
bergamotJsUrl = "//static.danilafe.com/bergamot/bergamot.js"
bergamotObjectLanguageJsUrl = "//static.danilafe.com/bergamot/objectlang.js"

79
i18n/en.toml Normal file
View File

@@ -0,0 +1,79 @@
[home]
other = "Home"
[about]
other = "About"
[resume]
other = "Resume"
[tags]
other = "Tags"
[favorites]
other = "Favorites"
[search]
other = "Search"
[allPosts]
other = "All Posts"
[nWords]
one = "one word"
other = "{{ .Count }} words"
[nMinutesToRead]
one = "about one minute to read"
other = "about {{ .Count }} minutes to read"
[latestInSeries]
other = "Latest in series:"
[recentPosts]
other = "Recent posts"
[tagged]
other = "Tagged \"{{ . }}\""
[postedOn]
other = "Posted on {{ . }}"
[tableOfContents]
other = "Table of Contents"
[warning]
other = "Warning!"
[postDraft]
other = "This post is a draft. At best, it may contain grammar mistakes; at worst, it can include significant errors and bugs. Please use your best judgement!"
[contactFooter]
other = "Liked this article? Have any questions or comments? Please don't hesitate to reach out to me at <a href=\"mailto:danila.fedorin@gmail.com\">danila.fedorin@gmail.com</a>! I love receiving emails from readers, and I'm always happy to provide any additional clarification or assistance."
[note]
other = "note"
[from]
other = "From"
[searchRequiresJS]
other = "Search (requires JavaScript)"
[series]
other = "Series"
[postsFromTo]
other = "First post in {{ .from }}, last post in {{ .to }}"
[seriesStatus]
other = "Series status:"
[suspendedSeries]
other = "Suspended"
[completeSeries]
other = "Complete"
[ongoingSeries]
other = "Ongoing"

View File

@@ -0,0 +1,9 @@
{{ if and (eq .Type "alert") (eq .AlertType "todo") -}}
<div style="background-color: tomato; color: white; padding: 10px;">
<em>TODO: </em>{{- .Text | plainify -}}
</div>
{{- else -}}
<blockquote {{- with .Attributes.id }} id="{{ . }}"{{ end }}>
{{ .Text -}}
</blockquote>
{{- end }}

View File

@@ -0,0 +1,6 @@
{{- .Page.Scratch.SetInMap "definedSections" (printf "#%s" .Anchor) true -}}
<a href="#{{ .Anchor }}">
<h{{ .Level }} id="{{ .Anchor }}">
{{- .Text | safeHTML -}}
</h{{ .Level }}>
</a>

View File

@@ -0,0 +1,32 @@
{{- $class := "" -}}
{{- $icon := "" -}}
{{- $absoluteDest := absLangURL .Destination -}}
{{- $siteRootUrl := absLangURL "" -}}
{{- $isExternal := not (hasPrefix $absoluteDest $siteRootUrl) -}}
{{- $isSamePage := hasPrefix .Destination "#" -}}
{{- if $isSamePage -}}
{{- $class = "same-page-link" -}}
{{- if index (.Page.Scratch.Get "definedSections") .Destination -}}
{{- $icon = "arrow-up" -}}
{{- else -}}
{{- /* Do not render "down" links because don't know how to distinguish unseen titles from paragraph links. */ -}}
{{- /* $icon = "arrow-down" */ -}}
{{- end -}}
{{- else if $isExternal -}}
{{- $class = "external-link" -}}
{{- $icon = "external-link" -}}
{{- end -}}
<a href="{{ .Destination | safeURL }}"
{{- with .Title }} title="{{ . }}"{{ end -}}
{{- with $class -}}
class="{{ . }}"
{{- end -}}
{{- if (and site.Params.externalLinksInNewTab $isExternal) -}}
target="_blank" rel="noopener noreferrer"
{{- end -}}
>
{{- with .Text | safeHTML }}{{ . }}{{ end -}}
{{- with $icon -}}{{- partial "icon.html" . -}}{{- end -}}
</a>
{{- /* chomp trailing newline */ -}}

View File

@@ -4,7 +4,7 @@
<ul class="post-list">
{{ range .Pages.ByDate.Reverse }}
{{ partial "post.html" . }}
{{ partial "post.html" (dict "page" .) }}
{{ end }}
</ul>
{{ end }}

View File

@@ -2,41 +2,37 @@
<h2>{{ .Title }}</h2>
<div class="post-subscript">
<p>
{{ range .Params.tags }}
<a class="button" href="{{ $.Site.BaseURL }}/tags/{{ . | urlize }}">{{ . }}</a>
{{ end }}
{{- range (.GetTerms "tags") -}}
<a class="button" href="{{ .Permalink }}">{{ .Title }}</a>
{{ end -}}
</p>
<p>Posted on {{ .Date.Format "January 2, 2006" }}.</p>
<p>{{ i18n "postedOn" (.Date.Format "January 2, 2006") }}.</p>
</div>
<div class="post-content">
{{ if not (eq .TableOfContents "<nav id=\"TableOfContents\"></nav>") }}
{{- if not (eq .TableOfContents "<nav id=\"TableOfContents\"></nav>") -}}
<div class="table-of-contents">
<div class="wrapper">
<em>Table of Contents</em>
{{ .TableOfContents }}
<em>{{- i18n "tableOfContents" -}}</em>
{{- .TableOfContents -}}
</div>
</div>
{{ end }}
{{- end -}}
{{ if .Draft }}
<div class="draft-warning">
<em>Warning!</em> This post is a draft. At best, it may contain grammar mistakes;
at worst, it can include significant errors and bugs. Please
use your best judgement!
</div>
{{ end }}
{{- if .Draft -}}
{{- partial "warning.html" (i18n "postDraft") -}}
{{- end -}}
{{ .Content }}
{{- .Content -}}
</div>
{{- end -}}
{{- define "after" -}}
<div class="container">
{{- partial "seriesnav.html" . -}}
</div>
{{ end }}
{{ define "after" }}
<hr class="container footer-divider">
<footer class="container">
<p>Liked this article? Have any questions or comments?
Please don't hesitate to reach out to me at <a href="mailto:danila.fedorin@gmail.com">
danila.fedorin@gmail.com</a>! I love receiving emails from readers, and I'm always happy
to provide any additional clarification or assistance.</p>
<p>{{ i18n "contactFooter" | safeHTML }}</p>
<!--
<p>I'm also currently looking for Computer Science internships for the summer
of 2021. Take a look at my <a href="/Resume-Danila-Fedorin.pdf">resume</a>,
@@ -45,4 +41,4 @@
to learn more about me!</p>
-->
</footer>
{{ end }}
{{- end -}}

View File

@@ -4,7 +4,7 @@
<ul class="post-list">
{{ range (where (where .Site.Pages.ByDate.Reverse "Section" "blog") ".Kind" "!=" "section") }}
{{ if .Params.favorite }}{{ partial "post.html" . }}{{ end }}
{{ if .Params.favorite }}{{ partial "post.html" (dict "page" .) }}{{ end }}
{{ end }}
</ul>
{{ end }}

16
layouts/graph/single.html Normal file
View File

@@ -0,0 +1,16 @@
{{ define "main" }}
<h2>{{ .Title }} </h2>
<script src="{{ .Site.Params.visNetworkJsUrl }}"></script>
<script type="module" src="{{ absLangURL "graph/graph.js" }}"></script>
<style>
#graph-container {
width: 100%;
height: 50vh;
border-radius: 0.2rem;
border: .075rem solid #bfbfbf
}
</style>
{{ .Content }}
<div id="graph-container">
</div>
{{ end }}

View File

@@ -1,10 +1,11 @@
{{ define "main" }}
{{ .Content }}
Recent posts:
{{ i18n "recentPosts" }}:
{{ partial "uniquebyseries.html" (dict "scratch" .Scratch) }}
<ul class="post-list">
{{ range first 10 (where (where .Site.Pages.ByDate.Reverse "Section" "blog") ".Kind" "!=" "section") }}
{{ partial "post.html" . }}
{{ range first 10 (.Scratch.Get "pages") }}
{{ partial "post.html" (dict "page" . "linkSeries" true) }}
{{ end }}
</ul>

View File

@@ -0,0 +1,6 @@
<script>
window.addEventListener('load', function() {
window.Bergamot.inputModes['{{ .name }}'] = {{ .fn | safeJS }};
});
</script>

View File

@@ -0,0 +1,17 @@
{
{{ if . }}
{{ range $name := split . ";" }}
{{ if eq $name "query" }}
"Query": "query",
{{ else }}
{{ $pieces := split $name ":" }}
{{ $name := index $pieces 0 }}
{{ $modestring := index $pieces 1 }}
"{{ $name }}": { "custom": "{{ $modestring }}" },
{{ end }}
{{ end }}
{{ else }}
"Languge Term": { "custom": "Bergamot Object Language" },
"Query": "query",
{{ end }}
}

View File

@@ -0,0 +1,11 @@
<script>
window.addEventListener('load', function() {
window.Bergamot.presets['{{ .name }}'] = {
rules: {{ .file }},
inputModes: {{ partial "bergamotparseinputmodes.js" .modes | safeJS }},
inputPrompt: '{{ .prompt }}',
query: '{{ .query }}',
renderPreset: '{{ default "default" .renderPreset }}'
};
});
</script>

View File

@@ -0,0 +1,6 @@
<script>
window.addEventListener('load', function() {
window.Bergamot.renderPresets['{{ .name }}'] =
{{ .file }};
});
</script>

View File

@@ -0,0 +1,2 @@
<link rel="preload" href="{{ .url }}" as="style" onload="this.onload=null;this.rel='stylesheet'" {{ .extra | safeHTMLAttr }}>
<noscript><link rel="stylesheet" href="{{ .url }}"></noscript>

View File

@@ -1,12 +1,27 @@
{{ $scratch := .scratch }}
{{ $scratch.Set "bestLength" -1 }}
{{ $scratch.Set "bestUrl" (printf "https://dev.danilafe.com/Web-Projects/blog-static/src/branch/master/code/%s" .path) }}
{{ $filePath := .path }}
{{ range $module, $props := .submoduleLinks }}
{{ $path := index $props "path" }}
{{ $bestLength := $scratch.Get "bestLength" }}
{{ if and (le $bestLength (len $path)) (hasPrefix $filePath $path) }}
{{ $scratch.Set "bestLength" (len $path) }}
{{ $scratch.Set "bestUrl" (printf "%s%s" (index $props "url") (strings.TrimPrefix $path $filePath)) }}
{{ end }}
{{ end }}
{{- $siteSourceUrl := site.Params.siteSourceUrl -}}
{{- $submoduleLinks := site.Data.submodules -}}
{{- $hostData := site.Data.hosts -}}
{{- $scratch := .scratch -}}
{{- $lines := .lines -}}
{{- $scratch.Set "bestLength" -1 -}}
{{- $scratch.Set "bestUrl" (printf "%s/code/%s" $siteSourceUrl .path) -}}
{{- $scratch.Set "bestPath" "" -}}
{{- $filePath := .path -}}
{{- range $path, $url := $submoduleLinks -}}
{{- $bestLength := $scratch.Get "bestLength" -}}
{{- if and (le $bestLength (len $path)) (hasPrefix $filePath $path) -}}
{{- $scratch.Set "bestLength" (len $path) -}}
{{- $scratch.Set "bestPath" $path -}}
{{- $scratch.Set "bestUrl" (printf "%s%s" $url (strings.TrimPrefix $path $filePath)) -}}
{{- end -}}
{{- end -}}
{{- if .lines -}}
{{- /* If the user provided a line range, see if we can tack it on to the end of the link. */ -}}
{{- range $host, $data := $hostData -}}
{{- if hasPrefix ($scratch.Get "bestUrl") $host -}}
{{- with $data.linesSuffix -}}
{{- $scratch.Add "bestUrl" (printf . (index $lines 0) (index $lines 1)) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -1,3 +1,3 @@
<div class="highlight-group">
<div class="highlight-label">From <a href="{{ .url }}">{{ path.Base .path }}</a>{{ .comment }}</div>{{ .content }}
<div class="highlight-group" {{ with .attrs }}{{ . | safeHTMLAttr }}{{ end }}>
<div class="highlight-label">{{ i18n "from" }} <a href="{{ .url }}">{{ path.Base .path }}</a>{{ .comment }}</div>{{ .content }}
</div>

View File

@@ -5,23 +5,95 @@
{{ if .Description }}
<meta name="description" content="{{ .Description }}">
{{ end }}
{{ with index (.GetTerms "series") 0 }}
<meta name="blog-series" content="{{ .Data.Term }}">
{{ end }}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&family=Raleway&family=Lora&display=block" media="screen">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css" media="screen">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous" media="screen">
{{ range .AlternativeOutputFormats -}}
{{ range .Params.discussionRooms }}
<meta name="matrix-highlight-comments" content="{{ . }}">
{{ end }}
<!-- Fonts -->
{{ if not (.Site.Params.noCss) }}
{{ $fonts := resources.Get "scss/fonts.scss" | css.Sass | resources.Minify }}
<link rel="stylesheet" href="{{ $fonts.Permalink }}" media="screen">
{{ end }}
<!-- External CSS (normalize and KaTeX -->
{{ if not (.Site.Params.noCss) }}
{{ partial "defercss.html" (dict "url" .Site.Params.normalizeCssUrl "extra" "") }}
{{ partial "defercss.html" (dict "url" .Site.Params.katexCssUrl "extra" "") }}
{{ end }}
<!-- Links to other formats (RSS, TOML) -->
{{ range .Site.Home.AlternativeOutputFormats -}}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type | html }}" href="{{ .Permalink | safeURL }}">
{{ end -}}
{{ $style := resources.Get "scss/style.scss" | resources.ToCSS | resources.Minify }}
{{ $sidenotes := resources.Get "scss/sidenotes.scss" | resources.ToCSS | resources.Minify }}
{{ $code := resources.Get "scss/code.scss" | resources.ToCSS | resources.Minify }}
<!-- In-house CSS -->
{{ $style := resources.Get "scss/style.scss" | css.Sass | resources.Minify }}
{{ $sidenotes := resources.Get "scss/sidenotes.scss" | css.Sass | resources.Minify }}
{{ $code := resources.Get "scss/code.scss" | css.Sass | resources.Minify }}
{{ $icon := resources.Get "img/favicon.png" }}
<style>.sidenote-checkbox { display: none; }</style>
<style>.feather { width: 1rem; height: 1rem; }</style>
<link rel="stylesheet" href="{{ $style.Permalink }}" media="screen">
<link rel="stylesheet" href="{{ $sidenotes.Permalink }}" media="screen">
<link rel="stylesheet" href="{{ $code.Permalink }}" media="screen">
<style>.feather { display: inline !important; width: 10px; height: 10px; }</style>
<style>img { max-width: 70%; }</style>
{{ if not (.Site.Params.noCss) }}
<link rel="stylesheet" href="{{ $style.Permalink }}">
{{ partial "defercss.html" (dict "url" $sidenotes.Permalink "extra" "") }}
{{ partial "defercss.html" (dict "url" $code.Permalink "extra" "") }}
{{ end }}
<link rel="icon" type="image/png" href="{{ $icon.Permalink }}">
{{ if .Params.custom_js }}
{{ range $customJs := .Params.custom_js }}
<script src="{{ page.Resources.Get $customJs }}"></script>
{{ end }}
{{ end }}
{{ if hugo.IsServer }}
<!-- KaTeX auto-rendering for when we don't have a post-processing step. -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.js" integrity="sha384-X/XCfMm41VSsqRNQgDerQczD69XqmjOOOwYQvr/uuC+j4OPoNhVgjdGFwhvN02Ja" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>
{{ end }}
{{ if .Params.bergamot }}
<!-- Code to support the Bergamot JS widget -->
<script defer src="{{ .Site.Params.katexJsUrl }}" crossorigin="anonymous"></script>
{{ $katexComponentJs := resources.Get "js/katex-component.js" | resources.Minify }}
<script defer src="{{ $katexComponentJs.Permalink }}"></script>
<script defer src="{{ .Site.Params.bergamotJsUrl }}"></script>
<script defer src="{{ .Site.Params.bergamotObjectLanguageJsUrl }}"></script>
{{ $bergamotHelpers := resources.Get "js/bergamot-helpers.js" | resources.Minify }}
<script defer src="{{ $bergamotHelpers.Permalink }}"></script>
{{ $bergamotStyle := resources.Get "scss/bergamot.scss" | css.Sass | resources.Minify }}
{{ partial "defercss.html" (dict "url" $bergamotStyle.Permalink "extra" "") }}
{{ if .Params.bergamot.render_presets }}
{{ range $name, $rulefile := .Params.bergamot.render_presets }}
{{ $file := default (resources.Get $rulefile) (page.Resources.Get $rulefile) }}
{{ partial "bergamotrenderpreset.html" (dict "name" $name "file" $file.Content) }}
{{ end }}
{{ else }}
{{ partial "bergamotrenderpreset.html" (dict "name" "default" "file" (resources.Get "bergamot/rendering/minimal.bergamot").Content) }}
{{ end }}
{{ if .Params.bergamot.presets }}
{{ range $name, $preset := .Params.bergamot.presets }}
{{ $file := default (resources.Get $preset.file) (page.Resources.Get $preset.file) }}
{{ $info := dict "name" $name "prompt" $preset.prompt "query" $preset.query "file" $file.Content "renderPreset" $preset.render_preset "inputModes" $preset.input_modes }}
{{ partial "bergamotpreset.html" $info }}
{{ end }}
{{ end }}
{{ if .Params.bergamot.input_modes }}
{{ range $mode := .Params.bergamot.input_modes }}
{{ partial "bergamotinputmode.html" (dict "name" $mode.name "fn" $mode.fn) }}
{{ end }}
{{ end }}
{{ end }}
{{ with .Site.Params.plausibleAnalyticsDomain }}
<!-- Plausible analytics, because log parsing is not working all that well. -->
<script defer data-domain="{{ . }}" src="https://plausible.io/js/script.js"></script>
{{ end }}
<title>{{ .Title }}</title>
</head>

View File

@@ -1,15 +1,20 @@
<div class="container">
<h1>Daniel's Blog</h1>
<h1>{{ .Site.Title }}</h1>
</div>
<nav>
<div class="container">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="https://github.com/DanilaFe">GitHub</a>
<a href="/Resume-Danila-Fedorin.pdf">Resume</a>
<a href="/tags">Tags</a>
<a href="/favorites">Favorites</a>
<a href="/search">Search</a>
<a href="/blog">All Posts</a>
<a href="{{ .Site.Home.Permalink }}">{{ i18n "home" }}</a>
<a href="{{ relref . "about" }}">{{ i18n "about" }}</a>
{{ with .Site.Params.githubUsername }}
<a href="https://github.com/{{ . }}">GitHub</a>
{{ end }}
{{ if .Site.Params.resumeStaticFile }}
<a href="{{ absLangURL .Site.Params.resumeStaticFile }}">{{ i18n "resume" }}</a>
{{ end }}
<a href="{{ site.Taxonomies.tags.Page.Permalink }}">{{ i18n "tags" }}</a>
<a href="{{ site.Taxonomies.series.Page.Permalink }}">{{ i18n "series" }}</a>
<a href="{{ relref . "favorites" }}">{{ i18n "favorites" }}</a>
<a href="{{ relref . "search" }}">{{ i18n "search" }}</a>
<a href="{{ relref . "blog" }}">{{ i18n "allPosts" }}</a>
</div>
</nav>

View File

@@ -1 +1,11 @@
{{ partial "group.html" (dict "url" .url "path" .path "comment" .comment "content" (highlight .code .language .opts)) }}
{{- $highlightGroupAttrs := (printf "data-base-path=\"%s\" data-file-path=\"%v\"" .basePath .path) -}}
{{- if (or .firstLine .lastLine) -}}
{{- $highlightGroupAttrs = add $highlightGroupAttrs (printf " data-first-line=\"%v\" data-last-line=\"%v\"" .firstLine .lastLine) -}}
{{- end -}}
{{- if eq (lower .language) "agda" -}}
{{- $highlightGroupAttrs = add $highlightGroupAttrs " data-agda-block" -}}
{{- end -}}
{{- with .offset -}}
{{- $highlightGroupAttrs = add $highlightGroupAttrs (printf " data-source-offset=\"%v\"" .) -}}
{{- end -}}
{{ partial "group.html" (dict "url" .url "path" .path "comment" .comment "content" (highlight .code .language .opts) "attrs" $highlightGroupAttrs) }}

View File

@@ -1,3 +1,4 @@
<svg class="feather">
<svg class="feather" style="display: none;">
<use xlink:href="/feather-sprite.svg#{{ . }}"/>
</svg>
{{- /* This comment is to remove trailing whitespace */ -}}

Before

Width:  |  Height:  |  Size: 81 B

After

Width:  |  Height:  |  Size: 164 B

View File

@@ -0,0 +1,9 @@
{{ if eq .from .to }}
{{ .scratch.Set "comment" (printf ", line %d" .from) }}
{{ else }}
{{ if eq .from 0 }}
{{ .scratch.Set "comment" (printf ", around line %d" .to) }}
{{ else }}
{{ .scratch.Set "comment" (printf ", lines %d through %d" .from .to) }}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,8 @@
{{- $term := index (.page.GetTerms "series") 0 -}}
{{- $divider := $term.Params.divider -}}
{{- if (and $divider (strings.Contains .page.Title $divider)) -}}
{{- $rest := after 1 (split .page.Title $divider) -}}
{{- .scratch.Set "name" (delimit $rest $divider) -}}
{{- else -}}
{{- .scratch.Set "name" .page.Title -}}
{{- end -}}

View File

@@ -1,5 +1,27 @@
<li>
<a href="{{ .Permalink }}" class="post-title">{{ if .Params.favorite }}{{ partial "icon.html" "star" }}{{ end }} {{ .Title }}</a>
<p class="post-wordcount">{{ .WordCount }} words, about {{ .ReadingTime }} minutes to read.</p>
<p class="post-preview">{{ .Summary }} . . .</p>
{{- $scratch := newScratch -}}
{{- if .seriesName -}}
{{- partial "nameinseries" (dict "page" .page "scratch" $scratch) -}}
{{- else -}}
{{- $scratch.Set "name" (.page.Title) -}}
{{- end -}}
<a href="{{ .page.Permalink }}" class="post-title">{{ if .page.Params.favorite }}{{ partial "icon.html" "star" }}{{ end }} {{ $scratch.Get "name" }}</a>
{{ if (not (eq .page.WordCount 0)) }}
<p class="post-wordcount">{{ i18n "nWords" .page.WordCount }}, {{ i18n "nMinutesToRead" .page.ReadingTime }}.</p>
{{ end }}
{{ if .page.Params.status }}
<p class="post-status">
{{ partial "seriesstatus.html" .page.Params.status }}
</p>
{{ end }}
<p class="post-preview">{{ partial "summary" .page }}</p>
{{- if .linkSeries -}}
{{- $term := index (.page.GetTerms "series") 0 -}}
{{- with $term -}}
<div class="series-link">
{{- partial "icon.html" "corner-down-right" -}}
<p>{{- i18n "latestInSeries" }} <a href="{{ $term.Permalink }}">{{ $term.Title }}</a></p>
</div>
{{- end -}}
{{- end }}
</li>

View File

@@ -0,0 +1,12 @@
<div class="{{ .direction }} wrapper">
<a href="{{ .page.RelPermalink }}">
{{ if eq .direction "previous" }}{{ partial "icon.html" "chevrons-left" }}{{ end }}
<div class="title-subtitle">
{{ title .direction }} in Series
{{ $scratch := newScratch -}}
{{- partial "nameinseries.html" (dict "page" .page "scratch" $scratch) -}}
<div class="title">{{ $scratch.Get "name" }}</div>
</div>
{{ if eq .direction "next" }}{{ partial "icon.html" "chevrons-right" }}{{ end }}
</a>
</div>

View File

@@ -0,0 +1,10 @@
<div class="{{ .direction }} wrapper">
<div class="ongoing-placeholder">
{{ if eq .direction "previous" }}{{ partial "icon.html" "chevrons-left" }}{{ end }}
<div class="title-subtitle">
{{ title .direction }} in Series
<div class="title">Coming soon!</div>
</div>
{{ if eq .direction "next" }}{{ partial "icon.html" "chevrons-right" }}{{ end }}
</div>
</div>

View File

@@ -0,0 +1,17 @@
{{- $page := . -}}
{{- $term := index (.GetTerms "series") 0 -}}
{{- with $term -}}
{{- /* No idea why the 'Reverse' is needed? */ -}}
{{- $pages := (site.Taxonomies.series.Get .Data.Term).Pages.ByDate.Reverse -}}
<nav class="series-navigation">
{{- with $pages.Prev $page -}}
{{- partial "serieslink.html" (dict "direction" "previous" "page" .) -}}
{{- end -}}
{{- $nextPage := $pages.Next $page -}}
{{- if $nextPage -}}
{{- partial "serieslink.html" (dict "direction" "next" "page" $nextPage) -}}
{{- else if eq $term.Params.status "ongoing" -}}
{{- partial "serieslinkplaceholder.html" (dict "direction" "next") -}}
{{- end -}}
</nav>
{{- end -}}

View File

@@ -0,0 +1,4 @@
<span class="series-status {{ . }}">
{{ i18n "seriesStatus" }}
<span class="series-status-keyword">{{ i18n (printf "%sSeries" .) }}</span>
</span>

View File

@@ -0,0 +1,5 @@
{{- if .Params.summary -}}
{{ .Params.summary }}
{{- else -}}
{{ .Summary | plainify | truncate 180 }}
{{- end -}}

View File

@@ -0,0 +1,14 @@
{{- $scratch := .scratch -}}
{{- $scratch.Set "pages" slice -}}
{{- $tmpScratch := newScratch -}}
{{- range $post := (where (where site.Pages.ByDate.Reverse "Section" "blog") ".Kind" "!=" "section") -}}
{{- $term := index ($post.GetTerms "series") 0 -}}
{{- if $term -}}
{{- if not ($tmpScratch.Get $term.Permalink) -}}
{{- $tmpScratch.Set $term.Permalink true -}}
{{- $scratch.Add "pages" $post -}}
{{- end -}}
{{- else -}}
{{- $scratch.Add "pages" $post -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,3 @@
<div class="warning">
<em>{{ i18n "warning" }}</em> {{ . }}
</div>

View File

@@ -2,12 +2,12 @@
<h2>{{ .Title }} </h2>
{{ .Content }}
{{ $search := resources.Get "scss/search.scss" | resources.ToCSS | resources.Minify }}
{{ $search := resources.Get "scss/search.scss" | css.Sass | resources.Minify }}
<link rel="stylesheet" href="{{ $search.Permalink }}" media="screen">
<div class="stork-wrapper">
<div class="stork-input-wrapper">
<input class="stork-input" data-stork="blog" placeholder="Search (requires JavaScript)"/>
<input class="stork-input" data-stork="blog" placeholder="{{ i18n "searchRequiresJS" }}"/>
</div>
<div class="stork-output" data-stork="blog-output"></div>
</div>

17
layouts/series/list.html Normal file
View File

@@ -0,0 +1,17 @@
{{ define "main" }}
<h2>{{ .Title }}</h2>
{{ $pages := .Pages.ByDate }}
{{ $startYear := (index (last 1 .Pages) 0).Date.Format "2006" }}
{{ $endYear := (index (first 1 .Pages) 0).Date.Format "2006" }}
<div class="post-subscript">
<p>{{ partial "seriesstatus.html" .Params.status }}</p>
<p>{{ i18n "postsFromTo" (dict "from" $startYear "to" $endYear) }}</p>
</div>
<p>{{ partial "summary" . }}</p>
<ul class="post-list">
{{ range $pages }}
{{ partial "post.html" (dict "page" . "seriesName" true) }}
{{ end }}
</ul>
{{ end }}

10
layouts/series/terms.html Normal file
View File

@@ -0,0 +1,10 @@
{{ define "main" }}
<h2>{{ .Title }}</h2>
{{ .Content }}
<ul class="post-list">
{{ range sort .Pages "Title" }}
{{ partial "post.html" (dict "page" .) }}
{{ end }}
</ul>
{{ end }}

View File

@@ -0,0 +1,21 @@
<div class="bergamot-exercise">
<details open>
<summary>
<span class="bergamot-exercise-label">
<span class="bergamot-exercise-number"></span>
{{ if or (eq (.Get "label") "") (eq (.Get "label") nil) }}{{ else }}({{ .Get "label" }}){{ end }}:
</span>
</summary>
{{ transform.Markdownify .Inner }}
<div class="bergamot-button-group">
{{ if or (eq (.Get "preset") "") (eq (.Get "preset") nil) }}
{{ else }}
<button class="bergamot-button bergamot-play" onclick='window.Bergamot.runPreset(this.parentElement, "bergamot-widget-container-{{ .Get "id" }}", "{{ .Get "preset" }}")'>{{ partial "icon.html" "play" }}Start Bergamot</button>
<button class="bergamot-button bergamot-close bergamot-hidden" onclick='window.Bergamot.close(this.parentElement, "bergamot-widget-container-{{ .Get "id" }}")'>{{ partial "icon.html" "x" }}Close Bergamot</button>
{{ end }}
</div>
<div id="bergamot-widget-container-{{ .Get "id" }}"></div>
</details>
</div>

View File

@@ -0,0 +1,8 @@
<div id="{{ .Get "id" }}"></div>
<script>
window.addEventListener('load', function() {
window.Bergamot.run(null, '{{ .Get "id" }}',
{{ partial "bergamotparseinputmodes.js" (.Get "modes") | safeJS }},
'{{ .Get "prompt" }}', '{{ .Inner }}', '{{ default "default" (.Get "rendering") }}', '{{ .Get "query" }}');
});
</script>

View File

@@ -0,0 +1,3 @@
<div class="block">
{{- .Inner -}}
</div>

View File

@@ -1,2 +1,12 @@
{{ partial "geturl.html" (dict "scratch" .Scratch "path" (.Get 1) "submoduleLinks" .Site.Params.submoduleLinks) }}
{{ partial "highlightgroup.html" (dict "url" (.Scratch.Get "bestUrl") "path" (.Get 1) "comment" ", entire file" "code" (readFile (printf "code/%s" (.Get 1))) "language" (.Get 0) "opts" "linenos=table") }}
{{- $scratch := newScratch -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 1)) -}}
{{- $groupconfig := dict
"url" ($scratch.Get "bestUrl")
"basePath" ($scratch.Get "bestPath")
"path" (.Get 1)
"comment" ", entire file"
"code" (readFile (printf "code/%s" (.Get 1)))
"language" (.Get 0)
"opts" "linenos=table"
-}}
{{- partial "highlightgroup.html" $groupconfig -}}

View File

@@ -1,23 +1,59 @@
{{ $source := (readFile (printf "code/%s" (.Get 1))) }}
{{ $allLines := split $source "\n" }}
{{ if not (eq (int (.Get 2)) 1) }}
{{ .Scratch.Set "remLines" (after (sub (int (.Get 2)) 1) $allLines) }}
{{ else }}
{{ .Scratch.Set "remLines" $allLines }}
{{ end }}
{{ $lines := first (add (sub (int (.Get 3)) (int (.Get 2))) 1) (.Scratch.Get "remLines") }}
{{- $source := (readFile (printf "code/%s" (.Get 1))) -}}
{{- $allLines := split $source "\n" -}}
{{- $scratch := newScratch -}}
{{- $remLines := $allLines -}}
{{- if not (eq (int (.Get 2)) 1) -}}
{{- $remLines = after (sub (int (.Get 2)) 1) $allLines -}}
{{- end -}}
{{- $lines := first (add (sub (int (.Get 3)) (int (.Get 2))) 1) $remLines -}}
{{ if (.Get 4) }}
{{ .Scratch.Set "opts" (printf ",%s" (.Get 4)) }}
{{ else }}
{{ .Scratch.Set "opts" "" }}
{{ end }}
{{- $opts := "" -}}
{{- if (.Get 4) -}}
{{- $opts = printf ",%s" (.Get 4) -}}
{{- end -}}
{{ partial "geturl.html" (dict "scratch" .Scratch "path" (.Get 1) "submoduleLinks" .Site.Params.submoduleLinks) }}
{{- if (.Get 5) -}}
{{- $scratch.Set "hidden" (.Get 5) -}}
{{- end -}}
{{ if eq (.Get 2) (.Get 3) }}
{{ .Scratch.Set "comment" (printf ", line %d" (.Get 2)) }}
{{ else }}
{{ .Scratch.Set "comment" (printf ", lines %d through %d" (.Get 2) (.Get 3)) }}
{{ end }}
{{ partial "highlightgroup.html" (dict "url" (.Scratch.Get "bestUrl") "path" (.Get 1) "comment" (.Scratch.Get "comment") "code" (delimit $lines "\n") "language" (.Get 0) "opts" (printf "linenos=table,linenostart=%d%s" (.Get 2) (.Scratch.Get "opts"))) }}
{{- $prefixLength := "" -}}
{{- $joinedLines := "" -}}
{{- if or (.Page.Params.left_align_code) (.Get 6) -}}
{{- $prefixLength = -1 -}}
{{- range $line := $lines -}}
{{- $leading := sub (len $line) (len (strings.TrimLeft " " $line)) -}}
{{- if and (ne $line "") (or (eq $prefixLength -1) (le $leading $prefixLength)) -}}
{{- $prefixLength = $leading -}}
{{- end -}}
{{- end -}}
{{- range $line := $lines -}}
{{- $joinedLines = add $joinedLines (substr $line $prefixLength) -}}
{{- $joinedLines = add $joinedLines "\n" -}}
{{- end -}}
{{- else -}}
{{- $joinedLines = delimit $lines "\n" -}}
{{- end -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 1) "lines" (slice (.Get 2) (.Get 3))) -}}
{{- partial "linerangestr.html" (dict "scratch" $scratch "from" (.Get 2) "to" (.Get 3)) -}}
{{- with ($scratch.Get "hidden") -}}
<details><summary>{{- . | markdownify -}}</summary>
{{- end -}}
{{- $groupconfig := dict
"url" ($scratch.Get "bestUrl")
"basePath" ($scratch.Get "bestPath")
"path" (.Get 1)
"comment" ($scratch.Get "comment")
"code" $joinedLines
"firstLine" (int (.Get 2))
"lastLine" (int (.Get 3))
"language" (.Get 0)
"offset" $prefixLength
"opts" (printf "linenos=table,linenostart=%d%s" (.Get 2) $opts)
-}}
{{- partial "highlightgroup.html" $groupconfig -}}
{{- with ($scratch.Get "hidden") -}}
</details>
{{- end -}}

View File

@@ -0,0 +1,3 @@
{{- $scratch := newScratch -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 0)) -}}
{{- $scratch.Get "bestUrl" -}}

View File

@@ -0,0 +1,4 @@
<details>
<summary>{{- .Get "summary" | markdownify -}}</summary>
{{- .Inner | markdownify -}}
</details>

View File

@@ -1,3 +1,3 @@
<p class="dialog">
{{ .Inner }}
{{- .Inner -}}
</p>

View File

@@ -0,0 +1,6 @@
{{- $page := site.GetPage (.Get 1) -}}
{{- if $page -}}
<a href="{{ $page.RelPermalink }}">{{ .Get 0 }}</a>
{{- else -}}
<span class="draft-link">{{ .Get 0 }} (coming soon)</span>
{{- end -}}

View File

@@ -0,0 +1 @@
<span class="fold-table"></span>

View File

@@ -0,0 +1,11 @@
{{- $repo := .Get 0 -}}
{{- $commit := .Get 1 -}}
{{- $file := .Get 2 -}}
{{- $lang := .Get 3 -}}
{{- $line := .Get 4 -}}
{{- $lines := split (trim .Inner "\n") "\n" -}}
{{- $scratch := newScratch -}}
{{- $url := printf "https://github.com/%s/blob/%s/%s#L%d" $repo $commit $file $line -}}
{{- partial "linerangestr.html" (dict "scratch" $scratch "from" 0 "to" $line) -}}
{{- partial "highlightgroup.html" (dict "url" $url "path" $file "comment" ($scratch.Get "comment") "code" (trim .Inner "\n") "language" $lang) -}}

View File

@@ -0,0 +1,12 @@
{{- $name := .Get 0 -}}
{{- $number := 1 -}}
{{- with .Page.Scratch.Get "internal-ref-counter" -}}
{{- $number = add . 1 }}
{{- end -}}
{{- .Page.Scratch.Set "internal-ref-counter" $number -}}
{{- .Page.Scratch.SetInMap "internal-ref" $name $number -}}
<span class="internal-ref" id="internal-ref-{{ $name }}">
{{ .Inner }}
<span class="internal-ref-counter">{{ $number }}</span></span>
{{- /* chomp whitespace at the end */ -}}

View File

@@ -0,0 +1,7 @@
{{- $name := .Get 0 -}}
{{- $number := index (.Page.Scratch.Get "internal-ref") $name -}}
<a href="#internal-ref-{{ $name }}">
{{ .Inner }}
<span class="internal-ref-counter">{{ $number }}</span></a>
{{- /* chomp whitespace at the end */ -}}

View File

@@ -1,4 +1,10 @@
<span class="message side-{{ .Get 0 }}">
<span class="message-sender">{{ partial "icon.html" "user" }}</span>
<span>{{ .Inner }}</span>
<span class="message-sender">
{{- if (eq (.Get 1) "reader") -}}
{{- partial "icon.html" "moon" -}}
{{- else -}}
{{- partial "icon.html" "sun" -}}
{{- end -}}
</span>
<span class="message-text">{{- .Inner -}}</span>
</span>

View File

@@ -1,11 +0,0 @@
{{ .Page.Scratch.Add "numbernote-id" 1 }}
{{ $id := .Page.Scratch.Get "numbernote-id" }}
<span class="sidenote">
<label class="sidenote-label" for="numbernote-{{ $id }}">({{ $id }})</label>
<input class="sidenote-checkbox" type="checkbox" id="numbernote-{{ $id }}"></input>
<span class="sidenote-content sidenote-{{ .Get 0 }}">
<span class="sidenote-delimiter">[note:</span>
{{ .Inner }}
<span class="sidenote-delimiter">]</span>
</span>
</span>

View File

@@ -1,2 +1,10 @@
{{ partial "geturl.html" (dict "scratch" .Scratch "path" (.Get 0) "submoduleLinks" .Site.Params.submoduleLinks) }}
{{ partial "group.html" (dict "url" (.Scratch.Get "bestUrl") "path" (.Get 0) "comment" ", entire file" "content" (safeHTML (printf "<pre><code>%s</code></pre>" (htmlEscape (readFile (printf "code/%s" (.Get 0))))))) }}
{{- $scratch := newScratch -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 0) "siteSourceUrl" .Site.Params.siteSourceUrl "submoduleLinks" .Site.Data.submodules) -}}
{{- $groupconfig := dict
"url" ($scratch.Get "bestUrl")
"basePath" ($scratch.Get "bestPath")
"path" (.Get 0)
"comment" ", entire file"
"content" (safeHTML (printf "<pre><code>%s</code></pre>" (htmlEscape (readFile (printf "code/%s" (.Get 0))))))
-}}
{{- partial "group.html" $groupconfig -}}

View File

@@ -0,0 +1,3 @@
<div class="early-navigation-wrapper">
{{ partial "seriesnav.html" .Page }}
</div>

View File

@@ -0,0 +1,3 @@
<div class="side-by-side">
{{ .Inner }}
</div>

View File

@@ -0,0 +1,3 @@
<div class="side-by-side-item" {{ with .Get "weight" }} style="flex-grow: {{ . }};" {{ end }}>
{{ .Inner }}
</div>

View File

@@ -1,9 +1,13 @@
<span class="sidenote">
<label class="sidenote-label" for="{{ .Get 1 }}">{{ .Get 2 }}</label>
<input class="sidenote-checkbox" type="checkbox" id="{{ .Get 1 }}"></input>
<span class="sidenote-content sidenote-{{ .Get 0 }}">
<span class="sidenote-delimiter">[note:</span>
{{ .Inner }}
<label class="sidenote-label" for="{{- .Get 1 -}}">{{- .Get 2 | markdownify -}}</label>
<input class="sidenote-checkbox" style="display: none;" type="checkbox" id="{{- .Get 1 -}}"></input>
{{- if $offset := .Get 3 -}}
<span class="sidenote-content sidenote-{{- .Get 0 -}}" style="margin-top: {{- $offset -}}rem">
{{- else -}}
<span class="sidenote-content sidenote-{{- .Get 0 -}}">
{{- end -}}
<span class="sidenote-delimiter">[{{- i18n "note" -}}:</span>
{{- .Inner -}}
<span class="sidenote-delimiter">]</span>
</span>
</span>

View File

@@ -1,3 +0,0 @@
<div style="background-color: tomato; color: white; padding: 10px;">
<em>TODO: </em>{{ .Inner }}
</div>

View File

@@ -1,9 +1,9 @@
{{ define "main" }}
<h2>Tagged "{{ .Title }}"</h2>
<h2>{{ i18n "tagged" .Title }}</h2>
<ul class="post-list">
{{ range .Pages.ByDate.Reverse }}
{{ partial "post.html" . }}
{{ partial "post.html" (dict "page" .) }}
{{ end }}
</ul>
{{ end }}

View File

@@ -1,6 +1,6 @@
{{ define "main" }}
<h2>{{ .Title }}</h2>
Below is a list of all the tags ever used on this site.
{{ .Content }}
<ul>
{{ range sort .Pages "Title" }}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

53
static/graph/graph.js Normal file
View File

@@ -0,0 +1,53 @@
import { nodes, edges } from "./graph.gen.js";
var container = document.getElementById("graph-container");
var options = {
interaction: {
hover: true
},
nodes: {
shape: "dot",
size: 16,
},
physics: {
forceAtlas2Based: {
gravitationalConstant: -10,
centralGravity: 0.005,
springLength: 230,
springConstant: 0.18,
},
maxVelocity: 146,
solver: "forceAtlas2Based",
timestep: 0.35,
stabilization: { iterations: 150 },
},
};
var nodesDs = new vis.DataSet();
nodesDs.add(nodes);
var edgesDs = new vis.DataSet();
edgesDs.add(edges);
var network = new vis.Network(container, { nodes: nodesDs, edges: edgesDs }, options);
network.on("doubleClick", function (params) {
params.event = "[original event]";
if (params.nodes.length !== 1) return;
window.open(nodesDs.get(params.nodes[0]).url, "_blank")
});
network.on("hoverNode", function (params) {
nodesDs.update({ id: params.node, label: nodesDs.get(params.node).name });
});
network.on("blurNode", function (params) {
nodesDs.update({ id: params.node, label: undefined });
});
// network.on("selectNode", function (params) {
// for (const node of params.nodes) {
// nodesDs.update({ id: node, label: nodesDs.get(node).name });
// }
// });
// network.on("deselectNode", function (params) {
// for (const node of params.previousSelection.nodes) {
// if (params.nodes.some(n => n === node)) continue;
// nodesDs.update({ id: node, label: undefined });
// }
// });