From 23e2ffecbf182b26aec5bdf220be7d455eeb349f Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Sat, 9 May 2020 21:34:00 +1200 Subject: [PATCH] Refactor sass for theming --- package-lock.json | 4 +- package.json | 2 +- src/lib/constants.js | 17 +- src/lib/utils/upgradedb.js | 11 + src/site/api/routes.js | 10 +- src/site/pug/includes/head.pug | 5 +- src/site/pug/settings.pug | 20 +- src/site/sass/blue.sass | 2 + src/site/sass/classic.sass | 2 + src/site/sass/{ => includes}/_forms.sass | 1 + .../sass/{main.sass => includes/_main.sass} | 205 ++++++++---------- src/site/sass/themes/_blue.scss | 16 ++ src/site/sass/themes/_classic.scss | 54 +++++ src/site/server.js | 5 +- 14 files changed, 226 insertions(+), 128 deletions(-) create mode 100644 src/site/sass/blue.sass create mode 100644 src/site/sass/classic.sass rename src/site/sass/{ => includes}/_forms.sass (99%) rename src/site/sass/{main.sass => includes/_main.sass} (71%) create mode 100644 src/site/sass/themes/_blue.scss create mode 100644 src/site/sass/themes/_classic.scss diff --git a/package-lock.json b/package-lock.json index c8e3a51..e9ab808 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2738,8 +2738,8 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pinski": { - "version": "github:cloudrac3r/pinski#342365c44b923d5e6c6c5c34bc9267d7652be2a9", - "from": "github:cloudrac3r/pinski#342365c44b923d5e6c6c5c34bc9267d7652be2a9", + "version": "github:cloudrac3r/pinski#61809e18606265ec47813f3bdab80928c70ae203", + "from": "github:cloudrac3r/pinski#61809e18606265ec47813f3bdab80928c70ae203", "requires": { "mime": "^2.4.4", "pug": "^2.0.3", diff --git a/package.json b/package.json index f2e0329..5cbcfe0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "mixin-deep": "^2.0.1", "node-dir": "^0.1.17", "node-fetch": "^2.6.0", - "pinski": "github:cloudrac3r/pinski#342365c44b923d5e6c6c5c34bc9267d7652be2a9", + "pinski": "github:cloudrac3r/pinski#61809e18606265ec47813f3bdab80928c70ae203", "pug": "^2.0.4", "semver": "^7.2.1", "sharp": "^0.25.2", diff --git a/src/lib/constants.js b/src/lib/constants.js index b68f1df..9955b86 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -114,6 +114,21 @@ let constants = { default: "", boolean: true, replaceEmptyWithDefault: true + },{ + name: "save_data", + default: "automatic", + boolean: false, + replaceEmptyWithDefault: true + },{ + name: "rewrite_youtube", + default: "", + boolean: false, + replaceEmptyWithDefault: true + },{ + name: "rewrite_twitter", + default: "", + boolean: false, + replaceEmptyWithDefault: true } ], @@ -210,7 +225,7 @@ let constants = { additional_routes: [], - database_version: 5 + database_version: 6 } // Override values from config and export the result diff --git a/src/lib/utils/upgradedb.js b/src/lib/utils/upgradedb.js index 1f861fe..54aa4e3 100644 --- a/src/lib/utils/upgradedb.js +++ b/src/lib/utils/upgradedb.js @@ -75,6 +75,17 @@ const deltas = new Map([ .run() })() }], + // version 5 to version 6 + [6, function() { + db.transaction(() => { + db.prepare("ALTER TABLE UserSettings ADD COLUMN save_data TEXT NOT NULL DEFAULT 'automatic'") + .run() + db.prepare("ALTER TABLE UserSettings ADD COLUMN rewrite_youtube TEXT NOT NULL DEFAULt ''") + .run() + db.prepare("ALTER TABLE UserSettings ADD COLUMN rewrite_twitter TEXT NOT NULL DEFAULT ''") + .run() + })() + }] ]) module.exports = async function() { diff --git a/src/site/api/routes.js b/src/site/api/routes.js index 3acab20..3288520 100644 --- a/src/site/api/routes.js +++ b/src/site/api/routes.js @@ -12,8 +12,10 @@ function getPageTitle(post) { module.exports = [ { - route: "/", methods: ["GET"], code: async () => { + route: "/", methods: ["GET"], code: async ({req}) => { + const settings = getSettings(req) return render(200, "pug/home.pug", { + settings, rssEnabled: constants.feeds.enabled, allUnblocked: history.testNoneBlocked(), torAvailable: switcher.canUseTor(), @@ -22,9 +24,11 @@ module.exports = [ } }, { - route: "/privacy", methods: ["GET"], code: async () => { + route: "/privacy", methods: ["GET"], code: async ({req}) => { + if (constants.has_privacy_policy && pugCache.has("pug/privacy.pug")) { - return render(200, "pug/privacy.pug") + const settings = getSettings(req) + return render(200, "pug/privacy.pug", {settings}) } else { return render(404, "pug/friendlyerror.pug", { statusCode: 404, diff --git a/src/site/pug/includes/head.pug b/src/site/pug/includes/head.pug index da0b614..a335a5f 100644 --- a/src/site/pug/includes/head.pug +++ b/src/site/pug/includes/head.pug @@ -1,5 +1,8 @@ meta(charset="utf-8") -link(rel="stylesheet" type="text/css" href=getStaticURL("sass", "main.sass")) + +- let theme = settings ? settings.theme : "classic" +link(rel="stylesheet" type="text/css" href=getStaticURL("sass", `${theme}.sass`)) + meta(name="viewport" content="width=device-width, initial-scale=1") link(rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png") link(rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png") diff --git a/src/site/pug/settings.pug b/src/site/pug/settings.pug index f8d0f73..0dd02fb 100644 --- a/src/site/pug/settings.pug +++ b/src/site/pug/settings.pug @@ -6,10 +6,10 @@ mixin fieldset(name) .fieldset-contents block -mixin input(id, description, disabled) +mixin input(id, description, placeholder, disabled) .field-row label.description(for=id)= description - input(type="text" id=id name=id value=settings[id] disabled=disabled) + input(type="text" id=id name=id value=settings[id] placeholder=placeholder disabled=disabled) mixin checkbox(id, description, label, disabled) .field-row.checkbox-row @@ -45,6 +45,17 @@ html {value: "en-us", text: "English (US)"} ]) + +select("save_data", "Save data", true, [ + {value: "automatic", text: "Automatic"}, + {value: "off", text: "Off"}, + {value: "lazy_load", text: "Lazy load"}, + {value: "full", text: "Full"} + ]) + + +input("rewrite_youtube", "Rewrite YouTube domain", "youtube.com", true) + + +input("rewrite_twitter", "Rewrite Twitter domain", "twitter.com", true) + +checkbox("show_comments", "Display comments", "Display", true) +checkbox("link_hashtags", "Clickable hashtags", "Clickable", true) @@ -52,8 +63,9 @@ html +checkbox("spa", "Fast navigation", "Enabled", false) +fieldset("Appearance") - +select("theme", "Theme", true, [ - {value: "classic", text: "Classic"} + +select("theme", "Theme", false, [ + {value: "classic", text: "Classic"}, + {value: "blue", text: "Classic blue"} ]) +checkbox("display_top_nav", "Display top bar", "Always", false) diff --git a/src/site/sass/blue.sass b/src/site/sass/blue.sass new file mode 100644 index 0000000..c817b27 --- /dev/null +++ b/src/site/sass/blue.sass @@ -0,0 +1,2 @@ +@use "themes/blue" as * +@use "includes/main" with ($theme: $theme) diff --git a/src/site/sass/classic.sass b/src/site/sass/classic.sass new file mode 100644 index 0000000..1d82851 --- /dev/null +++ b/src/site/sass/classic.sass @@ -0,0 +1,2 @@ +@use "themes/classic" as * +@use "includes/main" with ($theme: $theme) diff --git a/src/site/sass/_forms.sass b/src/site/sass/includes/_forms.sass similarity index 99% rename from src/site/sass/_forms.sass rename to src/site/sass/includes/_forms.sass index 985e92a..dfd96c8 100644 --- a/src/site/sass/_forms.sass +++ b/src/site/sass/includes/_forms.sass @@ -96,6 +96,7 @@ button, select, input, .checkbox-row .pill input[type="text"] width: 200px + padding: 5px 8px select padding: 4px 6px 4px 4px diff --git a/src/site/sass/main.sass b/src/site/sass/includes/_main.sass similarity index 71% rename from src/site/sass/main.sass rename to src/site/sass/includes/_main.sass index a73f3d4..63fc9f9 100644 --- a/src/site/sass/main.sass +++ b/src/site/sass/includes/_main.sass @@ -1,14 +1,12 @@ @use "forms" +$theme: () !default + $layout-a-max: 820px $layout-b-min: 821px $layout-c-max: 680px $layout-home-a-max: 520px $layout-home-b-min: 521px -$main-theme-link-color: #085cae -$medium-red-bg: #6a2222 -$light-red-bg: #bd4444 -$solar-background: #fff4e8 @font-face font-family: "Bariol" @@ -53,11 +51,11 @@ body border-color: hsl(104, 51.4%, 43.5%) .top-nav - background-color: $light-red-bg + background-color: map-get($theme, background-power-primary) position: relative z-index: 1 - box-shadow: 0px -2px 4px 4px rgba(0, 0, 0, 0.4) - border-bottom: 1px solid #333 + box-shadow: map-get($theme, "shadow-down") + border-bottom: map-get($theme, "edge-context-divider") padding: 6px 12px justify-content: space-between align-items: center @@ -87,13 +85,13 @@ body line-height: 1 @media screen and (max-width: $layout-a-max) - border-bottom: 1px solid #333 - box-shadow: 0px -2px 4px 4px rgba(0, 0, 0, 0.4) + border-bottom: map-get($theme, "edge-context-divider") + box-shadow: map-get($theme, "shadow-down") padding-bottom: 25px @media screen and (min-width: $layout-b-min) - border-right: 1px solid #333 - box-shadow: -2px 0px 4px 4px rgba(0, 0, 0, 0.4) + border-right: map-get($theme, "edge-context-divider") + box-shadow: map-get($theme, "shadow-right") .profile-sticky position: sticky @@ -109,7 +107,7 @@ body height: unset a, a:visited - color: $main-theme-link-color + color: map-get($theme, "link-primary") .pfp margin: 25px 0 @@ -153,17 +151,14 @@ body .bibliogram-meta margin: 20px 10px - border-top: 1px solid #333 + border-top: map-get($theme, "edge-context-divider") @media screen and (max-width: $layout-a-max) display: none - - .timeline --image-size: 260px $image-size: var(--image-size) - $background: $solar-background @media screen and (max-width: $layout-a-max) --image-size: 150px @@ -172,7 +167,7 @@ body @media screen and (max-width: $layout-c-max) --image-size: calc(33vw - 10px) - background-color: $background + background-color: map-get($theme, "background-primary") padding: 15px 15px 40px &.no-posts @@ -181,7 +176,7 @@ body justify-content: center .page-number - color: #444 + color: map-get($theme, "foreground-timeline-page") line-height: 1 max-width: 600px margin: 0px auto @@ -202,7 +197,7 @@ body position: relative z-index: 1 padding: 10px - background-color: $background + background-color: map-get($theme, "background-primary") .next-page-container margin: 20px 0px @@ -234,8 +229,9 @@ body $margin: 5px margin: $margin - color: #111 - background-color: rgba(40, 40, 40, 0.25) + color: map-get($theme, "foreground-thumbnail-alt") + border: 0px map-get($theme, "edge-thumbnail-hover") + background-color: map-get($theme, "background-timeline-loading") text-decoration: none overflow: hidden @include sized @@ -243,7 +239,7 @@ body &:hover $border-width: 3px margin: $margin - $border-width - border: $border-width solid #111 + border-width: $border-width @media screen and (max-width: $layout-c-max) $margin: 2px @@ -252,13 +248,13 @@ body &:hover $border-width: 2px margin: $margin - $border-width - border: $border-width solid #111 + border-width: $border-width .sized-image @include sized .post-page - background-color: #505156 + background-color: map-get($theme, "background-post-distraction") .post-page-divider display: grid @@ -292,14 +288,14 @@ body align-items: center grid-template-columns: auto 1fr auto justify-content: center - background-color: #b3b3b3 + background-color: map-get($theme, "background-post-header") padding: 10px position: sticky top: 0 - border-bottom: 1px solid #333 + border-bottom: map-get($theme, "edge-context-divider") @media screen and (max-width: $layout-a-max) - box-shadow: 0px -2px 4px 4px rgba(0, 0, 0, 0.4) + box-shadow: map-get($theme, "shadow-down") .navigate-posts -webkit-appearance: none @@ -330,23 +326,23 @@ body width: $size height: $size margin-right: 10px - background-color: rgba(40, 40, 40, 0.25) + background-color: map-get($theme, "background-post-pfp-loading") .name font-size: 20px - color: black + color: map-get($theme, "foreground-timeline-header") text-decoration: none &:hover text-decoration: underline .relative-box - background-color: #eee + background-color: map-get($theme, "background-post-caption") @media screen and (min-width: $layout-b-min) .relative-box position: relative - box-shadow: 0px 6px 4px -4px rgba(0, 0, 0, .4) inset + box-shadow: map-get($theme, "shadow-down-inset") .scrolling-box position: absolute @@ -374,7 +370,7 @@ body flex-direction: column align-items: center justify-content: center - background-color: #262728 + background-color: map-get($theme, "background-post-gallery") padding: 10px @media screen and (max-width: $layout-a-max) @@ -382,8 +378,8 @@ body position: relative .sized-image, .sized-video - color: #eee - background-color: #3b3c3d + color: map-get($theme, "foreground-gallery-alt") + background-color: map-get($theme, "background-post-loading") max-height: 94vh max-width: 100% @@ -401,7 +397,7 @@ body .error-page box-sizing: border-box min-height: 100vh - background: #191919 + background: map-get($theme, "background-error-page") padding: 10px text-align: center display: flex @@ -410,7 +406,7 @@ body align-items: center a, a:visited - color: #4a93d2 + color: map-get($theme, "link-error-page") .code, .message, .explanation, .back-link line-height: 1.2 @@ -418,18 +414,18 @@ body .code font-size: 80px - color: #fff + color: map-get($theme, "foreground-error-code") margin-bottom: 25px .message font-size: 35px - color: #ccc + color: map-get($theme, "foreground-error-message") .explanation line-height: 1.3 margin-top: 10px font-size: 20px - color: #bbb + color: map-get($theme, "foreground-error-explanation") white-space: pre-line .back @@ -437,13 +433,11 @@ body font-size: 25px .homepage - $link-color: #ffb8b8 - display: flex flex-direction: column min-height: 100vh - background-color: $light-red-bg - color: #fff + background-color: map-get($theme, "background-power-primary") + color: map-get($theme, "foreground-power-primary") h1 font-size: 48px @@ -454,7 +448,7 @@ body margin: 0px a, a:visited - color: $link-color + color: map-get($theme, "link-power") .banner padding: 0px 5px @@ -499,7 +493,8 @@ body box-sizing: content-box font-size: 20px height: 20px - border: 1px solid #333 + border: map-get($theme, "edge-go-control") + color: map-get($theme, "foreground-go-control") .text border-radius: 6px 0px 0px 6px @@ -515,15 +510,14 @@ body padding-left: 12px padding-right: 12px cursor: pointer - background-color: #ffbebe - color: #111 + background-color: map-get($theme, "background-power-palest") &:hover - background-color: #ff7c7c + background-color: map-get($theme, "background-power-pale") .about-container - background-color: $medium-red-bg - color: #eee + background-color: map-get($theme, "background-power-secondary") + color: map-get($theme, "foreground-power-secondary") padding: 50px 20px flex: 1 min-height: 60vh @@ -538,18 +532,18 @@ body white-space: nowrap .link-list - color: $link-color + color: map-get($theme, "link-power") .structured-text a, a:visited - color: $main-theme-link-color + color: map-get($theme, "link-primary") text-decoration: none a:link, a:link:visited text-decoration: underline .link-to-hashtag - color: #127722 + color: map-get($theme, "link-hashtag") .privacy-policy max-width: 700px @@ -558,31 +552,31 @@ body padding: 0px 10px 80px font-size: 20px line-height: 1.4 - background-color: #481717 - color: #e2e2e2 + background-color: map-get($theme, "background-power-tertiary") + color: map-get($theme, "foreground-power-tertiary") h1, h2, h3 - color: #f4f4f4 + color: map-get($theme, "foreground-header-privacy") h1 margin: 40px 0px font-size: 48px a, a:visited - color: #ffb8b8 + color: map-get($theme, "link-power") code font-size: 0.8em - background-color: #141414 + background-color: map-get($theme, "background-power-quote") padding: 3px 5px border-radius: 5px - color: #eee + color: map-get($theme, "foreground-power-secondary") .return-home line-height: 1 margin-top: 45px padding-top: 15px - border-top: 1px solid #714141 + border-top: map-get($theme, "edge-power-divider") .post-overlay position: fixed @@ -590,7 +584,7 @@ body left: 0 right: 0 bottom: 0 - background: rgba(0, 0, 0, 0.7) + background: map-get($theme, "background-post-overlay") z-index: 10 overflow-y: scroll @@ -603,69 +597,37 @@ body align-items: center .loading-inner - color: white + color: map-get($theme, "foreground-alert") font-size: 30px line-height: 1 padding: 26px border-radius: 20px - border: 2px solid #aaa + border: map-get($theme, "edge-alert") font-weight: bold - background-color: #282828 - -@mixin article-code - code - font-size: 0.8em - letter-spacing: -0.2px - background: #ccc - color: #000 - padding: 0px 4px - border-radius: 2px - -.updater-page - @include article-code - - font-size: 20px - max-width: 800px - margin: 0 auto - color: #222 - - .commits - border-left: 2px solid #555 - margin: 10px 0px - padding-left: 10px - - .hash - margin-right: 6px - - .attention - border-left: 2px solid - padding-left: 8px - color: #700 + background-color: map-get($theme, "background-alert") .article-page - @include article-code - - background-color: #fff4e8 + background-color: map-get($theme, "background-primary") font-size: 22px line-height: 1.4 - color: #222 + color: map-get($theme, "foreground-primary") min-height: 100vh - header - background-color: $medium-red-bg - color: #fff - padding: 40px 10px - line-height: 1.2 - - h1, h2 + h1 text-align: center margin: 0 - - h1 font-size: 50px h2 - font-size: 30px + font-size: 34px + margin: 0 + color: map-get($theme, "foreground-header") + + header + background-color: map-get($theme, "background-power-secondary") + color: map-get($theme, "foreground-power-primary") + padding: 40px 10px + line-height: 1.2 .article-main max-width: 800px @@ -673,13 +635,25 @@ body padding: 20px 20px 100px a, a:visited - color: $main-theme-link-color + color: map-get($theme, "link-primary") + + code + font-size: 0.8em + letter-spacing: -0.2px + background: map-get($theme, "background-primary-quote") + color: map-get($theme, "foreground-primary-quote") + padding: 0px 4px + border-radius: 2px .settings-page - background-color: #fff4e8 + background-color: map-get($theme, "background-primary") + color: map-get($theme, "foreground-primary") + + h1, legend + color: map-get($theme, "foreground-header") a, a:visited - color: $main-theme-link-color + color: map-get($theme, "link-primary") .settings padding: 0px 10px 50px @@ -691,8 +665,8 @@ body font-size: 24px line-height: 1 text-align: center - background-color: #0b420b - color: #fff + background-color: map-get($theme, "background-banner-success") + color: map-get($theme, "foreground-banner") .action-container margin-top: 20px @@ -701,8 +675,11 @@ body align-items: center .save-button - @include forms.curve-out-major + padding: 12px width: 180px + &:not(:active) + @include forms.curve-out-major + .home-link font-size: 21px diff --git a/src/site/sass/themes/_blue.scss b/src/site/sass/themes/_blue.scss new file mode 100644 index 0000000..072ddd1 --- /dev/null +++ b/src/site/sass/themes/_blue.scss @@ -0,0 +1,16 @@ +// Defined in scss file instead of sass because indented syntax does not have multiline maps +// This is based on the classic theme, so it pulls that in as the base and then overwrites only the properties it cares about +// This also makes it future-proof because future additions to classic will be automatically available in this style too + +@use "classic"; + +$theme: map-merge(classic.$theme, ( + "background-power-primary": #3e73b7, + "background-power-secondary": #274771, + "background-power-tertiary": #1b233c, + "background-power-palest": #bee5ff, + "background-power-pale": #7cc4ff, + "background-banner-success": #173d6f, + "link-power": #91cbfd, + "edge-power-divider": 1px solid #3b496a +)); diff --git a/src/site/sass/themes/_classic.scss b/src/site/sass/themes/_classic.scss new file mode 100644 index 0000000..1ebce91 --- /dev/null +++ b/src/site/sass/themes/_classic.scss @@ -0,0 +1,54 @@ +// Defined in scss file instead of sass because indented syntax does not have multiline maps +// https://github.com/sass/sass/issues/216 + +$theme: ( + "background-primary": #fff4e8, + "background-timeline-profile": #fff, + "background-timeline-loading": #c9c1b8, + "background-post-distraction": #505156, + "background-post-overlay": rgba(0, 0, 0, 0.7), + "background-post-header": #b3b3b3, + "background-post-pfp-loading": #999, + "background-post-caption": #eee, + "background-post-gallery": #262728, + "background-post-loading": #3b3c3d, + "background-power-primary": #bd4444, + "background-power-secondary": #6a2222, + "background-power-tertiary": #481717, + "background-power-palest": #ffbebe, + "background-power-pale": #ff7c7c, + "background-power-quote": #191919, + "background-primary-quote": #ccc, + "background-error-page": #191919, + "background-alert": #282828, + "background-banner-success": #0b420b, + "foreground-primary": #222, + "foreground-header": #000, + "foreground-power-primary": #fff, + "foreground-power-secondary": #eee, + "foreground-power-tertiary": #e2e2e2, + "foreground-go-control": #111, + "foreground-thumbnail-alt": #111, + "foreground-timeline-page": #444, + "foreground-timeline-header": #000, + "foreground-gallery-alt": #eee, + "foreground-error-code": #fff, + "foreground-error-message": #ccc, + "foreground-error-explanation": #bbb, + "foreground-header-privacy": #f4f4f4, + "foreground-alert": #eee, + "foreground-primary-quote": #000, + "foreground-banner": #fff, + "link-primary": #085cae, + "link-power": #ffb8b8, + "link-error-page": #4a93d2, + "link-hashtag": #127722, + "edge-context-divider": 1px solid #333, + "edge-thumbnail-hover": solid #111, + "edge-go-control": 1px solid #333, + "edge-power-divider": 1px solid #714141, + "edge-alert": 2px solid #aaa, + "shadow-down": 0px -2px 4px 4px rgba(0, 0, 0, 0.4), + "shadow-right": -2px 0px 4px 4px rgba(0, 0, 0, 0.4), + "shadow-down-inset": 0px 6px 4px -4px rgba(0, 0, 0, 0.4) inset, +); diff --git a/src/site/server.js b/src/site/server.js index 5ca7294..ca69801 100644 --- a/src/site/server.js +++ b/src/site/server.js @@ -21,10 +21,11 @@ subdirs("pug", async (err, dirs) => { await require("../lib/utils/upgradedb")() pinski.setNotFoundTarget("/404") - pinski.addRoute("/static/css/main.css", "sass/main.sass", "sass") + pinski.addRoute("/static/css/classic.css", "sass/classic.sass", "sass") + pinski.addRoute("/static/css/blue.css", "sass/blue.sass", "sass") pinski.addRoute("/settings", "pug/settings.pug", "pug") pinski.addPugDir("pug", dirs) - pinski.addSassDir("sass") + pinski.addSassDir("sass", ["sass/includes", "sass/themes"]) pinski.addStaticHashTableDir("html/static/js") pinski.muteLogsStartingWith("/imageproxy") pinski.muteLogsStartingWith("/videoproxy")