Compare commits

...

10 Commits

Author SHA1 Message Date
Simon Detheridge c7b9f9e67d
Add Mastodon toots to main page 2023-10-17 10:17:37 +01:00
Simon Detheridge a84195497e
Fix error in theme switcher 2023-10-16 19:55:08 +01:00
Simon Detheridge ab61ad1a67
Fix colours 2023-10-16 19:05:59 +01:00
Simon Detheridge 9b04b09f33
Add logo 2023-10-16 18:53:40 +01:00
Simon Detheridge 328473e596
Add theme switcher 2023-10-16 17:04:36 +01:00
Simon Detheridge a9b861a6aa
Update package.json 2023-10-16 15:06:45 +01:00
Sodbileg Gansukh 4b347f1b0d v1.0.1 2023-10-11 09:31:12 +08:00
Sodbileg Gansukh dedc9cbc3d Fixed pagination not working on tag templates
refs https://github.com/TryGhost/Source/issues/10
2023-10-11 09:30:48 +08:00
Daniel Lockyer e0483fd7f4
v1.0.0 2023-10-03 13:10:09 +02:00
Daniel Lockyer 98a35f9488
Updated built assets 2023-10-03 13:09:12 +02:00
18 changed files with 353 additions and 49 deletions

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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
/* ---------------------------------------------------------- */

View File

@ -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

File diff suppressed because one or more lines are too long

85
assets/js/mastodon.js Normal file
View 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, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
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
View 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)
}

View File

@ -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",

View File

@ -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">

View 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>

View File

@ -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>

View File

@ -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}}

View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 78 KiB

View 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

View File

@ -0,0 +1,3 @@
<button class="theme-toggle gh-icon-button" aria-label="Change theme">
{{> "icons/theme-icon"}}
</button>