Compare commits
10 Commits
3aa4afbee1
...
c7b9f9e67d
Author | SHA1 | Date |
---|---|---|
Simon Detheridge | c7b9f9e67d | |
Simon Detheridge | a84195497e | |
Simon Detheridge | ab61ad1a67 | |
Simon Detheridge | 9b04b09f33 | |
Simon Detheridge | 328473e596 | |
Simon Detheridge | a9b861a6aa | |
Sodbileg Gansukh | 4b347f1b0d | |
Sodbileg Gansukh | dedc9cbc3d | |
Daniel Lockyer | e0483fd7f4 | |
Daniel Lockyer | 98a35f9488 |
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
|
@ -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);
|
||||
}
|
||||
|
@ -369,7 +391,7 @@ button.gh-form-input {
|
|||
.gh-form {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
|
||||
.gh-form .gh-button {
|
||||
padding-inline: 12px;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
})();
|
File diff suppressed because one or more lines are too long
|
@ -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)
|
||||
}
|
||||
})
|
|
@ -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,9 +14,11 @@
|
|||
</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>
|
||||
|
||||
|
||||
{{#if @site.members_enabled}}
|
||||
{{#unless @member}}
|
||||
<section class="gh-footer-signup">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<section class="gh-container is-{{#match postFeedStyle "List"}}list{{else}}grid{{/match}}{{#if showSidebar}} has-sidebar{{/if}}{{#unless @custom.show_images_in_feed}} no-image{{/unless}} gh-outer">
|
||||
<div class="gh-container-inner gh-inner">
|
||||
|
||||
|
||||
{{#if showTitle}}
|
||||
<h2 class="gh-container-title">
|
||||
{{#unless title}}Latest{{else}}{{title}}{{/unless}}
|
||||
|
@ -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}}
|
||||
|
||||
|
|
|
@ -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 |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 78 KiB |
|
@ -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 |
|
@ -0,0 +1,3 @@
|
|||
<button class="theme-toggle gh-icon-button" aria-label="Change theme">
|
||||
{{> "icons/theme-icon"}}
|
||||
</button>
|
Loading…
Reference in New Issue