Compare commits
15
Commits
c7b9f9e67d
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebee3479b1
|
||
|
|
ca4231f8b0
|
||
|
|
a28cc7cd39
|
||
|
|
9d6cc301e8
|
||
|
|
2b68602f86
|
||
|
|
32f457b4cd
|
||
|
|
693bc08e61
|
||
|
|
be9686d40e
|
||
|
|
5435e0c8c0
|
||
|
|
e3df8db9bb
|
||
|
|
719012bb08
|
||
|
|
74e9f9feaf
|
||
|
|
346f3de193
|
||
|
|
54dd6d2a17
|
||
|
|
90e8a3b2a5
|
@@ -1,6 +1,8 @@
|
||||
# Source
|
||||
# sd.ai Ghost Theme
|
||||
|
||||
The default theme for [Ghost](http://github.com/tryghost/ghost/). This is the latest development version of Source! If you're just looking to download the latest release, head over to the [releases](https://github.com/TryGhost/Source/releases) page.
|
||||
Forked from [Source](https://github.com/TryGhost/Source) - the default theme for [Ghost](http://github.com/tryghost/ghost/).
|
||||
|
||||
Styles the site as it looked previously and adds Mastodon support and a theme switcher.
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,89 @@
|
||||
.tootlink-tip {
|
||||
font-size: 0.9em;
|
||||
padding: 1em;
|
||||
padding-top: 0.3em;
|
||||
}
|
||||
.mastodon-comments-top {
|
||||
padding-bottom: 1.5em;
|
||||
}
|
||||
.mastodon-comment {
|
||||
background-color: var(--background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
padding: 10px;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
border-top: 1px solid var(--background-secondary);
|
||||
.mastodon-body {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.mastodon-avatar {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.mastodon-avatar img {
|
||||
margin-right: 1rem;
|
||||
min-width: 60px;
|
||||
}
|
||||
.mastodon-meta {
|
||||
padding-top: 0;
|
||||
display: flex;
|
||||
.mastodon-author {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
.mastodon-author-uid {
|
||||
font-size: 80%;
|
||||
color: var(--color-secondary-text);
|
||||
}
|
||||
}
|
||||
.toot-link {
|
||||
flex-shrink: 1;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.mastodon-comment-content {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.disabled {
|
||||
color: var(--color-secondary-text)
|
||||
}
|
||||
}
|
||||
span.tootlink {
|
||||
font-size: 0.7em;
|
||||
font-family: monospace;
|
||||
padding: 0.2em 0.4em;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--background-secondary)
|
||||
}
|
||||
a.date {
|
||||
font-size: 0.9em;
|
||||
color: var(--color-secondary-text)
|
||||
}
|
||||
span.tootlink::after {
|
||||
content: "\f0c5";
|
||||
font-family: "Font Awesome 6 Free";
|
||||
font-weight: 900;
|
||||
padding-left: 4px;
|
||||
}
|
||||
.tootClick {
|
||||
animation: tootClickFrames .6s linear;
|
||||
}
|
||||
|
||||
@keyframes tootClickFrames {
|
||||
0% {
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
100% {
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
}
|
||||
.mastodon-emoji {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
.mastodon-comment-content p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
#toot-link-top {
|
||||
color: var(--ghost-accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* PrismJS 1.29.0
|
||||
https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+bash+go+go-module+handlebars+json+markup-templating+ruby+typescript+yaml&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard */
|
||||
code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;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}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;margin-top:.75em;z-index:0}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background-color:#8693a6;color:#f4f1ef}
|
||||
pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.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:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
|
||||
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:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
|
||||
div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}
|
||||
+20
-59
@@ -47,6 +47,9 @@ production stylesheet in assets/built/screen.css
|
||||
|
||||
*/
|
||||
|
||||
@import "mastodon.css";
|
||||
@import "prism.css";
|
||||
|
||||
/* 1. Variables
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
@@ -62,10 +65,10 @@ production stylesheet in assets/built/screen.css
|
||||
--color-secondary-text: rgb(0 0 0 / 0.5);
|
||||
--color-border: rgb(0 0 0 / 0.08);
|
||||
--color-dark-border: rgb(0 0 0 / 0.5);
|
||||
--font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
--font-serif: "EB Garamond", Georgia, Times, serif;
|
||||
--font-serif-alt: Georgia, Times, serif;
|
||||
--font-mono: "JetBrains Mono", Menlo, Consolas, Monaco, "Liberation Mono", "Lucida Console", monospace;
|
||||
--font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif, "Font Awesome 6 Free", "Font Awesome 6 Brands";
|
||||
--font-serif: "EB Garamond", Georgia, Times, serif, "Font Awesome 6 Free", "Font Awesome 6 Brands";
|
||||
--font-serif-alt: Georgia, Times, serif, "Font Awesome 6 Free", "Font Awesome 6 Brands";
|
||||
--font-mono: "JetBrains Mono", Menlo, Consolas, Monaco, "Liberation Mono", "Lucida Console", monospace, "Font Awesome 6 Free", "Font Awesome 6 Brands";
|
||||
--container-width: 1320px;
|
||||
--container-gap: clamp(24px, 1.7032rem + 1.9355vw, 48px);
|
||||
--grid-gap: 42px;
|
||||
@@ -971,12 +974,10 @@ Search LOGO Login Subscribe
|
||||
}
|
||||
|
||||
.gh-card-tag {
|
||||
display: none;
|
||||
margin-bottom: 4px;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.01em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.gh-card-title {
|
||||
@@ -1017,6 +1018,10 @@ Search LOGO Login Subscribe
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.gh-card-wrapper > .gh-card-meta:not(:empty) ~ .gh-card-meta:not(:empty) {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.gh-card-author + .gh-card-date::before {
|
||||
content: "—";
|
||||
margin-right: 4px;
|
||||
@@ -1955,59 +1960,6 @@ Search LOGO Login Subscribe
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.mastodon-comment {
|
||||
background-color: var(--background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
padding: 10px;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
border-top: 1px solid var(--background-secondary);
|
||||
.mastodon-body {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.mastodon-avatar {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.mastodon-avatar img {
|
||||
margin-right: 1rem;
|
||||
min-width: 60px;
|
||||
}
|
||||
.mastodon-meta {
|
||||
padding-top: 0;
|
||||
display: flex;
|
||||
.mastodon-author {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
.mastodon-author-uid {
|
||||
font-size: 80%;
|
||||
color: var(--ghost-accent-color);
|
||||
}
|
||||
}
|
||||
.toot-link {
|
||||
flex-shrink: 1;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.mastodon-comment-content {
|
||||
padding-top: 10px;
|
||||
.tootlink {
|
||||
font-size: 50%;
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
color: var(--ghost-accent-color)
|
||||
}
|
||||
}
|
||||
.mastodon-emoji {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
.mastodon-comment-content p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 14. Post/page
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
@@ -2022,15 +1974,24 @@ Search LOGO Login Subscribe
|
||||
.gh-article-header {
|
||||
margin: clamp(40px, 3.64vw + 25.45px, 72px) 0 40px;
|
||||
}
|
||||
.gh-article-tags {
|
||||
|
||||
}
|
||||
.gh-article-tag {
|
||||
margin-bottom: 12px;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.01em;
|
||||
text-transform: uppercase;
|
||||
padding-right: 1em;
|
||||
color: var(--ghost-accent-color);
|
||||
}
|
||||
.gh-article-tag::before {
|
||||
content: " ";
|
||||
font-weight: 900;
|
||||
font-size: 0.8em;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
.gh-article-title {
|
||||
font-size: calc(clamp(3.4rem, 1.36vw + 2.85rem, 4.6rem) * var(--factor, 1));
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
File diff suppressed because one or more lines are too long
+69
-10
@@ -1,10 +1,11 @@
|
||||
const MASTODON_ACCOUNT_ID = '109285376472065471'
|
||||
const MASTODON_HOST = 'social.sd.ai'
|
||||
|
||||
// Copies the text from an element to the clipboard, and flashes the element to provide visual feedback
|
||||
async function copyElementTextToClipboard(e)
|
||||
{
|
||||
const text = e.textContent
|
||||
await navigator.clipboard.write(text)
|
||||
await navigator.clipboard.writeText(text)
|
||||
|
||||
e.classList.add('tootClick');
|
||||
setTimeout(() => {
|
||||
@@ -12,6 +13,7 @@ async function copyElementTextToClipboard(e)
|
||||
}, 600);
|
||||
}
|
||||
|
||||
// sanitise text content for display
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
@@ -21,14 +23,25 @@ function escapeHtml(unsafe) {
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function renderMastodonContent(toots, parentElement) {
|
||||
// renders the content - provides an array of toots, the element to add the content to and whether to show a copyable link for replies
|
||||
function renderMastodonContent(toots, parentElement, showLink) {
|
||||
// clear the parent element so that we can add the new content
|
||||
parentElement.innerHTML = ''
|
||||
// add a simple "no comments" message if there are no toots
|
||||
if (!Array.isArray(toots) || toots.length === 0) {
|
||||
document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>"
|
||||
return
|
||||
}
|
||||
|
||||
// render each toot
|
||||
for (const toot of toots) {
|
||||
if (toot.sensitive) {
|
||||
// don't display toots marked as sensitive
|
||||
continue
|
||||
}
|
||||
|
||||
// sanitise the toot content for display, including correctly rendering custom emojis
|
||||
toot.account.display_name = escapeHtml(toot.account.display_name)
|
||||
console.log(toot)
|
||||
toot.account.emojis.forEach(emoji => {
|
||||
toot.account.display_name = toot.account.display_name.replace(`:${emoji.shortcode}:`,
|
||||
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
|
||||
@@ -37,6 +50,8 @@ function renderMastodonContent(toots, parentElement) {
|
||||
toot.content = toot.content.replace(`:${emoji.shortcode}:`,
|
||||
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
|
||||
})
|
||||
|
||||
// create a block of HTML content including the toot data
|
||||
const comment =
|
||||
`<div class="mastodon-comment">
|
||||
<div class="mastodon-avatar">
|
||||
@@ -46,7 +61,7 @@ function renderMastodonContent(toots, parentElement) {
|
||||
<div class="mastodon-meta">
|
||||
<div class="mastodon-author">
|
||||
<div class="mastodon-author-link">
|
||||
<a href="${toot.account.url}" rel="nofollow">
|
||||
<a href="${toot.account.url}" target="_blank" rel="nofollow">
|
||||
<span>${toot.account.display_name}</span>
|
||||
</a>
|
||||
<br/>
|
||||
@@ -54,7 +69,7 @@ function renderMastodonContent(toots, parentElement) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="toot-link">
|
||||
<a class="date" href="${toot.uri}" rel="nofollow">
|
||||
<a class="date" href="${toot.uri}" rel="nofollow" target="_blank">
|
||||
${toot.created_at.substring(0, 10)}
|
||||
</a>
|
||||
<br/>
|
||||
@@ -62,24 +77,68 @@ function renderMastodonContent(toots, parentElement) {
|
||||
</div>
|
||||
<div class="mastodon-comment-content">
|
||||
${toot.content}
|
||||
<span class="tootlink">${toot.uri}</span>
|
||||
<span class="tootlink" ${showLink ? '' : 'style="display: none;"'}>${toot.uri}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
// Use DOMPurify to create a sanitised element for the toot
|
||||
const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true});
|
||||
|
||||
// make all toot links clickable
|
||||
const links = child.querySelectorAll('.tootlink');
|
||||
for (const link of links) {
|
||||
link.onclick = function() { return copyToClipboard(this); }
|
||||
link.onclick = function() { return copyElementTextToClipboard(this); }
|
||||
}
|
||||
|
||||
// insert the toot into the DOM
|
||||
parentElement.appendChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
// We set this in the "code injection" footer for any page for which we want to enable comments
|
||||
let MASTODON_POST_ID
|
||||
|
||||
// when the page has finished loading, send a request for the toots
|
||||
document.addEventListener("DOMContentLoaded", async (event) => {
|
||||
let url, isComments
|
||||
// if we're being crawled, don't render comments - may help against spam
|
||||
const isBot = /bot|google|baidu|bing|msn|teoma|slurp|yandex/i
|
||||
.test(navigator.userAgent)
|
||||
|
||||
// if there is a sidebar, we're expecting to load the toots from the main account
|
||||
if (document.getElementsByClassName('gh-sidebar').length > 0) {
|
||||
url = `https://${MASTODON_HOST}/api/v1/accounts/${MASTODON_ACCOUNT_ID}/statuses?exclude_replies=true&exclude_reblogs=true`
|
||||
}
|
||||
// if there's a post ID and we're not a bot, we're expecting to load the replies from a specific toot
|
||||
if (MASTODON_POST_ID && !isBot) {
|
||||
url = `https://${MASTODON_HOST}/api/v1/statuses/${MASTODON_POST_ID}/context`
|
||||
isComments = true
|
||||
}
|
||||
// find the element to append the content to - if there isn't one, we don't need to query
|
||||
const element = document.getElementById('mastodon-comments-list')
|
||||
const response = await fetch(`https://${MASTODON_HOST}/api/v1/accounts/${MASTODON_ACCOUNT_ID}/statuses?exclude_replies=true&exclude_reblogs=true`)
|
||||
const content = await response.json()
|
||||
return renderMastodonContent(content, element)
|
||||
if (url && element) {
|
||||
// populate the link to the source toot, if necessary (for replies)
|
||||
const linkElement = document.getElementById('toot-link-top')
|
||||
const clipElement = document.getElementById('toot-link-clip')
|
||||
const tootUrl = `https://${MASTODON_HOST}/@s/${MASTODON_POST_ID}`
|
||||
if (linkElement) {
|
||||
linkElement.href = tootUrl
|
||||
}
|
||||
if (clipElement) {
|
||||
clipElement.innerText = tootUrl
|
||||
}
|
||||
// fetch the data from Mastodon
|
||||
const response = await fetch(url)
|
||||
let content = await response.json()
|
||||
if (isComments) {
|
||||
content = content.descendants
|
||||
}
|
||||
// render the content into the page
|
||||
const header = document.getElementById('mastodon-comments-header')
|
||||
if (header) {
|
||||
header.style.display = ''
|
||||
}
|
||||
return renderMastodonContent(content, element, isComments)
|
||||
}
|
||||
})
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ const localTheme = window.localStorage && window.localStorage.getItem("lightThem
|
||||
const themeToggle = document.querySelector(".theme-toggle")
|
||||
|
||||
function changeFavicon() {
|
||||
const src = document.documentElement.classList.contains("dark-theme") ? "/img/favicon-dark.png" : "/img/favicon.png";
|
||||
const src = document.documentElement.classList.contains("dark-theme") ? "/assets/images/favicon-dark.png" : "/assets/images/favicon.png";
|
||||
const link = document.createElement('link'),
|
||||
oldLink = document.getElementById('dynamic-favicon');
|
||||
link.id = 'dynamic-favicon';
|
||||
|
||||
+7
-22
@@ -7,6 +7,12 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/webfonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
||||
<link rel="me" href="https://social.sd.ai/@s" />
|
||||
|
||||
{{!-- Preload main styles and scripts for better performance --}}
|
||||
<link rel="preload" as="style" href="{{asset "built/screen.css"}}">
|
||||
<link rel="preload" as="script" href="{{asset "built/source.js"}}">
|
||||
@@ -14,32 +20,11 @@
|
||||
{{!-- Theme assets - use the {{asset}} helper to reference styles & scripts, this will take care of caching and cache-busting automatically --}}
|
||||
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}">
|
||||
|
||||
{{!-- Custom background color --}}
|
||||
<style>
|
||||
:root {
|
||||
--background-color: {{@custom.site_background_color}}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
/* The script for calculating the color contrast has been taken from
|
||||
https://gomakethings.com/dynamically-changing-the-text-color-based-on-background-color-contrast-with-vanilla-js/ */
|
||||
var accentColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color');
|
||||
accentColor = accentColor.trim().slice(1);
|
||||
var r = parseInt(accentColor.substr(0, 2), 16);
|
||||
var g = parseInt(accentColor.substr(2, 2), 16);
|
||||
var b = parseInt(accentColor.substr(4, 2), 16);
|
||||
var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||
var textColor = (yiq >= 128) ? 'dark' : 'light';
|
||||
|
||||
document.documentElement.className = `has-${textColor}-text`;
|
||||
</script>
|
||||
|
||||
{{!-- This tag outputs all your advanced SEO meta, structured data, and other important settings, it should always be the last tag before the closing head tag --}}
|
||||
{{ghost_head}}
|
||||
|
||||
</head>
|
||||
<body class="{{body_class}} has-{{#match @custom.title_font "Elegant serif"}}serif{{else match @custom.title_font "Consistent mono"}}mono{{else}}sans{{/match}}-title has-{{#match @custom.body_font "Elegant serif"}}serif{{else}}sans{{/match}}-body">
|
||||
<body class="{{body_class}} has-sans-title has-sans-body">
|
||||
|
||||
<div class="gh-viewport">
|
||||
|
||||
|
||||
@@ -84,35 +84,6 @@
|
||||
],
|
||||
"default": "Logo in the middle"
|
||||
},
|
||||
"site_background_color": {
|
||||
"type": "color",
|
||||
"default": "#ffffff"
|
||||
},
|
||||
"header_and_footer_color": {
|
||||
"type": "select",
|
||||
"options": [
|
||||
"Background color",
|
||||
"Accent color"
|
||||
],
|
||||
"default": "Background color"
|
||||
},
|
||||
"title_font": {
|
||||
"type": "select",
|
||||
"options": [
|
||||
"Modern sans-serif",
|
||||
"Elegant serif",
|
||||
"Consistent mono"
|
||||
],
|
||||
"default": "Modern sans-serif"
|
||||
},
|
||||
"body_font": {
|
||||
"type": "select",
|
||||
"options": [
|
||||
"Modern sans-serif",
|
||||
"Elegant serif"
|
||||
],
|
||||
"default": "Modern sans-serif"
|
||||
},
|
||||
"signup_heading": {
|
||||
"type": "text",
|
||||
"description": "Used in your footer across your theme, defaults to site title when empty"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<footer class="gh-footer{{#match @custom.header_and_footer_color "Accent color"}} has-accent-color{{/match}} gh-outer">
|
||||
<footer class="gh-footer gh-outer">
|
||||
<div class="gh-footer-inner gh-inner">
|
||||
|
||||
<div class="gh-footer-bar">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<header id="gh-navigation" class="gh-navigation is-{{#match navigationLayout "Logo on the left"}}left-logo{{else match navigationLayout "Stacked"}}stacked{{else}}middle-logo{{/match}}{{#match @custom.header_and_footer_color "Accent color"}} has-accent-color{{/match}} gh-outer">
|
||||
<header id="gh-navigation" class="gh-navigation is-{{#match navigationLayout "Logo on the left"}}left-logo{{else match navigationLayout "Stacked"}}stacked{{else}}middle-logo{{/match}} gh-outer">
|
||||
<div class="gh-navigation-inner gh-inner">
|
||||
|
||||
<div class="gh-navigation-brand">
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{{#match @custom.header_style "Highlight"}}
|
||||
{{#if @custom.show_featured_posts}}
|
||||
{{#match posts.length ">=" 4}}
|
||||
{{#get "posts" include="authors" limit="16"}}
|
||||
{{#get "posts" include="authors,tags" limit="16"}}
|
||||
{{#foreach posts from="5" limit="12"}}
|
||||
{{> "post-card" lazyLoad=true}}
|
||||
{{/foreach}}
|
||||
@@ -31,7 +31,7 @@
|
||||
{{/match}}
|
||||
{{else}}
|
||||
{{#match posts.length ">=" 10}}
|
||||
{{#get "posts" include="authors" limit="22"}}
|
||||
{{#get "posts" include="authors,tags" limit="22"}}
|
||||
{{#foreach posts from="11" limit="12"}}
|
||||
{{> "post-card" lazyLoad=true}}
|
||||
{{/foreach}}
|
||||
@@ -40,14 +40,14 @@
|
||||
{{/if}}
|
||||
{{else match @custom.header_style "Magazine"}}
|
||||
{{#match posts.length ">=" 7}}
|
||||
{{#get "posts" include="authors" limit="19"}}
|
||||
{{#get "posts" include="authors,tags" limit="19"}}
|
||||
{{#foreach posts from="8" limit="12"}}
|
||||
{{> "post-card" lazyLoad=true}}
|
||||
{{/foreach}}
|
||||
{{/get}}
|
||||
{{/match}}
|
||||
{{else}}
|
||||
{{#get "posts" include="authors" limit="12"}}
|
||||
{{#get "posts" include="authors,tags" limit="12"}}
|
||||
{{#foreach posts}}
|
||||
{{> "post-card" lazyLoad=true}}
|
||||
{{/foreach}}
|
||||
@@ -58,7 +58,7 @@
|
||||
{{!-- All posts --}}
|
||||
{{#match feed "index"}}
|
||||
{{#match pagination.page 2}}
|
||||
{{#get "posts" include="authors" limit=@config.posts_per_page as |recent|}}
|
||||
{{#get "posts" include="authors,tags" limit=@config.posts_per_page as |recent|}}
|
||||
{{#foreach recent}}
|
||||
{{> "post-card"}}
|
||||
{{/foreach}}
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
</figure>
|
||||
{{/if}}
|
||||
<div class="gh-card-wrapper">
|
||||
{{#if primary_tag}}
|
||||
<p class="gh-card-tag">{{primary_tag.name}}</p>
|
||||
{{/if}}
|
||||
<h3 class="gh-card-title is-title">{{title}}</h3>
|
||||
{{#if excerpt}}
|
||||
<p class="gh-card-excerpt is-body">{{excerpt}}</p>
|
||||
@@ -31,6 +28,15 @@
|
||||
{{#if @custom.show_publish_date}}
|
||||
<time class="gh-card-date" datetime="{{date format="YYYY-MM-DD"}}">{{date}}</time>
|
||||
{{/if}}<!--
|
||||
--></footer>
|
||||
<footer class="gh-card-meta"><!--
|
||||
--><div class="gh-card-tags">
|
||||
Filed under:
|
||||
{{#foreach tags}}
|
||||
{{#if @index}}, {{/if}}
|
||||
<span class="gh-card-tag">{{name}}</span>
|
||||
{{/foreach}}
|
||||
</div><!--
|
||||
--></footer>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
|
||||
<header class="gh-article-header gh-canvas">
|
||||
|
||||
{{#if primary_tag}}
|
||||
<a class="gh-article-tag" href="{{primary_tag.url}}">{{primary_tag.name}}</a>
|
||||
{{/if}}
|
||||
<div class="gh-article-tags">
|
||||
{{#foreach tags}}
|
||||
<a class="gh-article-tag" href="{{url}}">{{name}}</a>
|
||||
{{/foreach}}
|
||||
</div>
|
||||
<h1 class="gh-article-title is-title">{{title}}</h1>
|
||||
{{#if custom_excerpt}}
|
||||
<p class="gh-article-excerpt is-body">{{custom_excerpt}}</p>
|
||||
{{/if}}
|
||||
|
||||
<div class="gh-article-meta">
|
||||
<div class="gh-article-author-image">
|
||||
@@ -50,6 +49,26 @@
|
||||
|
||||
</article>
|
||||
|
||||
<section class="gh-comments gh-canvas">
|
||||
|
||||
<div id="mastodon-comments-header" style="display: none;">
|
||||
|
||||
<div class="mastodon-comments-top">
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
<h2>Comments</h2>
|
||||
<p>Comments powered by Mastodon. Reply to <a id="toot-link-top">this status</a> to comment.</p>
|
||||
<div class="tootlink-tip">
|
||||
<b>Tip:</b> paste this URL into the search bar of your Mastodon client:<br/>
|
||||
<span id="toot-link-clip" class="tootlink" onclick="copyElementTextToClipboard(this)"></span> (click to copy)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<noscript><p>You need JavaScript to view the comments.</p></noscript>
|
||||
<div id="mastodon-comments-list"></div>
|
||||
</section>
|
||||
|
||||
{{#if comments}}
|
||||
<div class="gh-comments gh-canvas">
|
||||
{{comments}}
|
||||
@@ -60,7 +79,7 @@
|
||||
|
||||
{{/post}}
|
||||
|
||||
{{#get "posts" include="authors" filter="id:-{{post.id}}" limit="4" as |next|}}
|
||||
{{#get "posts" include="authors,tags" filter="id:-{{post.id}}" limit="4" as |next|}}
|
||||
{{#if next}}
|
||||
<section class="gh-container is-grid gh-outer">
|
||||
<div class="gh-container-inner gh-inner">
|
||||
|
||||
Reference in New Issue
Block a user