From 27ea82a5c7c2a6a25f2f4a1d4d0d9f084cfdbe89 Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 19:51:39 -0400 Subject: [PATCH 1/9] many updates + darkmode - Use new ssgen version: - yaml metadata - dev hot-reloader - better markdown support - Fix github actions workflows - Syntax highlighting with prism - Light/dark theme toggle --- .github/workflows/comments.yml | 54 ++-- .github/workflows/release.yml | 37 +-- Makefile | 18 +- src/about.md | 4 +- src/blog.md | 4 +- src/blog/blog-comments.md | 13 +- src/blog/blogging-on-github.md | 12 +- src/blog/cultivate-post-mortem.md | 9 +- src/blog/flappyjam.md | 8 +- src/blog/haxe-and-google-play-services.md | 11 +- src/blog/haxe-signals.md | 9 +- src/blog/trying-twine-textjam.md | 8 +- src/projects.md | 4 +- src/projects/cultivate.md | 12 +- src/projects/isolation.md | 12 +- src/projects/lark.md | 12 +- src/projects/lvrg.md | 12 +- src/projects/maera.md | 12 +- src/projects/scraps.md | 10 +- src/projects/sundiver.md | 12 +- src/projects/testris.md | 12 +- src/projects/tinyforum.md | 12 +- static/prism-base.css | 215 +++++++++++++++ static/prism.js | 15 ++ static/style.css | 308 ++++++++++++++++++++-- templates/blog.html | 2 +- templates/include/base.html | 26 +- 27 files changed, 710 insertions(+), 153 deletions(-) create mode 100644 static/prism-base.css create mode 100644 static/prism.js diff --git a/.github/workflows/comments.yml b/.github/workflows/comments.yml index 2ca7757..6a765d4 100644 --- a/.github/workflows/comments.yml +++ b/.github/workflows/comments.yml @@ -9,41 +9,49 @@ jobs: - name: checkout uses: actions/checkout@v2 - name: collect-titles - run: "grep -E '@name\\s*\\=' ./src/blog/ -R > posts.txt && cat posts.txt" + run: "grep -E '^name\\s*\\:' ./src/blog/ -R > posts.txt && cat posts.txt" + - name: deps + run: | + npm install -g js-yaml - uses: actions/github-script@v3 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | - const fs = require("fs") - const { owner, repo } = context.repo - const result = await github.issues.listForRepo({ owner, repo }) - const issues = Object.fromEntries(result.data.map(x => [x.title, x])) - let lines = fs.readFileSync('posts.txt').toString().split('\n') + const fs = require("fs"); + const yaml = require("js-yaml"); + const { owner, repo } = context.repo; + const result = await github.issues.listForRepo({ owner, repo }); + const issues = Object.fromEntries(result.data.map(x => [x.title, x])); + let lines = fs.readFileSync('posts.txt').toString().split('\n'); lines.forEach(l => { - l = l.trim() - if (!l) return - let [f, nameLine] = l.split(':') - let labels = ["blog-post"] - const body = fs.readFileSync(f).toString().split('\n').map(x => { - if (x.match(/^\s*@labels/)) { - labels = labels.concat(x.trim().slice(x.indexOf('=')+1).split(",").map(l => l.trim())) + l = l.trim() + if (!l) return; + let [f, nameLine] = l.split(':', 2); + let title = nameLine.slice(nameLine.indexOf(':')+1).trim(); + let labels = ["blog-post"]; + let contents = fs.readFileSync(f).toString().trim(); + if contents.startsWith('---') { + const [_, metaString, rest] = contents.split('---', 3); + const meta = yaml.load(metaString); + labels = labels.concat(meta['labels'] || []); + if (meta['name']) { + title = meta['name'].trim(); } - return x - }).filter(x => !x.match(/^@/)) - .join('\n') + contents = rest; + } + const body = contents .replace(/(!\[[^\]]*\]\()(\/[^\)]+\))/g, `$1https://github.com/${owner}/${repo}/raw/master$2`) // MD image .replace(/(\[[^\]]*\]\()(\/[^\)]+\))/g, `$1https://github.com/${owner}/${repo}/blob/master$2`) // MD link - .replace(/(src=")(\/[^"]+")/g, `$1https://github.com/${owner}/${repo}/raw/master$2`) // tag - const title = nameLine.slice(nameLine.indexOf('=')+1).trim() + .replace(/(src=")(\/[^"]+")/g, `$1https://github.com/${owner}/${repo}/raw/master$2`); // tag if (title in issues) { - const found = issues[title] + const found = issues[title]; github.issues.update({ owner, repo, issue_number: found.number, labels: found.labels.concat(labels), title, body, - }) - return + }); + return; } - github.issues.create({ owner, repo, title, body, labels }) - }) + github.issues.create({ owner, repo, title, body, labels }); + }); diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8997355..fe37790 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,33 +7,34 @@ jobs: announce: runs-on: ubuntu-latest steps: + - run: npm install -g js-yaml - uses: actions/github-script@v3 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | - const pr = context.payload.pull_request + const yaml = require("js-yaml"); + const pr = context.payload.pull_request; if (pr.state !== "open" && pr.merged_at === null) { - console.log("pr was not merged, skipping") - return + console.log("pr was not merged, skipping"); + return; } - let urlBase = "https://kylemtravis.com/blog" + let urlBase = "https://kylemtravis.com/blog"; if (pr.state === "open") - urlBase = `https://deploy-preview-${pr.number}--kylemtravis.netlify.app/blog` + urlBase = `https://deploy-preview-${pr.number}--kylemtravis.netlify.app/blog`; const result = await github.pulls.listFiles({ pull_number: pr.number, owner: context.repo.owner, repo: context.repo.repo, - }) - const added = result.data.filter(f => f.status === "added") - const newBlogPosts = added.filter(f => f.filename.match(/src\/blog\//) !== null) + }); + const added = result.data.filter(f => f.status === "added"); + const newBlogPosts = added.filter(f => f.filename.match(/src\/blog\//) !== null); if (newBlogPosts.length < 1) - return + return; - const releaseName = newBlogPosts[0].patch.match(/@name\s*=\s*(.+)/)[1] - let slug = releaseName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9\-]/g, "") - const slugMatch = newBlogPosts[0].patch.match(/@slug\s*=\s*(.+)/) - if (slugMatch && slugMatch.length > 1) - slug = slugMatch[1] + const [_, metaString, _] = newBlogPosts[0].patch.split('---', 3); + const meta = yaml.load(metaString); + const releaseName = meta['name']; + const slug = meta['slug'] || releaseName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9\-]/g, ""); const rel = { owner: context.repo.owner, @@ -43,17 +44,17 @@ jobs: name: `[Blog Post] ${releaseName}`, body: `New blog post, read it [here](${urlBase}/${slug})!`, draft: pr.state === "open", - } + }; const rels = await github.repos.listReleases({ owner: context.repo.owner, repo: context.repo.repo, - }) - const found = rels.data.filter(r => r.draft && r.tag_name == rel.tag_name) + }); + const found = rels.data.filter(r => r.draft && r.tag_name == rel.tag_name); await (found.length > 1 ? github.repos.updateRelease({ release_id: found[0].id, ...rel }) : github.repos.createRelease(rel) - ) + ); diff --git a/Makefile b/Makefile index 78396ee..8525fe5 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,17 @@ .PHONY: clean build deploy -clean: - rm -rf build/* bin/* +SSGEN := $(shell go env GOPATH)/bin/ssgen +PORT := 8081 -build: - command -v ssgen || go install github.com/ktravis/ssgen@latest - PATH=$$(go env GOPATH)/bin:$$PATH ssgen -in src -out build +$(SSGEN): + go install github.com/ktravis/ssgen@latest + +build: $(SSGEN) + $(SSGEN) -in src -out build cp -R static/ build/ + +serve: $(SSGEN) + $(SSGEN) -serve localhost:$(PORT) + +clean: + rm -rf build/* bin/* diff --git a/src/about.md b/src/about.md index c75cfc2..ad679e8 100644 --- a/src/about.md +++ b/src/about.md @@ -1,4 +1,6 @@ -@title = about +--- +title: about +--- ```json { diff --git a/src/blog.md b/src/blog.md index 99565f4..46cd4dc 100644 --- a/src/blog.md +++ b/src/blog.md @@ -1,3 +1,5 @@ -@template = blog +--- +template: blog +--- testing diff --git a/src/blog/blog-comments.md b/src/blog/blog-comments.md index aee1178..3fced13 100644 --- a/src/blog/blog-comments.md +++ b/src/blog/blog-comments.md @@ -1,9 +1,10 @@ -@name = Blog Comments With GitHub -@slug = blog-comments -@published = 2020-09-09 -@labels = meta - -[//]: # (testing) +--- +name: Blog Comments With GitHub +slug: blog-comments +published: 2020-09-09 +labels: meta +previewLines: 3 +--- _For more background, see my [previous post](https://kylemtravis.com/blog/blogging-with-github) about GitHub Actions._ diff --git a/src/blog/blogging-on-github.md b/src/blog/blogging-on-github.md index 8c435de..59052fa 100644 --- a/src/blog/blogging-on-github.md +++ b/src/blog/blogging-on-github.md @@ -1,14 +1,16 @@ -@name = Blogging With GitHub -@published = 2020-08-28 -@labels = meta - +--- +name: Blogging With GitHub +published: 2020-08-28 +labels: meta +previewLines: 15 +--- _Obligatory "wow it's been so long since I've written here!"_ In an effort to reduce the (admittedly already low) friction of writing blog posts, I'm now hosting this site on [netlify](https://netlify.com), which makes it pretty effortless to generate site previews off of pull requests, as well as perform the usual tasks like updating DNS, provisioning a Let's Encrypt cert, etc. I'm still using [my own static site generator](https://github.com/ktravis/ssgen) which was easy to integrate with netlify's GitHub App: I set my site's "build command" to `make build`, which runs: -```make +```makefile SSGEN_BIN ?= ./ssgen build: $(SSGEN_BIN) diff --git a/src/blog/cultivate-post-mortem.md b/src/blog/cultivate-post-mortem.md index a4936cf..627d476 100644 --- a/src/blog/cultivate-post-mortem.md +++ b/src/blog/cultivate-post-mortem.md @@ -1,6 +1,9 @@ -@name = Cultivate Post-Mortem -@published = 2016-01-03 -@labels = game,ludum-dare,unity +--- +name: Cultivate Post-Mortem +published: 2016-01-03 +labels: game,ludum-dare,unity +previewLines: 3 +--- Hello there! With just over a day remaining in the voting period, it seemed like a great time to finally write up a post-mortem for my experience this time around. I've included my favorites/recommendations of the entries that I've played so far **at the end of this post.** diff --git a/src/blog/flappyjam.md b/src/blog/flappyjam.md index b94d6a7..8c0be5d 100644 --- a/src/blog/flappyjam.md +++ b/src/blog/flappyjam.md @@ -1,6 +1,8 @@ -@name = FlappyJam -@published = 2014-02-24 -@labels = haxe,game +--- +name: FlappyJam +published: 2014-02-24 +labels: haxe,game +--- I've just submitted my entry to [itch.io](http://itch.io)'s [FLAPPYJAM](http://itch.io/jam/flappyjam)! See it/[play it here](http://kmakai.itch.io/flee-lethal-avian-pests). diff --git a/src/blog/haxe-and-google-play-services.md b/src/blog/haxe-and-google-play-services.md index e33d197..2fecbd2 100644 --- a/src/blog/haxe-and-google-play-services.md +++ b/src/blog/haxe-and-google-play-services.md @@ -1,7 +1,10 @@ -@name = Haxe and Google Play Services -@slug = play-haxe -@published = 2014-10-07 -@labels = haxe +--- +name: Haxe and Google Play Services +slug: play-haxe +published: 2014-10-07 +labels: haxe +previewLines: 1 +--- Recently I decided I wanted to integrate Google Play Services -- leaderboards, achievements, etc -- with a Haxe/OpenFL project targetting Android devices. I assumed this should be easy enough given the ability to hook into Android/Java frameworks via native extensions. Overall it was simple, but not necessarily straightforward, so I'm writing this post as a quick start guide for others. diff --git a/src/blog/haxe-signals.md b/src/blog/haxe-signals.md index f417b8b..4ba7fd1 100644 --- a/src/blog/haxe-signals.md +++ b/src/blog/haxe-signals.md @@ -1,6 +1,9 @@ -@name = Haxe Signals -@published = 2014-05-16 -@labels = haxe +--- +name: Haxe Signals +published: 2014-05-16 +labels: haxe +previewLines: 2 +--- A common pattern I find myself following in game development is the message-subscription/callback model -- notifying a group of objects that a certain event has happened, at which point they all go about their business responding in the appropriate ways. diff --git a/src/blog/trying-twine-textjam.md b/src/blog/trying-twine-textjam.md index 39d9d8e..34f6fd1 100644 --- a/src/blog/trying-twine-textjam.md +++ b/src/blog/trying-twine-textjam.md @@ -1,6 +1,8 @@ -@name = Trying Twine (TextJam) -@published = 2014-06-24 -@labels = game,twine +--- +name: Trying Twine (TextJam) +published: 2014-06-24 +labels: game,twine +--- I was determined to participate in [TextJam](http://textjam.tumblr.com) last weekend, and without much time to devote I thought it could be smart to give Twine a try. Starting with a solid framework meant that once I had learned the syntax (and installed a few essential macros,) I could devote my remaining time to content and styling. diff --git a/src/projects.md b/src/projects.md index c36e595..ee83eaf 100644 --- a/src/projects.md +++ b/src/projects.md @@ -1 +1,3 @@ -@template = projects +--- +template: projects +--- diff --git a/src/projects/cultivate.md b/src/projects/cultivate.md index ce2522d..298a682 100644 --- a/src/projects/cultivate.md +++ b/src/projects/cultivate.md @@ -1,7 +1,9 @@ -@name = Cultivate -@year = 2015 -@type = Game -@thumbnail = /static/images/cultivate-1@120.jpg -@url = http://kmakai.itch.io/cultivate +--- +name: Cultivate +year: 2015 +type: Game +thumbnail: /static/images/cultivate-1@120.jpg +url: http://kmakai.itch.io/cultivate +--- Made for Ludum Dare 34, in 48 hours. Unity. diff --git a/src/projects/isolation.md b/src/projects/isolation.md index 1461778..21c5733 100644 --- a/src/projects/isolation.md +++ b/src/projects/isolation.md @@ -1,7 +1,9 @@ -@name = Isolation -@year = 2013 -@type = Game -@thumbnail = /static/images/iso@120.png -@url = http://kmakai.itch.io/isolation +--- +name: Isolation +year: 2013 +type: Game +thumbnail: /static/images/iso@120.png +url: http://kmakai.itch.io/isolation +--- A game about personal space. diff --git a/src/projects/lark.md b/src/projects/lark.md index 04d8e17..57717c6 100644 --- a/src/projects/lark.md +++ b/src/projects/lark.md @@ -1,7 +1,9 @@ -@name = Lark -@year = 2015 -@type = Language -@thumbnail = /static/images/screen-shot-2016-01-10-at-9.50.03-pm@120.png -@url = https://github.com/ktravis/lark +--- +name: Lark +year: 2015 +type: Language +thumbnail: /static/images/screen-shot-2016-01-10-at-9.50.03-pm@120.png +url: https://github.com/ktravis/lark +--- An odd dynamic programming language, interpreted by Python diff --git a/src/projects/lvrg.md b/src/projects/lvrg.md index 916ac40..f103638 100644 --- a/src/projects/lvrg.md +++ b/src/projects/lvrg.md @@ -1,7 +1,9 @@ -@name = LVRG -@year = 2014 -@type = Game -@thumbnail = /static/images/lvrg-icon@120.png -@url = https://play.google.com/store/apps/details?id=com.kmakai.lvrg +--- +name: LVRG +year: 2014 +type: Game +thumbnail: /static/images/lvrg-icon@120.png +url: https://play.google.com/store/apps/details?id=com.kmakai.lvrg +--- A simple Android game about self-control and timing. Made with Haxe and OpenFL. diff --git a/src/projects/maera.md b/src/projects/maera.md index 3d573e7..ac5db53 100644 --- a/src/projects/maera.md +++ b/src/projects/maera.md @@ -1,8 +1,10 @@ -@name = Maera -@url = https://play.google.com/store/apps/details?id=com.kmakai.maera -@year = 2014 -@type = App -@thumbnail = /static/images/maera@120.png +--- +name: Maera +url: https://play.google.com/store/apps/details?id=com.kmakai.maera +year: 2014 +type: App +thumbnail: /static/images/maera@120.png +--- A minimal Android camera app, inspired by [Noirca](https://wiki.xxiivv.com/noirca) by [Devine Lu Linvega](https://twitter.com/aliceffekt) diff --git a/src/projects/scraps.md b/src/projects/scraps.md index 954ffcf..99e05ce 100644 --- a/src/projects/scraps.md +++ b/src/projects/scraps.md @@ -1,6 +1,8 @@ -@name = Scraps -@year = 2013 -@thumbnail = /static/images/scraps@120.png -@url = https://gist.github.com/ktravis +--- +name: Scraps +year: 2013 +thumbnail: /static/images/scraps@120.png +url: https://gist.github.com/ktravis +--- Minor works of code. diff --git a/src/projects/sundiver.md b/src/projects/sundiver.md index 3f927b4..06d6d1e 100644 --- a/src/projects/sundiver.md +++ b/src/projects/sundiver.md @@ -1,7 +1,9 @@ -@name = Sundiver -@url = http://kmakai.itch.io/sundiver -@year = 2014 -@type = Game -@thumbnail = /static/images/sunicon@120.png +--- +name: Sundiver +url: http://kmakai.itch.io/sundiver +year: 2014 +type: Game +thumbnail: /static/images/sunicon@120.png +--- A game made in ~48 hours for the 29th [Ludum Dare](https://ludumdare.org/). diff --git a/src/projects/testris.md b/src/projects/testris.md index 132b6aa..6606cda 100644 --- a/src/projects/testris.md +++ b/src/projects/testris.md @@ -1,7 +1,9 @@ -@name = Testris -@year = 2020 -@type = Game -@thumbnail = /static/images/testris-1@120.png -@url = http://github.com/ktravis/testris +--- +name: Testris +year: 2020 +type: Game +thumbnail: /static/images/testris-1@120.png +url: http://github.com/ktravis/testris +--- Practice implementation of Tetris in C++ with SDL2 diff --git a/src/projects/tinyforum.md b/src/projects/tinyforum.md index 172a18d..14e3da5 100644 --- a/src/projects/tinyforum.md +++ b/src/projects/tinyforum.md @@ -1,7 +1,9 @@ -@name = Tinyforum -@url = https://play.google.com/store/apps/details?id=com.kmakai.maera -@year = 2013 -@type = Web App -@thumbnail = /static/images/screen-shot-2016-01-09-at-4.34.59-pm@120.png +--- +name: Tinyforum +url: https://play.google.com/store/apps/details?id=com.kmakai.maera +year: 2013 +type: Web App +thumbnail: /static/images/screen-shot-2016-01-09-at-4.34.59-pm@120.png +--- Small bulletin board system implemented in `clojure`. Source code and deployment instructions on [github](https://github.com/ktravis/tinyforum). diff --git a/static/prism-base.css b/static/prism-base.css new file mode 100644 index 0000000..57e97f2 --- /dev/null +++ b/static/prism-base.css @@ -0,0 +1,215 @@ +code[class*='language-'], +pre[class*='language-'] { + color: var(--code-fg); + background: none; + font-family: Consolas, Menlo, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*='language-']::-moz-selection, pre[class*='language-'] ::-moz-selection, +code[class*='language-']::-moz-selection, code[class*='language-'] ::-moz-selection { + background: var(--code-sel-bg); +} + +pre[class*='language-']::selection, pre[class*='language-'] ::selection, +code[class*='language-']::selection, code[class*='language-'] ::selection { + background: var(--code-sel-bg); +} + +/* Code blocks */ +pre[class*='language-'] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*='language-'], +pre[class*='language-'] { + background: var(--code-bg); +} + +/* Inline code */ +:not(pre) > code[class*='language-'] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: var(--code-comment); +} + +.token.punctuation { + color: var(--code-comment); +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.constant, +.token.symbol, +.token.deleted { + color: var(--code-symbol); +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: var(--code-string); +} + +.token.id { + color: var(--code-id); +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: var(--code-operator); + background: var(--code-operator-bg); +} + +.token.number, +.token.atrule, +.token.attr-value, +.token.keyword { + color: var(--code-keyword); +} + +.token.function, +.token.class-name { + color: var(--code-symbol); +} + +.token.regex, +.token.important, +.token.variable { + color: var(--code-variable); +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; +} + +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: 0; + margin-top: 1em; /* Same as .prism’s padding-top */ + background: var(--code-line-hl); + background: linear-gradient(to right, var(--code-line-hl) 70%, var(--code-line-hl-2); + pointer-events: none; + + line-height: inherit; + white-space: pre; +} + +.line-highlight:before, +.line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: var(--code-line-hl-meta-bg); + color: var(--code-line-hl-meta); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + box-shadow: 0 1px white; +} + +.line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; +} + +.line-numbers .line-highlight:before, +.line-numbers .line-highlight:after { + content: none; +} + +pre[class*='language-'].line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre[class*='language-'].line-numbers > code { + position: relative; + white-space: inherit; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: -3px; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid var(--code-lineno-border); + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + +.line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; +} + +.line-numbers-rows > span:before { + content: counter(linenumber); + color: var(--code-lineno-before); + display: block; + padding-right: 0.8em; + text-align: right; +} diff --git a/static/prism.js b/static/prism.js new file mode 100644 index 0000000..ee5bc21 --- /dev/null +++ b/static/prism.js @@ -0,0 +1,15 @@ +/* PrismJS 1.30.0 +https://prismjs.com/download#themes=prism&languages=markup+css+clike+csharp+lua+makefile+markdown+python+rust+wgsl+yaml+zig */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var P=w.value;if(n.length>e.length)return;if(!(P instanceof i)){var E,S=1;if(y){if(!(E=l(b,A,e,m))||E.index>=e.length)break;var L=E.index,O=E.index+E[0].length,C=A;for(C+=w.value.length;L>=C;)C+=(w=w.next).value.length;if(A=C-=w.value.length,w.value instanceof i)continue;for(var j=w;j!==n.tail&&(Cg.reach&&(g.reach=W);var I=w.prev;if(_&&(I=u(n,I,_),A+=_.length),c(n,I,S),w=u(n,I,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),S>1){var T={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,T),g&&T.reach>g.reach&&(g.reach=T.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +!function(e){function n(e,n){return e.replace(/<<(\d+)>>/g,(function(e,s){return"(?:"+n[+s]+")"}))}function s(e,s,a){return RegExp(n(e,s),a||"")}function a(e,n){for(var s=0;s>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var t="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var d=l(r),p=RegExp(l(t+" "+r+" "+i+" "+o)),c=l(r+" "+i+" "+o),u=l(t+" "+r+" "+o),g=a("<(?:[^<>;=+\\-*/%&|^]|<>)*>",2),b=a("\\((?:[^()]|<>)*\\)",2),h="@?\\b[A-Za-z_]\\w*\\b",f=n("<<0>>(?:\\s*<<1>>)?",[h,g]),m=n("(?!<<0>>)<<1>>(?:\\s*\\.\\s*<<1>>)*",[c,f]),k="\\[\\s*(?:,\\s*)*\\]",y=n("<<0>>(?:\\s*(?:\\?\\s*)?<<1>>)*(?:\\s*\\?)?",[m,k]),w=n("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k]),v=n("\\(<<0>>+(?:,<<0>>+)+\\)",[w]),x=n("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[v,m,k]),$={keyword:p,punctuation:/[<>()?,.:[\]]/},_="'(?:[^\r\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",B='"(?:\\\\.|[^\\\\"\r\n])*"';e.languages.csharp=e.languages.extend("clike",{string:[{pattern:s("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:s("(^|[^@$\\\\])<<0>>",[B]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:s("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,x]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:s("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:$},{pattern:s("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:$},{pattern:s("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:s("(\\b(?:is(?:\\s+not)?|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:$},{pattern:s("\\b<<0>>(?=\\s+(?!<<1>>|with\\s*\\{)<<2>>(?:\\s*[=,;:{)\\]]|\\s+(?:in|when)\\b))",[x,u,h]),inside:$}],keyword:p,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:s("([(,]\\s*)<<0>>(?=\\s*:)",[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:s("(\\b(?:namespace|using)\\s+)<<0>>(?:\\s*\\.\\s*<<0>>)*(?=\\s*[;{])",[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:s("(\\b(?:default|sizeof|typeof)\\s*\\(\\s*(?!\\s))(?:[^()\\s]|\\s(?!\\s)|<<0>>)*(?=\\s*\\))",[b]),lookbehind:!0,alias:"class-name",inside:$},"return-type":{pattern:s("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[x,m]),inside:$,alias:"class-name"},"constructor-invocation":{pattern:s("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[x]),lookbehind:!0,inside:$,alias:"class-name"},"generic-method":{pattern:s("<<0>>\\s*<<1>>(?=\\s*\\()",[h,g]),inside:{function:s("^<<0>>",[h]),generic:{pattern:RegExp(g),alias:"class-name",inside:$}}},"type-list":{pattern:s("\\b((?:<<0>>\\s+<<1>>|record\\s+<<1>>\\s*<<5>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>|<<1>>\\s*<<5>>|<<6>>)(?:\\s*,\\s*(?:<<3>>|<<4>>|<<6>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,x,p.source,b,"\\bnew\\s*\\(\\s*\\)"]),lookbehind:!0,inside:{"record-arguments":{pattern:s("(^(?!new\\s*\\()<<0>>\\s*)<<1>>",[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:p,"class-name":{pattern:RegExp(x),greedy:!0,inside:$},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var E=B+"|"+_,R=n("/(?![*/])|//[^\r\n]*[\r\n]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>",[E]),z=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),S="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",j=n("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,z]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:s("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[S,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:s("^<<0>>(?=\\s*:)",[S]),alias:"keyword"},"attribute-arguments":{pattern:s("\\(<<0>>*\\)",[z]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var A=":[^}\r\n]+",F=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),P=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[F,A]),U=a(n("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[E]),2),Z=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[U,A]);function q(n,a){return{interpolation:{pattern:s("((?:^|[^{])(?:\\{\\{)*)<<0>>",[n]),lookbehind:!0,inside:{"format-string":{pattern:s("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[a,A]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:s('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[P]),lookbehind:!0,greedy:!0,inside:q(P,F)},{pattern:s('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[Z]),lookbehind:!0,greedy:!0,inside:q(Z,U)}],char:{pattern:RegExp(_),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(Prism); +Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; +Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}; +!function(n){function e(n){return n=n.replace(//g,(function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"})),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var t="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",a="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,(function(){return t})),i="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+i+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+i+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(t),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(t),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:e("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:e("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:e("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:e('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(e){["url","bold","italic","strike","code-snippet"].forEach((function(t){e!==t&&(n.languages.markdown[e].inside.content.inside[t]=n.languages.markdown[t])}))})),n.hooks.add("after-tokenize",(function(n){"markdown"!==n.language&&"md"!==n.language||function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},l=String.fromCodePoint||String.fromCharCode;n.languages.md=n.languages.markdown}(Prism); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +!function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,(function(){return a}));a=a.replace(//g,(function(){return"[^\\s\\S]"})),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +Prism.languages.wgsl={comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"builtin-attribute":{pattern:/(@)builtin\(.*?\)/,lookbehind:!0,inside:{attribute:{pattern:/^builtin/,alias:"attr-name"},punctuation:/[(),]/,"built-in-values":{pattern:/\b(?:frag_depth|front_facing|global_invocation_id|instance_index|local_invocation_id|local_invocation_index|num_workgroups|position|sample_index|sample_mask|vertex_index|workgroup_id)\b/,alias:"attr-value"}}},attributes:{pattern:/(@)(?:align|binding|compute|const|fragment|group|id|interpolate|invariant|location|size|vertex|workgroup_size)/i,lookbehind:!0,alias:"attr-name"},functions:{pattern:/\b(fn\s+)[_a-zA-Z]\w*(?=[(<])/,lookbehind:!0,alias:"function"},keyword:/\b(?:bitcast|break|case|const|continue|continuing|default|discard|else|enable|fallthrough|fn|for|function|if|let|loop|private|return|storage|struct|switch|type|uniform|var|while|workgroup)\b/,builtin:/\b(?:abs|acos|acosh|all|any|array|asin|asinh|atan|atan2|atanh|atomic|atomicAdd|atomicAnd|atomicCompareExchangeWeak|atomicExchange|atomicLoad|atomicMax|atomicMin|atomicOr|atomicStore|atomicSub|atomicXor|bool|ceil|clamp|cos|cosh|countLeadingZeros|countOneBits|countTrailingZeros|cross|degrees|determinant|distance|dot|dpdx|dpdxCoarse|dpdxFine|dpdy|dpdyCoarse|dpdyFine|exp|exp2|extractBits|f32|f64|faceForward|firstLeadingBit|floor|fma|fract|frexp|fwidth|fwidthCoarse|fwidthFine|i32|i64|insertBits|inverseSqrt|ldexp|length|log|log2|mat[2-4]x[2-4]|max|min|mix|modf|normalize|override|pack2x16float|pack2x16snorm|pack2x16unorm|pack4x8snorm|pack4x8unorm|pow|ptr|quantizeToF16|radians|reflect|refract|reverseBits|round|sampler|sampler_comparison|select|shiftLeft|shiftRight|sign|sin|sinh|smoothstep|sqrt|staticAssert|step|storageBarrier|tan|tanh|textureDimensions|textureGather|textureGatherCompare|textureLoad|textureNumLayers|textureNumLevels|textureNumSamples|textureSample|textureSampleBias|textureSampleCompare|textureSampleCompareLevel|textureSampleGrad|textureSampleLevel|textureStore|texture_1d|texture_2d|texture_2d_array|texture_3d|texture_cube|texture_cube_array|texture_depth_2d|texture_depth_2d_array|texture_depth_cube|texture_depth_cube_array|texture_depth_multisampled_2d|texture_multisampled_2d|texture_storage_1d|texture_storage_2d|texture_storage_2d_array|texture_storage_3d|transpose|trunc|u32|u64|unpack2x16float|unpack2x16snorm|unpack2x16unorm|unpack4x8snorm|unpack4x8unorm|vec[2-4]|workgroupBarrier)\b/,"function-calls":{pattern:/\b[_a-z]\w*(?=\()/i,alias:"function"},"class-name":/\b(?:[A-Z][A-Za-z0-9]*)\b/,"bool-literal":{pattern:/\b(?:false|true)\b/,alias:"boolean"},"hex-int-literal":{pattern:/\b0[xX][0-9a-fA-F]+[iu]?\b(?![.pP])/,alias:"number"},"hex-float-literal":{pattern:/\b0[xX][0-9a-fA-F]*(?:\.[0-9a-fA-F]*)?(?:[pP][+-]?\d+[fh]?)?/,alias:"number"},"decimal-float-literal":[{pattern:/\d*\.\d+(?:[eE](?:\+|-)?\d+)?[fh]?/,alias:"number"},{pattern:/\d+\.\d*(?:[eE](?:\+|-)?\d+)?[fh]?/,alias:"number"},{pattern:/\d+[eE](?:\+|-)?\d+[fh]?/,alias:"number"},{pattern:/\b\d+[fh]\b/,alias:"number"}],"int-literal":{pattern:/\b\d+[iu]?\b/,alias:"number"},operator:[{pattern:/(?:\^|~|\|(?!\|)|\|\||&&|<<|>>|!)(?!=)/},{pattern:/&(?![&=])/},{pattern:/(?:\+=|-=|\*=|\/=|%=|\^=|&=|\|=|<<=|>>=)/},{pattern:/(^|[^<>=!])=(?![=>])/,lookbehind:!0},{pattern:/(?:==|!=|<=|\+\+|--|(^|[^=])>=)/,lookbehind:!0},{pattern:/(?:(?:[+%]|(?:\*(?!\w)))(?!=))|(?:-(?!>))|(?:\/(?!\/))/},{pattern:/->/}],punctuation:/[@(){}[\],;<>:.]/}; +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +!function(e){function n(e){return function(){return e}}var r=/\b(?:align|allowzero|and|anyframe|anytype|asm|async|await|break|cancel|catch|comptime|const|continue|defer|else|enum|errdefer|error|export|extern|fn|for|if|inline|linksection|nakedcc|noalias|nosuspend|null|or|orelse|packed|promise|pub|resume|return|stdcallcc|struct|suspend|switch|test|threadlocal|try|undefined|union|unreachable|usingnamespace|var|volatile|while)\b/,a="\\b(?!"+r.source+")(?!\\d)\\w+\\b",o="align\\s*\\((?:[^()]|\\([^()]*\\))*\\)",s="(?!\\s)(?:!?\\s*(?:"+"(?:\\?|\\bpromise->|(?:\\[[^[\\]]*\\]|\\*(?!\\*)|\\*\\*)(?:\\s*|\\s*const\\b|\\s*volatile\\b|\\s*allowzero\\b)*)".replace(//g,n(o))+"\\s*)*"+"(?:\\bpromise\\b|(?:\\berror\\.)?(?:\\.)*(?!\\s+))".replace(//g,n(a))+")+";e.languages.zig={comment:[{pattern:/\/\/[/!].*/,alias:"doc-comment"},/\/{2}.*/],string:[{pattern:/(^|[^\\@])c?"(?:[^"\\\r\n]|\\.)*"/,lookbehind:!0,greedy:!0},{pattern:/([\r\n])([ \t]+c?\\{2}).*(?:(?:\r\n?|\n)\2.*)*/,lookbehind:!0,greedy:!0}],char:{pattern:/(^|[^\\])'(?:[^'\\\r\n]|[\uD800-\uDFFF]{2}|\\(?:.|x[a-fA-F\d]{2}|u\{[a-fA-F\d]{1,6}\}))'/,lookbehind:!0,greedy:!0},builtin:/\B@(?!\d)\w+(?=\s*\()/,label:{pattern:/(\b(?:break|continue)\s*:\s*)\w+\b|\b(?!\d)\w+\b(?=\s*:\s*(?:\{|while\b))/,lookbehind:!0},"class-name":[/\b(?!\d)\w+(?=\s*=\s*(?:(?:extern|packed)\s+)?(?:enum|struct|union)\s*[({])/,{pattern:RegExp("(:\\s*)(?=\\s*(?:\\s*)?[=;,)])|(?=\\s*(?:\\s*)?\\{)".replace(//g,n(s)).replace(//g,n(o))),lookbehind:!0,inside:null},{pattern:RegExp("(\\)\\s*)(?=\\s*(?:\\s*)?;)".replace(//g,n(s)).replace(//g,n(o))),lookbehind:!0,inside:null}],"builtin-type":{pattern:/\b(?:anyerror|bool|c_u?(?:int|long|longlong|short)|c_longdouble|c_void|comptime_(?:float|int)|f(?:16|32|64|128)|[iu](?:8|16|32|64|128|size)|noreturn|type|void)\b/,alias:"keyword"},keyword:r,function:/\b(?!\d)\w+(?=\s*\()/,number:/\b(?:0b[01]+|0o[0-7]+|0x[a-fA-F\d]+(?:\.[a-fA-F\d]*)?(?:[pP][+-]?[a-fA-F\d]+)?|\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)\b/,boolean:/\b(?:false|true)\b/,operator:/\.[*?]|\.{2,3}|[-=]>|\*\*|\+\+|\|\||(?:<<|>>|[-+*]%|[-+*/%^&|<>!=])=?|[?~]/,punctuation:/[.:,;(){}[\]]/},e.languages.zig["class-name"].forEach((function(n){null===n.inside&&(n.inside=e.languages.zig)}))}(Prism); diff --git a/static/style.css b/static/style.css index 2155ea1..7c9ecf7 100755 --- a/static/style.css +++ b/static/style.css @@ -1,14 +1,238 @@ +@import "/static/prism-base.css"; + +/* === BEGIN color definitions === */ +/* system prefers light, or default */ +@media (prefers-color-scheme: light) { + body { + --text-color: #222; + --bkg-color: #fff; + --code-color: #c7254e; + --code-bkg-color: #f9f2f4; + --navlist-color: var(--code-color); + --navlist-bkg-color: var(--code-bkg-color); + --navlist-hover-color: #fff; + --navlist-bkg-hover-color: var(--anchor-hover-color); + --anchor-color: #222; + --anchor-hover-color: var(--code-color); + --footer-color: #444; + --footer-divider-color: #eee; + --caption-color: #888; + + /* light-mode */ + /* ========== */ + /* colorscheme: B4T_Classic_Q by Bram de Haan */ + /* author: Bram de Haan - https://github.com/atelierbram/Base4Tone-prism */ + /* https://github.com/atelierbram/Base4Tone-prism/blob/master/output/prism-b4t_classic-q-light.css */ + --code-fg: #08070d; + --code-bg: #f6f6f9; + --code-sel-bg: #d1cbfb; + --code-comment: #95949e; + --code-symbol: #8a2ac6; + --code-string: #175dcf; + --code-id: #564e53; + --code-operator: #8f1e66; + --code-operator-bg: #f6f6f980; + --code-variable: #bd2887; + --code-lineno-border: #b3b2bd; + --code-keyword: #5a49df; + --code-line-hl: #8a899454; + --code-line-hl-2: #8a899400; + --code-linno-before: #95949e; + --code-line-hl-meta-bg: #8a899454; + --code-line-hl-meta: #c8c7d1; + } + + /* overridden to be dark */ + body.dark-theme { + --text-color: #dedede; + --bkg-color: #0d1115; + --code-color: #b0bbda; + --code-bkg-color: #222436; + --anchor-color: #dedede; + --anchor-hover-color: #c7254e; + --footer-color: #bbb; + --footer-divider-color: #333; + --caption-color: #aaa; + + /* dark-mode */ + /* ========= */ + /* colorscheme (with modified comment color): B4T_Classic_Q by Bram de Haan */ + /* author: Bram de Haan - https://github.com/atelierbram/Base4Tone-prism */ + /* https://github.com/atelierbram/Base4Tone-prism/blob/master/output/prism-b4t_classic-q-dark.css */ + --code-fg: #f6f6f9; + --code-bg: #1d1d20; + --code-sel-bg: #4b38dc; + --code-comment: #8885a0; + --code-symbol: #74a8fb; + --code-string: #d1cbfb; + --code-id: #948990; + --code-variable: #dd40a4; + --code-operator: var(--code-variable); + --code-operator-bg: #1d1d2080; + --code-lineno-border: var(--code-operator-bg); + --code-keyword: #e0baf7; + --code-line-hl: #3b3a4054; + --code-line-hl-2: #3b3a4000; + --code-linno-before: #313036; + --code-line-hl-meta-bg: #8a899454; + --code-line-hl-meta: #c8c7d1; + } +} + +/* system prefers dark */ +@media (prefers-color-scheme: dark) { + body { + --text-color: #dedede; + --bkg-color: #0d1115; + --code-color: #b0bbda; + --code-bkg-color: #222436; + --navlist-color: var(--code-color); + --navlist-bkg-color: var(--code-bkg-color); + --navlist-hover-color: #fff; + --navlist-bkg-hover-color: var(--anchor-hover-color); + --anchor-color: #dedede; + --anchor-hover-color: #c7254e; + --footer-color: #bbb; + --footer-divider-color: #333; + --caption-color: #aaa; + + /* dark-mode */ + /* ========= */ + /* colorscheme (with modified comment color): B4T_Classic_Q by Bram de Haan */ + /* author: Bram de Haan - https://github.com/atelierbram/Base4Tone-prism */ + /* https://github.com/atelierbram/Base4Tone-prism/blob/master/output/prism-b4t_classic-q-dark.css */ + --code-fg: #f6f6f9; + --code-bg: #1d1d20; + --code-sel-bg: #4b38dc; + --code-comment: #8885a0; + --code-symbol: #74a8fb; + --code-string: #d1cbfb; + --code-id: #948990; + --code-variable: #dd40a4; + --code-operator: var(--code-variable); + --code-operator-bg: #1d1d2080; + --code-lineno-border: var(--code-operator-bg); + --code-keyword: #e0baf7; + --code-line-hl: #3b3a4054; + --code-line-hl-2: #3b3a4000; + --code-linno-before: #313036; + --code-line-hl-meta-bg: #8a899454; + --code-line-hl-meta: #c8c7d1; + } + + /* overridden to be light */ + body.light-theme { + --text-color: #222; + --bkg-color: #fff; + --code-color: #c7254e; + --code-bkg-color: #f9f2f4; + --anchor-color: #222; + --anchor-hover-color: var(--code-color); + --footer-color: #444; + --footer-divider-color: #eee; + --caption-color: #888; + + /* light-mode */ + /* ========== */ + /* colorscheme: B4T_Classic_Q by Bram de Haan */ + /* author: Bram de Haan - https://github.com/atelierbram/Base4Tone-prism */ + /* https://github.com/atelierbram/Base4Tone-prism/blob/master/output/prism-b4t_classic-q-light.css */ + --code-fg: #08070d; + --code-bg: #f6f6f9; + --code-sel-bg: #d1cbfb; + --code-comment: #95949e; + --code-symbol: #8a2ac6; + --code-string: #175dcf; + --code-id: #564e53; + --code-operator: #8f1e66; + --code-operator-bg: #f6f6f980; + --code-variable: #bd2887; + --code-lineno-border: #b3b2bd; + --code-keyword: #5a49df; + --code-line-hl: #8a899454; + --code-line-hl-2: #8a899400; + --code-linno-before: #95949e; + --code-line-hl-meta-bg: #8a899454; + --code-line-hl-meta: #c8c7d1; + } +} +/* === END color definitions === */ + +/* === BEGIN theme toggle styling === */ +#theme-toggle { + float: none; + position: fixed; + padding: 5px; + bottom: 5px; + right: 5px; + color: var(--anchor-color); + font-size: 1.2em; +} +#theme-toggle i:hover { + cursor: pointer; + color: var(--anchor-hover-color); +} +/* hide all theme buttons */ +#theme-toggle i::before { + display: none; +} +/* show all theme buttons on hover */ +#theme-toggle:hover i::before { + display: inline-block; +} + +/* set theme button icons */ +#theme-toggle i[data-theme="light-theme"]::before { + content: '\f695'; /* white-balance-sunny */ +} +#theme-toggle i[data-theme="dark-theme"]::before { + content: '\f681'; /* weather-night */ +} +#theme-toggle i[data-theme="auto"]::before { + content: '\f15f'; +} + +/* system prefers light, or default */ +@media (prefers-color-scheme: light) { + /* default (not overridden), show toggle to dark */ + body:not(.dark-theme) #theme-toggle i[data-theme="dark-theme"]::before { + display: inline-block; + } + /* overridden, show toggle back to light */ + body.dark-theme #theme-toggle i[data-theme="light-theme"]::before { + display: inline-block; + } +} + +/* system explicitly prefers dark */ +@media (prefers-color-scheme: dark) { + /* default (not overridden), show toggle to light */ + body:not(.light-theme) #theme-toggle i[data-theme="light-theme"]::before { + display: inline-block !important; + } + /* overridden, show toggle back to dark */ + body.light-theme #theme-toggle i[data-theme="dark-theme"]::before { + display: inline-block !important; + } +} +/* === END theme toggle styling === */ + body { /*font-family: 'Verdana', sans-serif;*/ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; margin: 25px 25px; - background-color: #fff; + background-color: var(--bkg-color); + color: +} + +header { + color: var(--anchor-color); } code { padding: 2px 4px; - color: #c7254e; - background-color: #f9f2f4; + color: var(--code-color); + background-color: var(--code-bkg-color); white-space: nowrap; border-radius: 4px; } @@ -18,17 +242,20 @@ code, kbd, pre, samp { font-size: 90%; } +pre code { + font-size: 16px; +} + pre { - /*border-left: solid #f54b31 3px;*/ margin-left: 10px; } a { - color: #000; + color: var(--anchor-color); } a:hover { - color: #f54b31; + color: var(--anchor-hover-color); } header, footer, div.page { @@ -38,10 +265,9 @@ header, footer, div.page { } footer { - /*background: #242424;*/ - color: #444; + color: var(--footer-color); font-size: 0.85em; - border-top: dashed #eee 2px; + border-top: dashed var(--footer-divider-color) 2px; } header { @@ -74,7 +300,7 @@ header a { } div.page { - color: #000; + color: var(--text-color); } .nav-list { @@ -87,20 +313,24 @@ div.page { } .nav-list a i.mdi { margin-bottom: -12px; + min-width: 1em; + display: inline-block; } .nav-list a { font-size: 2.5em; padding: 12px; - color: #c7254e; + color: var(--navlist-color); margin: 2px; - background-color: #f9f2f4; + background-color: var(--navlist-bkg-color); white-space: nowrap; border-radius: 4px; text-decoration: none; + line-height: 1em; + display: inline-block; } .nav-list a:hover { - background-color: #c7254e; - color: #fff; + background-color: var(--navlist-bkg-hover-color); + color: var(--navlist-hover-color); } .nav-list .nav-list-row { display: flex; @@ -123,7 +353,7 @@ div.page { align-items: center; } .captioned-center-image .caption { - color: #888; + color: var(--caption-color); } .image-right { @@ -138,17 +368,21 @@ div.page { .blog-post { margin-bottom: 12px; } -.blog-post p img { +.blog-post img { display: block; max-width: 100%; max-height: 360px; margin: auto; + border: 2px solid var(--anchor-color); +} +.blog-post img:hover { + border-color: var(--anchor-hover-color); } -.blog-post p img+em { - display: block; - text-align: center; - font-size: 0.85em; - margin-top: 0.85em; +.blog-post img+em { + display: block; + text-align: center; + font-size: 0.85em; + margin-top: 0.85em; } .blog-post-header { margin-right: 7px; @@ -158,7 +392,7 @@ div.page { justify-content: space-between; } .blog-post-header .meta { - color: #bbb; + color: var(--caption-color); margin-bottom: 0; } .blog-post-header h2 a { @@ -178,8 +412,8 @@ div.page { .projects .project:last-of-type { margin-bottom: 0; } -.project .read-more { - font-size: 0.85em; +.blog-post .read-more { + font-weight: bold; } .project .thumbnail { margin-right: 12px; @@ -187,11 +421,11 @@ div.page { line-height: 0; } .project .thumbnail:hover { - border: solid #f54b31 2px; + border: solid var(--anchor-hover-color) 2px; } .project-inner { flex-grow: 2; - color: #333; + color: var(--anchor-color); } .project-title { margin-right: 7px; @@ -204,9 +438,29 @@ div.page { text-decoration: none; } .project-type { - color: #bbb; + color: var(--caption-color); } .project-year { font-size: 0.65em; font-weight: normal; } +a.anchor { + color: var(--caption-color); + text-decoration: none; + display: none; +} +a.anchor:hover { + color: var(--anchor-hover-color); +} +:is(h1, h2, h3, h4, h5, h6):hover a.anchor { + display: inline; +} +figure figcaption { + color: var(--caption-color); + text-align: center; + font-size: 0.95em; + line-height: 1em; +} +figcaption p { + margin-top: 0.7em; +} diff --git a/templates/blog.html b/templates/blog.html index 6e59f3e..ef57956 100644 --- a/templates/blog.html +++ b/templates/blog.html @@ -45,7 +45,7 @@

{{ .Metadata.name }}

{{ template "article-header" . }} - {{ readmore .Content .Path }} + {{ readmore .Content .Path .Metadata.previewLines }}
{{ end }} {{ end }} diff --git a/templates/include/base.html b/templates/include/base.html index 6bcbf99..201abeb 100644 --- a/templates/include/base.html +++ b/templates/include/base.html @@ -3,8 +3,9 @@ - + + {{ block "title" . }}kylemtravis.com{{ end }} @@ -13,13 +14,9 @@

~{{ block "breadcrumbs" . }}/kyle-m-travis{{ end }}

@@ -31,7 +28,26 @@

~{{ block "breadcrumbs" . }}/kyle-m-travis{{ end }}

© Copyright 2014-2025 by Kyle Travis.
+
+ + + {{ reloader }} {{ end }} From 1424c837d23dbb7fa7e1fe8c3b31016daf92df88 Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:34:37 -0400 Subject: [PATCH 2/9] netlify config file --- .gitignore | 3 +++ Makefile | 6 +++--- netlify.toml | 7 +++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 netlify.toml diff --git a/.gitignore b/.gitignore index d9df715..d0c7d82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ build/* bin/ + +# Local Netlify folder +.netlify diff --git a/Makefile b/Makefile index 8525fe5..f8b5eb2 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,13 @@ SSGEN := $(shell go env GOPATH)/bin/ssgen PORT := 8081 -$(SSGEN): - go install github.com/ktravis/ssgen@latest - build: $(SSGEN) $(SSGEN) -in src -out build cp -R static/ build/ +$(SSGEN): + go install github.com/ktravis/ssgen@latest + serve: $(SSGEN) $(SSGEN) -serve localhost:$(PORT) diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..b4fc868 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,7 @@ +[build] +command = "make build" +publish = "build" + +[build.environment] + GO_VERSION = "1.25" + GO111MODULE = "on" From 8b77013bf48ad2935daf10ec6e0f577d2a66b8c8 Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:36:11 -0400 Subject: [PATCH 3/9] debug --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index f8b5eb2..ba7db15 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,10 @@ build: $(SSGEN) $(SSGEN): go install github.com/ktravis/ssgen@latest + go env + echo $$GOBIN + echo $$GOPATH + ls -la $$HOME/go/bin serve: $(SSGEN) $(SSGEN) -serve localhost:$(PORT) From 76f55193469e96a8c8a16f41c48802cf606f5cfe Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:38:22 -0400 Subject: [PATCH 4/9] more debug --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ba7db15..8a95dc2 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ build: $(SSGEN) $(SSGEN): go install github.com/ktravis/ssgen@latest go env - echo $$GOBIN - echo $$GOPATH - ls -la $$HOME/go/bin + echo ${GOBIN} + echo ${GOPATH} + ls -la ~/go/bin serve: $(SSGEN) $(SSGEN) -serve localhost:$(PORT) From 982b8f4cc78ce9c509831938aa6f4621e2eead4e Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:42:34 -0400 Subject: [PATCH 5/9] this one for sure --- Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 8a95dc2..b290dc5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ .PHONY: clean build deploy -SSGEN := $(shell go env GOPATH)/bin/ssgen +GOPATH ?= $(shell go env GOPATH) +GOBIN ?= $(GOPATH)/bin +SSGEN := $(GOBIN)/ssgen PORT := 8081 build: $(SSGEN) @@ -9,10 +11,6 @@ build: $(SSGEN) $(SSGEN): go install github.com/ktravis/ssgen@latest - go env - echo ${GOBIN} - echo ${GOPATH} - ls -la ~/go/bin serve: $(SSGEN) $(SSGEN) -serve localhost:$(PORT) From 015a6eeaf115e22a949c0f9a7beaa9df1665be3d Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:47:25 -0400 Subject: [PATCH 6/9] nope --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index b290dc5..050f3a7 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ build: $(SSGEN) cp -R static/ build/ $(SSGEN): + go env GOPATH + echo $(GOPATH) + go env GOBIN + echo $(GOBIN) go install github.com/ktravis/ssgen@latest serve: $(SSGEN) From aba19be897fc6506d45e9a566654861a56821765 Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:48:39 -0400 Subject: [PATCH 7/9] just checking --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 050f3a7..c0b7859 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: clean build deploy -GOPATH ?= $(shell go env GOPATH) +# GOPATH ?= $(shell go env GOPATH) GOBIN ?= $(GOPATH)/bin SSGEN := $(GOBIN)/ssgen PORT := 8081 From f8c8f9d1f8ef9d7b7d4ef8988cfada323dd3f7a3 Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:50:40 -0400 Subject: [PATCH 8/9] more --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c0b7859..4e92a04 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .PHONY: clean build deploy # GOPATH ?= $(shell go env GOPATH) -GOBIN ?= $(GOPATH)/bin -SSGEN := $(GOBIN)/ssgen +# GOBIN ?= $(GOPATH)/bin +SSGEN := $(shell go env GOBIN)/ssgen PORT := 8081 build: $(SSGEN) From cc6e0be799881a154eb7b0a84e33aab62eec8f6f Mon Sep 17 00:00:00 2001 From: Kyle Travis Date: Sat, 20 Sep 2025 20:57:11 -0400 Subject: [PATCH 9/9] this time --- Makefile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 4e92a04..94bd999 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ .PHONY: clean build deploy -# GOPATH ?= $(shell go env GOPATH) -# GOBIN ?= $(GOPATH)/bin -SSGEN := $(shell go env GOBIN)/ssgen +# annoying workaround to handle netlify +GOPATH := $(or $(GOPATH),$(shell go env GOPATH)) +GOBIN := $(or $(shell go env GOBIN),$(GOPATH)/bin) +SSGEN := $(GOBIN)/ssgen PORT := 8081 build: $(SSGEN) @@ -10,10 +11,6 @@ build: $(SSGEN) cp -R static/ build/ $(SSGEN): - go env GOPATH - echo $(GOPATH) - go env GOBIN - echo $(GOBIN) go install github.com/ktravis/ssgen@latest serve: $(SSGEN)