Compare commits
10 Commits
3aa4afbee1
...
c7b9f9e67d
Author | SHA1 | Date | |
---|---|---|---|
c7b9f9e67d | |||
a84195497e | |||
ab61ad1a67 | |||
9b04b09f33 | |||
328473e596 | |||
a9b861a6aa | |||
|
4b347f1b0d | ||
|
dedc9cbc3d | ||
|
e0483fd7f4 | ||
|
98a35f9488 |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
29
assets/built/source.js
Executable file → Normal file
29
assets/built/source.js
Executable file → Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -69,13 +69,35 @@ production stylesheet in assets/built/screen.css
|
||||
--container-width: 1320px;
|
||||
--container-gap: clamp(24px, 1.7032rem + 1.9355vw, 48px);
|
||||
--grid-gap: 42px;
|
||||
--card-border-radius: 5px;
|
||||
}
|
||||
|
||||
:root.light-theme {
|
||||
/* light theme color */
|
||||
--background-color: #fff;
|
||||
--background-secondary: #eaeaea;
|
||||
--header: #fafafa;
|
||||
--color-primary-text: #222;
|
||||
--color-secondary-text: #999;
|
||||
--border-color: #dcdcdc;
|
||||
--ghost-accent-color: #007700;
|
||||
}
|
||||
|
||||
:root.dark-theme {
|
||||
/* dark theme colors */
|
||||
--background-color: #292a2d;
|
||||
--background-secondary: #3b3d42;
|
||||
--header: #252627;
|
||||
--color-primary-text: #a9a9b3;
|
||||
--color-secondary-text: #73747b;
|
||||
--border-color: #4a4b50;
|
||||
--ghost-accent-color: #77bb77;
|
||||
}
|
||||
|
||||
:root.has-light-text,
|
||||
:is(.gh-navigation, .gh-footer).has-accent-color {
|
||||
--color-lighter-gray: rgb(255 255 255 / 0.1);
|
||||
--color-darker-gray: #fff;
|
||||
--color-secondary-text: rgb(255 255 255 / 0.64);
|
||||
--color-darker-gray: var(--color-primary-text);
|
||||
--color-border: rgb(255 255 255 / 0.15);
|
||||
--color-dark-border: rgb(255 255 255 / 0.5);
|
||||
}
|
||||
@ -1002,6 +1024,73 @@ Search LOGO Login Subscribe
|
||||
|
||||
/* 8. Header
|
||||
/* ---------------------------------------------------------- */
|
||||
.gh-navigation-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: var(--color-secondary-text)
|
||||
}
|
||||
|
||||
.logo-mark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 5px;
|
||||
height: 0.8em;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 0.8em;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.logo-cursor {
|
||||
display: inline-block;
|
||||
width: 0.4em;
|
||||
height: 0.8em;
|
||||
background: var(--color-secondary-text);
|
||||
margin-left: 5px;
|
||||
border-radius: 1px;
|
||||
animation: cursor 1.5s infinite;
|
||||
}
|
||||
|
||||
.greater-icon {
|
||||
width: 0.6em;
|
||||
height: 0.6em;
|
||||
}
|
||||
.greater-icon path {
|
||||
stroke: currentColor;
|
||||
stroke-width: .95rem;
|
||||
}
|
||||
|
||||
@keyframes cursor {
|
||||
0% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
#svglogo {
|
||||
height: 2.5em;
|
||||
width: 2.5em;
|
||||
}
|
||||
|
||||
#svglogo use {
|
||||
fill: var(--color-primary-text);
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.theme-toggler {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
||||
.gh-header {
|
||||
position: relative;
|
||||
@ -1638,12 +1727,12 @@ Search LOGO Login Subscribe
|
||||
/* 11.1. With sidebar */
|
||||
|
||||
.gh-container.has-sidebar .gh-main {
|
||||
grid-column: 1 / span 12;
|
||||
grid-column: 1 / span 11;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gh-container.has-sidebar .gh-sidebar {
|
||||
grid-column: 13 / -1;
|
||||
grid-column: 12 / -1;
|
||||
}
|
||||
|
||||
.gh-container.has-sidebar .gh-main::after {
|
||||
@ -1866,6 +1955,59 @@ 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
|
||||
/* ---------------------------------------------------------- */
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
/* Infinite scroll pagination */
|
||||
(function () {
|
||||
if (document.body.classList.contains('paged')) {
|
||||
if (!document.body.classList.contains('post-template')) {
|
||||
pagination();
|
||||
}
|
||||
})();
|
3
assets/js/lib/purify.min.js
vendored
Normal file
3
assets/js/lib/purify.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
85
assets/js/mastodon.js
Normal file
85
assets/js/mastodon.js
Normal file
@ -0,0 +1,85 @@
|
||||
const MASTODON_ACCOUNT_ID = '109285376472065471'
|
||||
const MASTODON_HOST = 'social.sd.ai'
|
||||
|
||||
async function copyElementTextToClipboard(e)
|
||||
{
|
||||
const text = e.textContent
|
||||
await navigator.clipboard.write(text)
|
||||
|
||||
e.classList.add('tootClick');
|
||||
setTimeout(() => {
|
||||
e.classList.remove('tootClick');
|
||||
}, 600);
|
||||
}
|
||||
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function renderMastodonContent(toots, parentElement) {
|
||||
if (!Array.isArray(toots) || toots.length === 0) {
|
||||
document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>"
|
||||
return
|
||||
}
|
||||
for (const toot of toots) {
|
||||
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" />`);
|
||||
})
|
||||
toot.emojis.forEach(emoji => {
|
||||
toot.content = toot.content.replace(`:${emoji.shortcode}:`,
|
||||
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
|
||||
})
|
||||
const comment =
|
||||
`<div class="mastodon-comment">
|
||||
<div class="mastodon-avatar">
|
||||
<img src="${escapeHtml(toot.account.avatar_static)}" height=60 width=60 alt="${escapeHtml(toot.account.display_name)}'s avatar">
|
||||
</div>
|
||||
<div class="mastodon-body">
|
||||
<div class="mastodon-meta">
|
||||
<div class="mastodon-author">
|
||||
<div class="mastodon-author-link">
|
||||
<a href="${toot.account.url}" rel="nofollow">
|
||||
<span>${toot.account.display_name}</span>
|
||||
</a>
|
||||
<br/>
|
||||
<span class="mastodon-author-uid">(@${escapeHtml(toot.account.acct === 's' ? 's@sd.ai' : toot.account.acct)})</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toot-link">
|
||||
<a class="date" href="${toot.uri}" rel="nofollow">
|
||||
${toot.created_at.substring(0, 10)}
|
||||
</a>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mastodon-comment-content">
|
||||
${toot.content}
|
||||
<span class="tootlink">${toot.uri}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true});
|
||||
const links = child.querySelectorAll('.tootlink');
|
||||
for (const link of links) {
|
||||
link.onclick = function() { return copyToClipboard(this); }
|
||||
}
|
||||
parentElement.appendChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async (event) => {
|
||||
if (document.getElementsByClassName('gh-sidebar').length > 0) {
|
||||
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)
|
||||
}
|
||||
})
|
45
assets/js/theme.js
Normal file
45
assets/js/theme.js
Normal file
@ -0,0 +1,45 @@
|
||||
// Toggle theme
|
||||
|
||||
const isOSLight = window.matchMedia("(prefers-color-scheme: light)").matches
|
||||
const localTheme = window.localStorage && window.localStorage.getItem("lightTheme")
|
||||
const themeToggle = document.querySelector(".theme-toggle")
|
||||
|
||||
function changeFavicon() {
|
||||
const src = document.documentElement.classList.contains("dark-theme") ? "/img/favicon-dark.png" : "/img/favicon.png";
|
||||
const link = document.createElement('link'),
|
||||
oldLink = document.getElementById('dynamic-favicon');
|
||||
link.id = 'dynamic-favicon';
|
||||
link.rel = 'shortcut icon';
|
||||
link.href = src;
|
||||
if (oldLink) {
|
||||
document.head.removeChild(oldLink);
|
||||
}
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function changeTheme(useLight) {
|
||||
document.documentElement.classList.remove('light-theme', 'dark-theme', 'has-light-text', 'has-dark-text')
|
||||
if (useLight) {
|
||||
document.documentElement.classList.add('light-theme', 'has-dark-text')
|
||||
} else {
|
||||
document.documentElement.classList.add('dark-theme', 'has-light-text')
|
||||
}
|
||||
|
||||
if (window.localStorage) {
|
||||
window.localStorage.setItem(
|
||||
"lightTheme",
|
||||
useLight ? "light" : "dark")
|
||||
}
|
||||
|
||||
changeFavicon()
|
||||
}
|
||||
|
||||
themeToggle.addEventListener("click", () => {
|
||||
changeTheme(document.documentElement.classList.contains('dark-theme'))
|
||||
});
|
||||
|
||||
if (localTheme === "light") {
|
||||
changeTheme(true)
|
||||
} else {
|
||||
changeTheme(isOSLight)
|
||||
}
|
23
package.json
23
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "source",
|
||||
"description": "A default theme for the Ghost publishing platform",
|
||||
"demo": "https://source.ghost.io",
|
||||
"name": "sd-ai",
|
||||
"description": "Theme for sd.ai, forked from Source theme",
|
||||
"demo": "https://sd.ai/",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"ghost": ">=5.0.0"
|
||||
@ -18,16 +18,9 @@
|
||||
"postship": "git fetch && gulp release"
|
||||
},
|
||||
"author": {
|
||||
"name": "Ghost Foundation",
|
||||
"email": "hello@ghost.org",
|
||||
"url": "https://ghost.org/"
|
||||
},
|
||||
"gpm": {
|
||||
"type": "theme",
|
||||
"categories": [
|
||||
"Minimal",
|
||||
"Magazine"
|
||||
]
|
||||
"name": "Simon Detheridge",
|
||||
"email": "s@sd.ai",
|
||||
"url": "https://sd.ai/"
|
||||
},
|
||||
"keywords": [
|
||||
"ghost",
|
||||
@ -36,10 +29,8 @@
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/TryGhost/Source.git"
|
||||
"url": "https://git.sd.ai/simon/ghost-theme-sd.ai"
|
||||
},
|
||||
"bugs": "https://github.com/TryGhost/Source/issues",
|
||||
"contributors": "https://github.com/TryGhost/Source/graphs/contributors",
|
||||
"devDependencies": {
|
||||
"@tryghost/release-utils": "0.8.1",
|
||||
"autoprefixer": "10.4.7",
|
||||
|
@ -14,6 +14,8 @@
|
||||
</nav>
|
||||
<div class="gh-footer-copyright">
|
||||
Powered by <a href="https://ghost.org/" target="_blank" rel="noopener">Ghost</a>
|
||||
:
|
||||
<a href="https://git.sd.ai/simon/ghost-theme-sd.ai" target="_blank" rel="noopener">Theme</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
5
partials/components/logo.hbs
Normal file
5
partials/components/logo.hbs
Normal file
@ -0,0 +1,5 @@
|
||||
{{> "icons/svglogo"}}
|
||||
|
||||
<span class="logo-mark">{{> "icons/greater-icon"}}</span>
|
||||
<span class="logo-text">sd.ai</span>
|
||||
<span class="logo-cursor"></span>
|
@ -6,7 +6,7 @@
|
||||
{{#if @site.logo}}
|
||||
<img src="{{@site.logo}}" alt="{{@site.title}}">
|
||||
{{else}}
|
||||
{{@site.title}}
|
||||
{{> "components/logo"}}
|
||||
{{/if}}
|
||||
</a>
|
||||
{{> "search-toggle"}}
|
||||
@ -47,6 +47,7 @@
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{> "theme-switcher"}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -81,26 +81,8 @@
|
||||
|
||||
{{#if showSidebar}}
|
||||
<aside class="gh-sidebar">
|
||||
<section class="gh-about">
|
||||
{{#if @site.icon}}
|
||||
<img class="gh-about-icon" src="{{@site.icon}}" alt="{{@site.title}}" loading="lazy">
|
||||
{{/if}}
|
||||
<h3 class="gh-about-title is-title">{{@site.title}}</h3>
|
||||
{{#if @site.description}}
|
||||
<p class="gh-about-description is-body">{{@site.description}}</p>
|
||||
{{/if}}
|
||||
{{#if @site.members_enabled}}
|
||||
{{#unless @member}}
|
||||
<button class="gh-button" data-portal="signup">Subscribe</button>
|
||||
{{else}}
|
||||
{{#if @site.paid_members_enabled}}
|
||||
{{#unless @member.paid}}
|
||||
<button class="gh-button" data-portal="upgrade">Upgrade</button>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</section>
|
||||
<h3 class="gh-card-title is-title"><a href="https://social.sd.ai/@s" target="_blank" rel="noopener">Latest From Mastodon</a></h3>
|
||||
<div id="mastodon-comments-list"></div>
|
||||
</aside>
|
||||
{{/if}}
|
||||
|
||||
|
3
partials/icons/greater-icon.hbs
Normal file
3
partials/icons/greater-icon.hbs
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="greater-icon" viewBox="0 0 44 44">
|
||||
<path fill="none" d="M15 8l14.729 14.382L15 35.367" />
|
||||
</svg>
|
After Width: | Height: | Size: 146 B |
1
partials/icons/svglogo.hbs
Normal file
1
partials/icons/svglogo.hbs
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 78 KiB |
14
partials/icons/theme-icon.hbs
Normal file
14
partials/icons/theme-icon.hbs
Normal file
@ -0,0 +1,14 @@
|
||||
<svg
|
||||
class="theme-toggler"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 48 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M22 41C32.4934 41 41 32.4934 41 22C41 11.5066 32.4934 3 22
|
||||
3C11.5066 3 3 11.5066 3 22C3 32.4934 11.5066 41 22 41ZM7 22C7
|
||||
13.7157 13.7157 7 22 7V37C13.7157 37 7 30.2843 7 22Z"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 337 B |
3
partials/theme-switcher.hbs
Normal file
3
partials/theme-switcher.hbs
Normal file
@ -0,0 +1,3 @@
|
||||
<button class="theme-toggle gh-icon-button" aria-label="Change theme">
|
||||
{{> "icons/theme-icon"}}
|
||||
</button>
|
Loading…
Reference in New Issue
Block a user