From a339ff93b12f959bc97111d707da1608316deb1a Mon Sep 17 00:00:00 2001 From: Cassio Zen Date: Wed, 9 Nov 2022 12:15:22 -0600 Subject: [PATCH 1/3] Minor styling tweaks: piccalil.li's modern CSS Reset swyx.io's 100 Bytes of CSS to look great everywhere --- app/scss/main.scss | 365 +++++++++++++++++++++++++-------------------- 1 file changed, 200 insertions(+), 165 deletions(-) diff --git a/app/scss/main.scss b/app/scss/main.scss index dc99b1c..4a14c33 100644 --- a/app/scss/main.scss +++ b/app/scss/main.scss @@ -1,9 +1,11 @@ -$font-stack: Helvetica, sans-serif; +$font-stack: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, + Ubuntu, roboto, noto, arial, sans-serif; + $background: #ddd; $light-background: #e6e6e6; $text-color: #111; $primary-color: #1d781d; -$secondary-color: #781D78; +$secondary-color: #781d78; $form-background-color: #ccc; $form-text-color: #333; $muted-color: #555; // solarized comment text @@ -13,6 +15,46 @@ $code-highlight-background: #f0f0f0; // Load custom theme @import "theme.scss"; +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Set core root defaults */ +html:focus-within { + scroll-behavior: smooth; +} + +/* Inherit fonts for inputs and buttons */ +input, +button, +textarea, +select { + font: inherit; +} + +html { + max-width: 90ch; + padding: 3em 1em; + margin: auto; + line-height: 1.75; + font-size: 1.25em; +} + +body { + font-family: $font-stack; + background: $background; + color: $text-color; + display: flex; + min-height: 100vh; + flex-direction: column; +} +a { + text-decoration: none; +} + .primary-color { color: $primary-color; } @@ -70,7 +112,7 @@ $code-highlight-background: #f0f0f0; display: none; } .sensitive-attachment-state:checked ~ .sensitive-attachment-box div { - display:none; + display: none; } .sensitive-attachment-box { position: relative; @@ -84,7 +126,6 @@ $code-highlight-background: #f0f0f0; } } - blockquote { border-left: 3px solid $secondary-color; margin-left: 0; @@ -92,28 +133,11 @@ blockquote { } .muted { - color: $muted-color; + color: $muted-color; } .light-background { - background: $light-background; -} - - -body { - font-family: $font-stack; - font-size: 20px; - line-height: 32px; - background: $background; - color: $text-color; - margin: 0; - padding: 0; - display: flex; - min-height: 100vh; - flex-direction: column; -} -a { - text-decoration: none; + background: $light-background; } dl { @@ -137,53 +161,56 @@ dl { } .shared-header { - margin-left: 20px; - margin-top: 30px; - margin-bottom: -20px; - strong { - color: $primary-color; - } - span { - color: $muted-color; - } + margin-left: 20px; + margin-top: 30px; + margin-bottom: -20px; + strong { + color: $primary-color; + } + span { + color: $muted-color; + } } div.highlight { - background: $code-highlight-background; - padding: 0 10px; - overflow: auto; - display: block; - margin: 20px 0; + background: $code-highlight-background; + padding: 0 10px; + overflow: auto; + display: block; + margin: 20px 0; } .box { - padding: 0 20px; + padding: 0 20px; } -code, pre { +code, +pre { color: $secondary-color; // #cb4b16; // #268bd2; // #2aa198; font-family: monospace; } .form { - input, select, textarea { - font-size: 20px; - border: 0; - padding: 5px; - background: $form-background-color; - color: $form-text-color; - &:focus { - outline: 1px solid $secondary-color; - } - } - input[type=submit] { - font-size: 20px; - outline: none; - background: $primary-color; - color: $primary-button-text-color; - padding: 5px 12px; - cursor: pointer; + input, + select, + textarea { + font-size: 20px; + border: 0; + padding: 5px; + background: $form-background-color; + color: $form-text-color; + &:focus { + outline: 1px solid $secondary-color; } + } + input[type="submit"] { + font-size: 20px; + outline: none; + background: $primary-color; + color: $primary-button-text-color; + padding: 5px 12px; + cursor: pointer; + } } header { @@ -212,18 +239,17 @@ a { } } #main { - display: flex; - flex: 1; + display: flex; + flex: 1; } main { - width: 100%; - max-width: 1000px; - margin: 30px auto; + width: 100%; + margin: 30px auto; } .main-flex { - display: flex; - flex: 1; + display: flex; + flex: 1; } .centered { @@ -237,12 +263,12 @@ main { } footer { + font-size: 1em; width: 100%; - max-width: 1000px; margin: 20px auto; color: $muted-color; p { - margin: 0; + margin: 0; } } .tiny-actor-icon { @@ -254,7 +280,7 @@ footer { .actor-box { display: flex; column-gap: 20px; - margin:10px 0; + margin: 10px 0; .icon-box { flex: 0 0 50px; } @@ -268,50 +294,54 @@ footer { } } #articles { - list-style-type: none; - margin: 30px 0; - padding: 0 20px; - li { - display: block; - span { - padding-right:10px; - } + list-style-type: none; + margin: 30px 0; + padding: 0 20px; + li { + display: block; + span { + padding-right: 10px; } + } } -#notifications, #followers, #following { - ul { - list-style-type: none; - margin: 0; - padding: 0; - } - li { - display: block; - } +#notifications, +#followers, +#following { + ul { + list-style-type: none; + margin: 0; + padding: 0; + } + li { + display: block; + } } @mixin admin-button() { - font-size: 20px; - line-height: 32px; - font-family: $font-stack; - background: $form-background-color; - color: $form-text-color; - border: 1px solid $background; - padding: 8px 10px 5px 10px; - cursor: pointer; - &:hover { - border: 1px solid $form-text-color; - } + font-size: 20px; + line-height: 32px; + font-family: $font-stack; + background: $form-background-color; + color: $form-text-color; + border: 1px solid $background; + padding: 8px 10px 5px 10px; + cursor: pointer; + &:hover { + border: 1px solid $form-text-color; + } } -.show-sensitive-btn, .show-more-btn, .label-btn { - @include admin-button; - padding: 10px 5px; - margin: 20px 0; +.show-sensitive-btn, +.show-more-btn, +.label-btn { + @include admin-button; + padding: 10px 5px; + margin: 20px 0; } .show-hide-sensitive-btn { - display:inline-block; + display: inline-block; } .no-margin-top { @@ -335,13 +365,13 @@ ul.poll-items { } .poll-bar { - width:100%;height:20px; - line { - stroke: $secondary-color; - stroke-width: 20px; - } + width: 100%; + height: 20px; + line { + stroke: $secondary-color; + stroke-width: 20px; + } } - } } @@ -362,44 +392,45 @@ ul.poll-items { } nav { - form { - margin: 15px 0; - } - input[type=submit], button { - @include admin-button; - } + form { + margin: 15px 0; + } + input[type="submit"], + button { + @include admin-button; + } } nav.flexbox { - ul { - display: flex; - flex-wrap: wrap; - align-items: center; - list-style-type: none; - margin: 0; - padding: 0; + ul { + display: flex; + flex-wrap: wrap; + align-items: center; + list-style-type: none; + margin: 0; + padding: 0; + } - } + ul li { + margin-right: 20px; - ul li { - margin-right: 20px; - - &:last-child { - margin-right: 0px; - } + &:last-child { + margin-right: 0px; } - a:not(.label-btn) { - color: $primary-color; - text-decoration: none; - &:hover, &:active { - color: $secondary-color; - text-decoration: underline; - } - } - a.active:not(.label-btn) { - color: $secondary-color; - font-weight: bold; + } + a:not(.label-btn) { + color: $primary-color; + text-decoration: none; + &:hover, + &:active { + color: $secondary-color; + text-decoration: underline; } + } + a.active:not(.label-btn) { + color: $secondary-color; + font-weight: bold; + } } // after nav.flexbox to override default behavior @@ -412,31 +443,34 @@ a.label-btn { } .ap-object { - margin: 15px 0; - padding: 20px; - nav { - color: $muted-color; + margin: 15px 0; + padding: 20px; + nav { + color: $muted-color; + } + .in-reply-to { + display: inline; + color: $muted-color; + } + .e-content, + .activity-og-meta { + a:hover { + text-decoration: underline; } - .in-reply-to { - display: inline; - color: $muted-color; - } - .e-content, .activity-og-meta { - a:hover { - text-decoration: underline; - } - } - .activity-attachment { - margin: 30px 0 20px 0; - img, audio, video { - width: 100%; - max-width: 740px; - } - } - img.inline-img { - display: block; - max-width: 740px; + } + .activity-attachment { + margin: 30px 0 20px 0; + img, + audio, + video { + width: 100%; + max-width: 740px; } + } + img.inline-img { + display: block; + max-width: 740px; + } } .activity-og-meta { @@ -453,25 +487,26 @@ a.label-btn { } .ap-object-expanded { - border: 2px dashed $secondary-color; + border: 2px dashed $secondary-color; } .error-box { - color: $secondary-color; + color: $secondary-color; } .actor-action { - margin-top:20px; - margin-bottom:-20px; + margin-top: 20px; + margin-bottom: -20px; padding: 0 20px; span { color: $muted-color; } } .actor-metadata { - color: $muted-color; + color: $muted-color; } -.emoji, .custom-emoji { +.emoji, +.custom-emoji { max-width: 25px; } From 62c9327500e3ff47c34acf8098e5d1f5138208b7 Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Wed, 9 Nov 2022 21:26:43 +0100 Subject: [PATCH 2/3] Add support for setting a custom CSP --- app/config.py | 3 +++ app/main.py | 12 +++++++++--- docs/user_guide.md | 12 +++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/config.py b/app/config.py index 27e7ffb..36ff073 100644 --- a/app/config.py +++ b/app/config.py @@ -109,6 +109,8 @@ class Config(pydantic.BaseModel): inbox_retention_days: int = 15 + custom_content_security_policy: str | None = None + # Config items to make tests easier sqlalchemy_database: str | None = None key_path: str | None = None @@ -165,6 +167,7 @@ if CONFIG.privacy_replace: BLOCKED_SERVERS = {blocked_server.hostname for blocked_server in CONFIG.blocked_servers} ALSO_KNOWN_AS = CONFIG.also_known_as +CUSTOM_CONTENT_SECURITY_POLICY = CONFIG.custom_content_security_policy INBOX_RETENTION_DAYS = CONFIG.inbox_retention_days CUSTOM_FOOTER = ( diff --git a/app/main.py b/app/main.py index 0829167..37e1ab8 100644 --- a/app/main.py +++ b/app/main.py @@ -137,9 +137,15 @@ class CustomMiddleware: headers["x-frame-options"] = "DENY" headers["permissions-policy"] = "interest-cohort=()" headers["content-security-policy"] = ( - f"default-src 'self'; " - f"style-src 'self' 'sha256-{HIGHLIGHT_CSS_HASH}'; " - f"frame-ancestors 'none'; base-uri 'self'; form-action 'self';" + ( + f"default-src 'self'; " + f"style-src 'self' 'sha256-{HIGHLIGHT_CSS_HASH}'; " + f"frame-ancestors 'none'; base-uri 'self'; form-action 'self';" + ) + if not config.CUSTOM_CONTENT_SECURITY_POLICY + else config.CUSTOM_CONTENT_SECURITY_POLICY.format( + HIGHLIGHT_CSS_HASH=HIGHLIGHT_CSS_HASH + ) ) if not DEBUG: headers["strict-transport-security"] = "max-age=63072000;" diff --git a/docs/user_guide.md b/docs/user_guide.md index 578bf08..51ad9c1 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -131,9 +131,19 @@ See `app/scss/main.scss` to see what variables can be overridden. If you'd like to customize your instance's theme beyond CSS, you can modify the app's HTML by placing templates in `data/templates` which overwrite the defaults in `app/templates`. +#### Custom Content Security Policy (CSP) + +You can override the default Content Security Policy by adding a line in `data/profile.toml`: + +```toml +custom_content_security_policy = "default-src 'self'; style-src 'self' 'sha256-{HIGHLIGHT_CSS_HASH}'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" +``` + +This example will output the default CSP, note that `{HIGHLIGHT_CSS_HASH}` will be dynamically replaced by the correct value (the hash of the CSS needed for syntax highlighting). + #### Code highlighting theme -You can switch to one of the [styles supported by Pygments](https://pygments.org/styles/) by adding a line in `profile.toml`: +You can switch to one of the [styles supported by Pygments](https://pygments.org/styles/) by adding a line in `data/profile.toml`: ```toml code_highlighting_theme = "solarized-dark" From 5c98b8dbfb1ea5f00c5ec507543ec10fc47baa3e Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Fri, 11 Nov 2022 15:07:18 +0100 Subject: [PATCH 3/3] Revert "Minor styling tweaks: piccalil.li's modern CSS Reset swyx.io's 100 Bytes of CSS to look great everywhere" This reverts commit a339ff93b12f959bc97111d707da1608316deb1a. --- app/scss/main.scss | 365 ++++++++++++++++++++------------------------- 1 file changed, 165 insertions(+), 200 deletions(-) diff --git a/app/scss/main.scss b/app/scss/main.scss index 4a14c33..dc99b1c 100644 --- a/app/scss/main.scss +++ b/app/scss/main.scss @@ -1,11 +1,9 @@ -$font-stack: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, - Ubuntu, roboto, noto, arial, sans-serif; - +$font-stack: Helvetica, sans-serif; $background: #ddd; $light-background: #e6e6e6; $text-color: #111; $primary-color: #1d781d; -$secondary-color: #781d78; +$secondary-color: #781D78; $form-background-color: #ccc; $form-text-color: #333; $muted-color: #555; // solarized comment text @@ -15,46 +13,6 @@ $code-highlight-background: #f0f0f0; // Load custom theme @import "theme.scss"; -/* Box sizing rules */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -/* Set core root defaults */ -html:focus-within { - scroll-behavior: smooth; -} - -/* Inherit fonts for inputs and buttons */ -input, -button, -textarea, -select { - font: inherit; -} - -html { - max-width: 90ch; - padding: 3em 1em; - margin: auto; - line-height: 1.75; - font-size: 1.25em; -} - -body { - font-family: $font-stack; - background: $background; - color: $text-color; - display: flex; - min-height: 100vh; - flex-direction: column; -} -a { - text-decoration: none; -} - .primary-color { color: $primary-color; } @@ -112,7 +70,7 @@ a { display: none; } .sensitive-attachment-state:checked ~ .sensitive-attachment-box div { - display: none; + display:none; } .sensitive-attachment-box { position: relative; @@ -126,6 +84,7 @@ a { } } + blockquote { border-left: 3px solid $secondary-color; margin-left: 0; @@ -133,11 +92,28 @@ blockquote { } .muted { - color: $muted-color; + color: $muted-color; } .light-background { - background: $light-background; + background: $light-background; +} + + +body { + font-family: $font-stack; + font-size: 20px; + line-height: 32px; + background: $background; + color: $text-color; + margin: 0; + padding: 0; + display: flex; + min-height: 100vh; + flex-direction: column; +} +a { + text-decoration: none; } dl { @@ -161,56 +137,53 @@ dl { } .shared-header { - margin-left: 20px; - margin-top: 30px; - margin-bottom: -20px; - strong { - color: $primary-color; - } - span { - color: $muted-color; - } + margin-left: 20px; + margin-top: 30px; + margin-bottom: -20px; + strong { + color: $primary-color; + } + span { + color: $muted-color; + } } div.highlight { - background: $code-highlight-background; - padding: 0 10px; - overflow: auto; - display: block; - margin: 20px 0; + background: $code-highlight-background; + padding: 0 10px; + overflow: auto; + display: block; + margin: 20px 0; } .box { - padding: 0 20px; + padding: 0 20px; } -code, -pre { +code, pre { color: $secondary-color; // #cb4b16; // #268bd2; // #2aa198; font-family: monospace; } .form { - input, - select, - textarea { - font-size: 20px; - border: 0; - padding: 5px; - background: $form-background-color; - color: $form-text-color; - &:focus { - outline: 1px solid $secondary-color; + input, select, textarea { + font-size: 20px; + border: 0; + padding: 5px; + background: $form-background-color; + color: $form-text-color; + &:focus { + outline: 1px solid $secondary-color; + } + } + input[type=submit] { + font-size: 20px; + outline: none; + background: $primary-color; + color: $primary-button-text-color; + padding: 5px 12px; + cursor: pointer; } - } - input[type="submit"] { - font-size: 20px; - outline: none; - background: $primary-color; - color: $primary-button-text-color; - padding: 5px 12px; - cursor: pointer; - } } header { @@ -239,17 +212,18 @@ a { } } #main { - display: flex; - flex: 1; + display: flex; + flex: 1; } main { - width: 100%; - margin: 30px auto; + width: 100%; + max-width: 1000px; + margin: 30px auto; } .main-flex { - display: flex; - flex: 1; + display: flex; + flex: 1; } .centered { @@ -263,12 +237,12 @@ main { } footer { - font-size: 1em; width: 100%; + max-width: 1000px; margin: 20px auto; color: $muted-color; p { - margin: 0; + margin: 0; } } .tiny-actor-icon { @@ -280,7 +254,7 @@ footer { .actor-box { display: flex; column-gap: 20px; - margin: 10px 0; + margin:10px 0; .icon-box { flex: 0 0 50px; } @@ -294,54 +268,50 @@ footer { } } #articles { - list-style-type: none; - margin: 30px 0; - padding: 0 20px; - li { - display: block; - span { - padding-right: 10px; + list-style-type: none; + margin: 30px 0; + padding: 0 20px; + li { + display: block; + span { + padding-right:10px; + } } - } } -#notifications, -#followers, -#following { - ul { - list-style-type: none; - margin: 0; - padding: 0; - } - li { - display: block; - } +#notifications, #followers, #following { + ul { + list-style-type: none; + margin: 0; + padding: 0; + } + li { + display: block; + } } @mixin admin-button() { - font-size: 20px; - line-height: 32px; - font-family: $font-stack; - background: $form-background-color; - color: $form-text-color; - border: 1px solid $background; - padding: 8px 10px 5px 10px; - cursor: pointer; - &:hover { - border: 1px solid $form-text-color; - } + font-size: 20px; + line-height: 32px; + font-family: $font-stack; + background: $form-background-color; + color: $form-text-color; + border: 1px solid $background; + padding: 8px 10px 5px 10px; + cursor: pointer; + &:hover { + border: 1px solid $form-text-color; + } } -.show-sensitive-btn, -.show-more-btn, -.label-btn { - @include admin-button; - padding: 10px 5px; - margin: 20px 0; +.show-sensitive-btn, .show-more-btn, .label-btn { + @include admin-button; + padding: 10px 5px; + margin: 20px 0; } .show-hide-sensitive-btn { - display: inline-block; + display:inline-block; } .no-margin-top { @@ -365,13 +335,13 @@ ul.poll-items { } .poll-bar { - width: 100%; - height: 20px; - line { - stroke: $secondary-color; - stroke-width: 20px; - } + width:100%;height:20px; + line { + stroke: $secondary-color; + stroke-width: 20px; + } } + } } @@ -392,45 +362,44 @@ ul.poll-items { } nav { - form { - margin: 15px 0; - } - input[type="submit"], - button { - @include admin-button; - } + form { + margin: 15px 0; + } + input[type=submit], button { + @include admin-button; + } } nav.flexbox { - ul { - display: flex; - flex-wrap: wrap; - align-items: center; - list-style-type: none; - margin: 0; - padding: 0; - } + ul { + display: flex; + flex-wrap: wrap; + align-items: center; + list-style-type: none; + margin: 0; + padding: 0; - ul li { - margin-right: 20px; + } - &:last-child { - margin-right: 0px; + ul li { + margin-right: 20px; + + &:last-child { + margin-right: 0px; + } } - } - a:not(.label-btn) { - color: $primary-color; - text-decoration: none; - &:hover, - &:active { - color: $secondary-color; - text-decoration: underline; + a:not(.label-btn) { + color: $primary-color; + text-decoration: none; + &:hover, &:active { + color: $secondary-color; + text-decoration: underline; + } + } + a.active:not(.label-btn) { + color: $secondary-color; + font-weight: bold; } - } - a.active:not(.label-btn) { - color: $secondary-color; - font-weight: bold; - } } // after nav.flexbox to override default behavior @@ -443,34 +412,31 @@ a.label-btn { } .ap-object { - margin: 15px 0; - padding: 20px; - nav { - color: $muted-color; - } - .in-reply-to { - display: inline; - color: $muted-color; - } - .e-content, - .activity-og-meta { - a:hover { - text-decoration: underline; + margin: 15px 0; + padding: 20px; + nav { + color: $muted-color; } - } - .activity-attachment { - margin: 30px 0 20px 0; - img, - audio, - video { - width: 100%; - max-width: 740px; + .in-reply-to { + display: inline; + color: $muted-color; + } + .e-content, .activity-og-meta { + a:hover { + text-decoration: underline; + } + } + .activity-attachment { + margin: 30px 0 20px 0; + img, audio, video { + width: 100%; + max-width: 740px; + } + } + img.inline-img { + display: block; + max-width: 740px; } - } - img.inline-img { - display: block; - max-width: 740px; - } } .activity-og-meta { @@ -487,26 +453,25 @@ a.label-btn { } .ap-object-expanded { - border: 2px dashed $secondary-color; + border: 2px dashed $secondary-color; } .error-box { - color: $secondary-color; + color: $secondary-color; } .actor-action { - margin-top: 20px; - margin-bottom: -20px; + margin-top:20px; + margin-bottom:-20px; padding: 0 20px; span { color: $muted-color; } } .actor-metadata { - color: $muted-color; + color: $muted-color; } -.emoji, -.custom-emoji { +.emoji, .custom-emoji { max-width: 25px; }