From 9b2b90b46e5ba849bbf4e8477e028c04a38dd263 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Sun, 23 Sep 2018 12:26:01 -0700 Subject: [PATCH] simplify theme definitions (#574) * simplify theme definitions * remove rollup dep which is overkill * fix syntax error * fix lint * fix test --- bin/build-inline-script.js | 23 ++++++++++++++--------- docs/Theming.md | 37 +++---------------------------------- inline-script.js | 20 +++----------------- package.json | 2 +- scss/themes/_offline.scss | 14 +------------- templates/2xx.html | 26 +++++++------------------- tests/utils.js | 4 +++- 7 files changed, 32 insertions(+), 94 deletions(-) diff --git a/bin/build-inline-script.js b/bin/build-inline-script.js index 5c83123..a648097 100644 --- a/bin/build-inline-script.js +++ b/bin/build-inline-script.js @@ -1,18 +1,23 @@ #!/usr/bin/env node -const crypto = require('crypto') -const fs = require('fs') -const pify = require('pify') +import crypto from 'crypto' +import fs from 'fs' +import pify from 'pify' +import path from 'path' +import { themes } from '../routes/_static/themes.js' +import { fromPairs } from 'lodash-es' + const readFile = pify(fs.readFile.bind(fs)) const writeFile = pify(fs.writeFile.bind(fs)) -const path = require('path') async function main () { - let headScriptFilepath = path.join(__dirname, '../inline-script.js') - let headScript = await readFile(headScriptFilepath, 'utf8') - headScript = `(function () {'use strict'; ${headScript}})()` + let inlineScriptPath = path.join(__dirname, '../inline-script.js') + let code = await readFile(inlineScriptPath, 'utf8') - let checksum = crypto.createHash('sha256').update(headScript).digest('base64') + code = code.replace('process.env.THEME_COLORS', JSON.stringify(fromPairs(themes.map(_ => ([_.name, _.color]))))) + code = `(function () {'use strict'\n${code}})()` + + let checksum = crypto.createHash('sha256').update(code).digest('base64') let checksumFilepath = path.join(__dirname, '../inline-script-checksum.json') await writeFile(checksumFilepath, JSON.stringify({ checksum }), 'utf8') @@ -21,7 +26,7 @@ async function main () { let html2xxFile = await readFile(html2xxFilepath, 'utf8') html2xxFile = html2xxFile.replace( /[\s\S]+/, - '' + '' ) await writeFile(html2xxFilepath, html2xxFile, 'utf8') } diff --git a/docs/Theming.md b/docs/Theming.md index 318fb74..57bca8e 100644 --- a/docs/Theming.md +++ b/docs/Theming.md @@ -11,48 +11,17 @@ body.theme-foobar { > Note: You can find all the SCSS variables available in `scss/themes/_default.scss` while the all CSS Custom Properties available are listed in `scss/themes/_base.scss`. -Add the CSS class you just define to `scss/themes/_offlines`. -```scss -... -body.offline, -body.theme-foobar.offline, // <- -body.theme-hotpants.offline, -body.theme-majesty.offline, -body.theme-oaken.offline, -body.theme-scarlet.offline, -body.theme-seafoam.offline, -body.theme-gecko.offline { - @include baseTheme(); -} - -``` - Add your theme to `routes/_static/themes.js` ```js const themes = [ ... { name: 'foobar', - label: 'Foobar' + label: 'Foobar', // user-visible name + color: 'magenta', // main theme color + dark: true // whether it's a dark theme or not } ] - -export { themes } -``` - -Add your theme in `inline-script.js`. -```js -window.__themeColors = { - 'default': "royalblue", - scarlet: "#e04e41", - seafoam: "#177380", - hotpants: "hotpink", - oaken: "saddlebrown", - majesty: "blueviolet", - gecko: "#4ab92f", - foobar: "#BADA55", // <- - offline: "#999999" - } ``` Start the development server (`npm run dev`), go to `http://localhost:4002/settings/instances/your-instance-name` and select your newly created theme. Once you've done that, you can update your theme, and refresh the page to see the change (you don't have to restart the server). diff --git a/inline-script.js b/inline-script.js index 68bb3a6..6af6cd7 100644 --- a/inline-script.js +++ b/inline-script.js @@ -1,23 +1,8 @@ // For perf reasons, this script is run inline to quickly set certain styles. // To allow CSP to work correctly, we also calculate a sha256 hash during // the build process and write it to inline-script-checksum.json. -// TODO: these should not have to be defined twice, once here and again in themes.js -window.__themeColors = { - 'default': 'royalblue', - scarlet: '#e04e41', - seafoam: '#177380', - hotpants: 'hotpink', - oaken: 'saddlebrown', - majesty: 'blueviolet', - gecko: '#4ab92f', - ozark: '#5263af', - cobalt: '#08439b', - sorcery: '#ae91e8', - punk: '#e04e41', - riot: 'hotpink', - hacker: '#4ab92f', - offline: '#999999' -} +window.__themeColors = process.env.THEME_COLORS + if (localStorage.store_currentInstance && localStorage.store_instanceThemes) { let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str) let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)] @@ -32,6 +17,7 @@ if (localStorage.store_currentInstance && localStorage.store_instanceThemes) { } } } + if (!localStorage.store_currentInstance) { // if not logged in, show all these 'hidden-from-ssr' elements let style = document.createElement('style') diff --git a/package.json b/package.json index 8635829..ff7df1b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "start": "cross-env NODE_ENV=production npm run serve", "build-and-start": "run-s build start", "build-svg": "node ./bin/build-svg.js", - "build-inline-script": "node ./bin/build-inline-script.js", + "build-inline-script": "node -r esm ./bin/build-inline-script.js", "build-sass": "node ./bin/build-sass.js", "build-sass-watch": "node ./bin/build-sass.js --watch", "run-mastodon": "node -r esm ./bin/run-mastodon.js", diff --git a/scss/themes/_offline.scss b/scss/themes/_offline.scss index efeac8f..826f0ec 100644 --- a/scss/themes/_offline.scss +++ b/scss/themes/_offline.scss @@ -12,18 +12,6 @@ $compose-background: lighten($main-theme-color, 17%); @import "_base.scss"; -body.offline, -body.theme-hotpants.offline, -body.theme-majesty.offline, -body.theme-oaken.offline, -body.theme-scarlet.offline, -body.theme-seafoam.offline, -body.theme-gecko.offline, -body.theme-ozark.offline, -body.theme-cobalt.offline, -body.theme-sorcery.offline, -body.theme-riot.offline, -body.theme-punk.offline, -body.theme-hacker.offline { +body.the-body.offline { /* "the-body" is a specificity hack to allow offline to always trump themes */ @include baseTheme(); } diff --git a/templates/2xx.html b/templates/2xx.html index dfee823..95f8022 100644 --- a/templates/2xx.html +++ b/templates/2xx.html @@ -18,7 +18,7 @@ /* auto-generated w/ build-sass.js */ body{--button-primary-bg: #6081e6;--button-primary-text: #fff;--button-primary-border: #132c76;--button-primary-bg-active: #456ce2;--button-primary-bg-hover: #6988e7;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #4169e1;--main-bg: #fff;--body-bg: #e8edfb;--body-text-color: #333;--main-border: #dadada;--svg-fill: #4169e1;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #4169e1;--nav-border: #214cce;--nav-a-border: #4169e1;--nav-a-selected-border: #fff;--nav-a-selected-bg: #6d8ce8;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #839deb;--nav-a-bg-hover: #577ae4;--nav-a-border-hover: #4169e1;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #90a8ee;--action-button-fill-color-hover: #a2b6f0;--action-button-fill-color-active: #577ae4;--action-button-fill-color-pressed: #2351dc;--action-button-fill-color-pressed-hover: #3862e0;--action-button-fill-color-pressed-active: #1d44b8;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #4169e1;--settings-list-item-text-hover: #4169e1;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #c5d1f6;--very-deemphasized-link-color: rgba(65,105,225,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #d2dcf8;--main-theme-color: #4169e1;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #ced8f7;--compose-autosuggest-item-active: #b8c7f4;--compose-autosuggest-outline: #dbe3f9;--compose-button-halo: rgba(255,255,255,0.1)} body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);-webkit-tap-highlight-color:transparent}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;position:absolute;top:42px;left:0;right:0;bottom:0}@media (max-width: 991px){.container{top:52px}}@media (max-width: 767px){.container{top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:15px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}input,textarea{background:inherit;color:inherit}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}.container:focus{outline:none}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}25%{transform:rotate(90deg)}50%{transform:rotate(180deg)}75%{transform:rotate(270deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 1.5s infinite linear}.ellipsis::after{content:"\2026"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.inline-custom-emoji{width:1.4em;height:1.4em;margin:-0.1em 0;object-fit:contain;vertical-align:middle} -body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline,body.theme-ozark.offline,body.theme-cobalt.offline,body.theme-sorcery.offline,body.theme-riot.offline,body.theme-punk.offline,body.theme-hacker.offline{--button-primary-bg: #ababab;--button-primary-text: #fff;--button-primary-border: #4d4d4d;--button-primary-bg-active: #9c9c9c;--button-primary-bg-hover: #b0b0b0;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #999;--main-bg: #fff;--body-bg: #fafafa;--body-text-color: #333;--main-border: #dadada;--svg-fill: #999;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #999;--nav-border: gray;--nav-a-border: #999;--nav-a-selected-border: #fff;--nav-a-selected-bg: #b3b3b3;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #bfbfbf;--nav-a-bg-hover: #a6a6a6;--nav-a-border-hover: #999;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #c7c7c7;--action-button-fill-color-hover: #d1d1d1;--action-button-fill-color-active: #a6a6a6;--action-button-fill-color-pressed: #878787;--action-button-fill-color-pressed-hover: #949494;--action-button-fill-color-pressed-active: #737373;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #999;--settings-list-item-text-hover: #999;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #bfbfbf;--very-deemphasized-link-color: rgba(153,153,153,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #ededed;--main-theme-color: #999;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #c4c4c4;--compose-autosuggest-item-active: #b8b8b8;--compose-autosuggest-outline: #ccc;--compose-button-halo: rgba(255,255,255,0.1)} +body.the-body.offline{--button-primary-bg: #ababab;--button-primary-text: #fff;--button-primary-border: #4d4d4d;--button-primary-bg-active: #9c9c9c;--button-primary-bg-hover: #b0b0b0;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #999;--main-bg: #fff;--body-bg: #fafafa;--body-text-color: #333;--main-border: #dadada;--svg-fill: #999;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #999;--nav-border: gray;--nav-a-border: #999;--nav-a-selected-border: #fff;--nav-a-selected-bg: #b3b3b3;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #bfbfbf;--nav-a-bg-hover: #a6a6a6;--nav-a-border-hover: #999;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #c7c7c7;--action-button-fill-color-hover: #d1d1d1;--action-button-fill-color-active: #a6a6a6;--action-button-fill-color-pressed: #878787;--action-button-fill-color-pressed-hover: #949494;--action-button-fill-color-pressed-active: #737373;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #999;--settings-list-item-text-hover: #999;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #bfbfbf;--very-deemphasized-link-color: rgba(153,153,153,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #ededed;--main-theme-color: #999;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #c4c4c4;--compose-autosuggest-item-active: #b8b8b8;--compose-autosuggest-outline: #ccc;--compose-button-halo: rgba(255,255,255,0.1)} @@ -39,27 +39,14 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o the current page has one --> %sapper.head% - + -