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/.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 78396ee..94bd999 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,20 @@ .PHONY: clean build deploy -clean: - rm -rf build/* bin/* +# 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: - command -v ssgen || go install github.com/ktravis/ssgen@latest - PATH=$$(go env GOPATH)/bin:$$PATH ssgen -in src -out build +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) + +clean: + rm -rf build/* bin/* 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" 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 }}