From 65f960c31a734b5306a8b919040c3aae9b783efd Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Sat, 16 Nov 2024 22:49:55 +0800 Subject: [PATCH 1/7] perf: speed up page rendering and jekyll build process (#2034) - Ensure inline scripts execute after the DOM has fully loaded. - Use Rollup to bundle the theme-mode and Mermaid scripts, reducing the number of Jekyll include snippets. --- _includes/analytics/cloudflare.html | 1 - _includes/analytics/fathom.html | 5 +- _includes/analytics/google.html | 2 +- _includes/analytics/matomo.html | 13 +- _includes/{comments.html => comment.html} | 0 _includes/comments/disqus.html | 63 ++++---- _includes/comments/giscus.html | 44 ++---- _includes/comments/utterances.html | 65 ++++----- _includes/head.html | 25 +++- _includes/js-selector.html | 29 +--- _includes/jsdelivr-combine.html | 8 +- _includes/mermaid.html | 62 -------- _includes/mode-toggle.html | 116 --------------- _includes/search-loader.html | 42 +++--- _javascript/categories.js | 2 +- _javascript/home.js | 2 +- _javascript/misc.js | 2 +- .../modules/{plugins.js => components.js} | 4 + _javascript/modules/components/img-popup.js | 16 +-- _javascript/modules/components/mermaid.js | 60 ++++++++ _javascript/modules/components/mode-toggle.js | 15 ++ .../modules/components/mode-watcher.js | 14 -- _javascript/modules/components/sidebar.js | 22 --- _javascript/modules/layouts/basic.js | 4 +- _javascript/modules/layouts/sidebar.js | 20 ++- _javascript/modules/theme.js | 135 ++++++++++++++++++ _javascript/page.js | 8 +- _javascript/post.js | 6 +- _layouts/default.html | 8 +- _layouts/post.html | 3 +- _sass/layout/post.scss | 1 + package.json | 1 + rollup.config.js | 19 ++- 33 files changed, 410 insertions(+), 407 deletions(-) rename _includes/{comments.html => comment.html} (100%) delete mode 100644 _includes/mermaid.html delete mode 100644 _includes/mode-toggle.html rename _javascript/modules/{plugins.js => components.js} (60%) create mode 100644 _javascript/modules/components/mermaid.js create mode 100644 _javascript/modules/components/mode-toggle.js delete mode 100644 _javascript/modules/components/mode-watcher.js delete mode 100644 _javascript/modules/components/sidebar.js create mode 100644 _javascript/modules/theme.js diff --git a/_includes/analytics/cloudflare.html b/_includes/analytics/cloudflare.html index 1eeb1a9..9faa11e 100644 --- a/_includes/analytics/cloudflare.html +++ b/_includes/analytics/cloudflare.html @@ -4,4 +4,3 @@ src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token": "{{ site.analytics.cloudflare.id }}"}' > - diff --git a/_includes/analytics/fathom.html b/_includes/analytics/fathom.html index 4b603d3..216bb14 100644 --- a/_includes/analytics/fathom.html +++ b/_includes/analytics/fathom.html @@ -2,6 +2,5 @@ - + defer +> diff --git a/_includes/analytics/google.html b/_includes/analytics/google.html index d0aac65..dfe4828 100644 --- a/_includes/analytics/google.html +++ b/_includes/analytics/google.html @@ -1,7 +1,7 @@ - diff --git a/_includes/comments.html b/_includes/comment.html similarity index 100% rename from _includes/comments.html rename to _includes/comment.html diff --git a/_includes/comments/disqus.html b/_includes/comments/disqus.html index 2b889a4..fd12a3c 100644 --- a/_includes/comments/disqus.html +++ b/_includes/comments/disqus.html @@ -1,38 +1,25 @@ - - -
-

Comments powered by Disqus.

-
- - diff --git a/_includes/comments/giscus.html b/_includes/comments/giscus.html index f9becfe..8058472 100644 --- a/_includes/comments/giscus.html +++ b/_includes/comments/giscus.html @@ -1,21 +1,8 @@ - - - diff --git a/_includes/head.html b/_includes/head.html index af3acdb..310f52e 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -97,11 +97,32 @@ {% endif %} - + {% unless site.theme_mode %} - {% include mode-toggle.html %} + {% endunless %} + {% include js-selector.html lang=lang %} + + {% if jekyll.environment == 'production' %} + + {% if site.pwa.enabled %} + + {% endif %} + + + {% for analytics in site.analytics %} + {% capture str %}{{ analytics }}{% endcapture %} + {% assign platform = str | split: '{' | first %} + {% if site.analytics[platform].id and site.analytics[platform].id != empty %} + {% include analytics/{{ platform }}.html %} + {% endif %} + {% endfor %} + {% endif %} + {% include metadata-hook.html %} diff --git a/_includes/js-selector.html b/_includes/js-selector.html index 4d77d06..fd4acca 100644 --- a/_includes/js-selector.html +++ b/_includes/js-selector.html @@ -62,12 +62,12 @@ {% capture script %}/assets/js/dist/{{ js }}.min.js{% endcapture %} - + {% if page.math %} - - + + {% endif %} @@ -84,26 +84,3 @@ {% endcase %} {% endif %} {% endif %} - -{% if page.mermaid %} - {% include mermaid.html %} -{% endif %} - -{% if jekyll.environment == 'production' %} - - {% if site.pwa.enabled %} - - {% endif %} - - - {% for analytics in site.analytics %} - {% capture str %}{{ analytics }}{% endcapture %} - {% assign type = str | split: '{' | first %} - {% if site.analytics[type].id and site.analytics[type].id != empty %} - {% include analytics/{{ type }}.html %} - {% endif %} - {% endfor %} -{% endif %} diff --git a/_includes/jsdelivr-combine.html b/_includes/jsdelivr-combine.html index cffa699..0611213 100644 --- a/_includes/jsdelivr-combine.html +++ b/_includes/jsdelivr-combine.html @@ -1,6 +1,6 @@ {% assign urls = include.urls | split: ',' %} -{% assign combined_urls = nil %} +{% assign combined_urls = null %} {% assign domain = 'https://cdn.jsdelivr.net/' %} @@ -15,12 +15,12 @@ {% endif %} {% elsif url contains '//' %} - + {% else %} - + {% endif %} {% endfor %} {% if combined_urls %} - + {% endif %} diff --git a/_includes/mermaid.html b/_includes/mermaid.html deleted file mode 100644 index a3a83ed..0000000 --- a/_includes/mermaid.html +++ /dev/null @@ -1,62 +0,0 @@ - - diff --git a/_includes/mode-toggle.html b/_includes/mode-toggle.html deleted file mode 100644 index 113ec37..0000000 --- a/_includes/mode-toggle.html +++ /dev/null @@ -1,116 +0,0 @@ - - - diff --git a/_includes/search-loader.html b/_includes/search-loader.html index 2582580..7fd065d 100644 --- a/_includes/search-loader.html +++ b/_includes/search-loader.html @@ -19,29 +19,31 @@ {% capture not_found %}

{{ site.data.locales[include.lang].search.no_results }}

{% endcapture %} diff --git a/_javascript/categories.js b/_javascript/categories.js index 15d8251..ce87d67 100644 --- a/_javascript/categories.js +++ b/_javascript/categories.js @@ -1,5 +1,5 @@ import { basic, initSidebar, initTopbar } from './modules/layouts'; -import { categoryCollapse } from './modules/plugins'; +import { categoryCollapse } from './modules/components'; basic(); initSidebar(); diff --git a/_javascript/home.js b/_javascript/home.js index ef22cb9..7f628a1 100644 --- a/_javascript/home.js +++ b/_javascript/home.js @@ -1,5 +1,5 @@ import { basic, initSidebar, initTopbar } from './modules/layouts'; -import { initLocaleDatetime, loadImg } from './modules/plugins'; +import { initLocaleDatetime, loadImg } from './modules/components'; loadImg(); initLocaleDatetime(); diff --git a/_javascript/misc.js b/_javascript/misc.js index 52b4043..37130da 100644 --- a/_javascript/misc.js +++ b/_javascript/misc.js @@ -1,5 +1,5 @@ import { basic, initSidebar, initTopbar } from './modules/layouts'; -import { initLocaleDatetime } from './modules/plugins'; +import { initLocaleDatetime } from './modules/components'; initSidebar(); initTopbar(); diff --git a/_javascript/modules/plugins.js b/_javascript/modules/components.js similarity index 60% rename from _javascript/modules/plugins.js rename to _javascript/modules/components.js index cc95c1b..95791a6 100644 --- a/_javascript/modules/plugins.js +++ b/_javascript/modules/components.js @@ -4,3 +4,7 @@ export { loadImg } from './components/img-loading'; export { imgPopup } from './components/img-popup'; export { initLocaleDatetime } from './components/locale-datetime'; export { initToc } from './components/toc'; +export { loadMermaid } from './components/mermaid'; +export { modeWatcher } from './components/mode-toggle'; +export { back2top } from './components/back-to-top'; +export { loadTooptip } from './components/tooltip-loader'; diff --git a/_javascript/modules/components/img-popup.js b/_javascript/modules/components/img-popup.js index ac12043..420a226 100644 --- a/_javascript/modules/components/img-popup.js +++ b/_javascript/modules/components/img-popup.js @@ -4,7 +4,6 @@ * Dependencies: https://github.com/biati-digital/glightbox */ -const html = document.documentElement; const lightImages = '.popup:not(.dark)'; const darkImages = '.popup:not(.light)'; let selector = lightImages; @@ -33,26 +32,17 @@ export function imgPopup() { document.querySelector('.popup.dark') === null ); - if ( - (html.hasAttribute('data-mode') && - html.getAttribute('data-mode') === 'dark') || - (!html.hasAttribute('data-mode') && - window.matchMedia('(prefers-color-scheme: dark)').matches) - ) { + if (Theme.visualState === Theme.DARK) { selector = darkImages; } let current = GLightbox({ selector: `${selector}` }); - if (hasDualImages && document.getElementById('mode-toggle')) { + if (hasDualImages && Theme.switchable) { let reverse = null; window.addEventListener('message', (event) => { - if ( - event.source === window && - event.data && - event.data.direction === ModeToggle.ID - ) { + if (event.source === window && event.data && event.data.id === Theme.ID) { updateImages(current, reverse); } }); diff --git a/_javascript/modules/components/mermaid.js b/_javascript/modules/components/mermaid.js new file mode 100644 index 0000000..2b4759f --- /dev/null +++ b/_javascript/modules/components/mermaid.js @@ -0,0 +1,60 @@ +/** + * Mermaid-js loader + */ + +const MERMAID = 'mermaid'; +const themeMapper = Theme.getThemeMapper('default', 'dark'); + +function refreshTheme(event) { + if (event.source === window && event.data && event.data.id === Theme.ID) { + // Re-render the SVG › + const mermaidList = document.getElementsByClassName(MERMAID); + + [...mermaidList].forEach((elem) => { + const svgCode = elem.previousSibling.children.item(0).innerHTML; + elem.textContent = svgCode; + elem.removeAttribute('data-processed'); + }); + + const newTheme = themeMapper[Theme.visualState]; + + mermaid.initialize({ theme: newTheme }); + mermaid.init(null, `.${MERMAID}`); + } +} + +function setNode(elem) { + const svgCode = elem.textContent; + const backup = elem.parentElement; + backup.classList.add('d-none'); + // Create mermaid node + const mermaid = document.createElement('pre'); + mermaid.classList.add(MERMAID); + const text = document.createTextNode(svgCode); + mermaid.appendChild(text); + backup.after(mermaid); +} + +export function loadMermaid() { + if ( + typeof mermaid === 'undefined' || + typeof mermaid.initialize !== 'function' + ) { + return; + } + + const initTheme = themeMapper[Theme.visualState]; + + let mermaidConf = { + theme: initTheme + }; + + const basicList = document.getElementsByClassName('language-mermaid'); + [...basicList].forEach(setNode); + + mermaid.initialize(mermaidConf); + + if (Theme.switchable) { + window.addEventListener('message', refreshTheme); + } +} diff --git a/_javascript/modules/components/mode-toggle.js b/_javascript/modules/components/mode-toggle.js new file mode 100644 index 0000000..455ff0a --- /dev/null +++ b/_javascript/modules/components/mode-toggle.js @@ -0,0 +1,15 @@ +/** + * Add listener for theme mode toggle + */ + +const $toggle = document.getElementById('mode-toggle'); + +export function modeWatcher() { + if (!$toggle) { + return; + } + + $toggle.addEventListener('click', () => { + Theme.flip(); + }); +} diff --git a/_javascript/modules/components/mode-watcher.js b/_javascript/modules/components/mode-watcher.js deleted file mode 100644 index 9eecd09..0000000 --- a/_javascript/modules/components/mode-watcher.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Add listener for theme mode toggle - */ -const toggle = document.getElementById('mode-toggle'); - -export function modeWatcher() { - if (!toggle) { - return; - } - - toggle.addEventListener('click', () => { - modeToggle.flipMode(); - }); -} diff --git a/_javascript/modules/components/sidebar.js b/_javascript/modules/components/sidebar.js deleted file mode 100644 index aed759e..0000000 --- a/_javascript/modules/components/sidebar.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Expand or close the sidebar in mobile screens. - */ - -const $sidebar = document.getElementById('sidebar'); -const $trigger = document.getElementById('sidebar-trigger'); -const $mask = document.getElementById('mask'); - -class SidebarUtil { - static #isExpanded = false; - - static toggle() { - this.#isExpanded = !this.#isExpanded; - document.body.toggleAttribute('sidebar-display', this.#isExpanded); - $sidebar.classList.toggle('z-2', this.#isExpanded); - $mask.classList.toggle('d-none', !this.#isExpanded); - } -} - -export function sidebarExpand() { - $trigger.onclick = $mask.onclick = () => SidebarUtil.toggle(); -} diff --git a/_javascript/modules/layouts/basic.js b/_javascript/modules/layouts/basic.js index fb36a8b..b8eddf6 100644 --- a/_javascript/modules/layouts/basic.js +++ b/_javascript/modules/layouts/basic.js @@ -1,7 +1,7 @@ -import { back2top } from '../components/back-to-top'; -import { loadTooptip } from '../components/tooltip-loader'; +import { back2top, loadTooptip, modeWatcher } from '../components'; export function basic() { + modeWatcher(); back2top(); loadTooptip(); } diff --git a/_javascript/modules/layouts/sidebar.js b/_javascript/modules/layouts/sidebar.js index 8795693..bbf5e7d 100644 --- a/_javascript/modules/layouts/sidebar.js +++ b/_javascript/modules/layouts/sidebar.js @@ -1,7 +1,19 @@ -import { modeWatcher } from '../components/mode-watcher'; -import { sidebarExpand } from '../components/sidebar'; +const ATTR_DISPLAY = 'sidebar-display'; +const $sidebar = document.getElementById('sidebar'); +const $trigger = document.getElementById('sidebar-trigger'); +const $mask = document.getElementById('mask'); + +class SidebarUtil { + static #isExpanded = false; + + static toggle() { + this.#isExpanded = !this.#isExpanded; + document.body.toggleAttribute(ATTR_DISPLAY, this.#isExpanded); + $sidebar.classList.toggle('z-2', this.#isExpanded); + $mask.classList.toggle('d-none', !this.#isExpanded); + } +} export function initSidebar() { - modeWatcher(); - sidebarExpand(); + $trigger.onclick = $mask.onclick = () => SidebarUtil.toggle(); } diff --git a/_javascript/modules/theme.js b/_javascript/modules/theme.js new file mode 100644 index 0000000..f9ebf20 --- /dev/null +++ b/_javascript/modules/theme.js @@ -0,0 +1,135 @@ +/** + * Theme management class + * + * To reduce flickering during page load, this script should be loaded synchronously. + */ +class Theme { + static #modeKey = 'mode'; + static #modeAttr = 'data-mode'; + static #darkMedia = window.matchMedia('(prefers-color-scheme: dark)'); + static switchable = !document.documentElement.hasAttribute(this.#modeAttr); + + static get DARK() { + return 'dark'; + } + + static get LIGHT() { + return 'light'; + } + + /** + * @returns {string} Theme mode identifier + */ + static get ID() { + return 'theme-mode'; + } + + /** + * Gets the current visual state of the theme. + * + * @returns {string} The current visual state, either the mode if it exists, + * or the system dark mode state ('dark' or 'light'). + */ + static get visualState() { + if (this.#hasMode) { + return this.#mode; + } else { + return this.#sysDark ? this.DARK : this.LIGHT; + } + } + + static get #mode() { + return sessionStorage.getItem(this.#modeKey); + } + + static get #isDarkMode() { + return this.#mode === this.DARK; + } + + static get #hasMode() { + return this.#mode !== null; + } + + static get #sysDark() { + return this.#darkMedia.matches; + } + + /** + * Maps theme modes to provided values + * @param {string} light Value for light mode + * @param {string} dark Value for dark mode + * @returns {Object} Mapped values + */ + static getThemeMapper(light, dark) { + return { + [this.LIGHT]: light, + [this.DARK]: dark + }; + } + + /** + * Initializes the theme based on system preferences or stored mode + */ + static init() { + if (!this.switchable) { + return; + } + + this.#darkMedia.addEventListener('change', () => { + const lastMode = this.#mode; + this.#clearMode(); + + if (lastMode !== this.visualState) { + this.#notify(); + } + }); + + if (!this.#hasMode) { + return; + } + + if (this.#isDarkMode) { + this.#setDark(); + } else { + this.#setLight(); + } + } + + /** + * Flips the current theme mode + */ + static flip() { + if (this.#hasMode) { + this.#clearMode(); + } else { + this.#sysDark ? this.#setLight() : this.#setDark(); + } + this.#notify(); + } + + static #setDark() { + document.documentElement.setAttribute(this.#modeAttr, this.DARK); + sessionStorage.setItem(this.#modeKey, this.DARK); + } + + static #setLight() { + document.documentElement.setAttribute(this.#modeAttr, this.LIGHT); + sessionStorage.setItem(this.#modeKey, this.LIGHT); + } + + static #clearMode() { + document.documentElement.removeAttribute(this.#modeAttr); + sessionStorage.removeItem(this.#modeKey); + } + + /** + * Notifies other plugins that the theme mode has changed + */ + static #notify() { + window.postMessage({ id: this.ID }, '*'); + } +} + +Theme.init(); + +export default Theme; diff --git a/_javascript/page.js b/_javascript/page.js index 76e8ce9..4b03b79 100644 --- a/_javascript/page.js +++ b/_javascript/page.js @@ -1,9 +1,15 @@ import { basic, initSidebar, initTopbar } from './modules/layouts'; -import { loadImg, imgPopup, initClipboard } from './modules/plugins'; +import { + loadImg, + imgPopup, + initClipboard, + loadMermaid +} from './modules/components'; loadImg(); imgPopup(); initSidebar(); initTopbar(); initClipboard(); +loadMermaid(); basic(); diff --git a/_javascript/post.js b/_javascript/post.js index 1c616ec..dc472b4 100644 --- a/_javascript/post.js +++ b/_javascript/post.js @@ -5,8 +5,9 @@ import { imgPopup, initLocaleDatetime, initClipboard, - initToc -} from './modules/plugins'; + initToc, + loadMermaid +} from './modules/components'; loadImg(); initToc(); @@ -15,4 +16,5 @@ initSidebar(); initLocaleDatetime(); initClipboard(); initTopbar(); +loadMermaid(); basic(); diff --git a/_layouts/default.html b/_layouts/default.html index 1590ef6..c83c561 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -74,8 +74,12 @@ layout: compress {% include_cached notification.html lang=lang %} {% endif %} - - {% include js-selector.html lang=lang %} + + + {% for _include in layout.script_includes %} + {% assign _include_path = _include | append: '.html' %} + {% include {{ _include_path }} %} + {% endfor %} {% include_cached search-loader.html lang=lang %} diff --git a/_layouts/post.html b/_layouts/post.html index 6a2deff..c8c21ef 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -6,7 +6,8 @@ panel_includes: tail_includes: - related-posts - post-nav - - comments +script_includes: + - comment --- {% include lang.html %} diff --git a/_sass/layout/post.scss b/_sass/layout/post.scss index b66e906..891479e 100644 --- a/_sass/layout/post.scss +++ b/_sass/layout/post.scss @@ -532,6 +532,7 @@ header { .utterances { max-width: 100%; + min-height: 269px; } %btn-share-hover { diff --git a/package.json b/package.json index f93e76b..3447784 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "devDependencies": { "@babel/core": "^7.25.2", "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-private-methods": "^7.25.7", "@babel/preset-env": "^7.25.4", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", diff --git a/rollup.config.js b/rollup.config.js index 19ba4da..3a1ae29 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -34,24 +34,32 @@ function insertFrontmatter() { }; } -function build(filename, { src = SRC_DEFAULT, jekyll = false } = {}) { +function build( + filename, + { src = SRC_DEFAULT, jekyll = false, outputName = null } = {} +) { + const input = `${src}/${filename}.js`; + return { - input: `${src}/${filename}.js`, + input, output: { file: `${DIST}/${filename}.min.js`, format: 'iife', - name: 'Chirpy', + ...(outputName !== null && { name: outputName }), banner, sourcemap: !isProd && !jekyll }, watch: { - include: `${src}/**` + include: input }, plugins: [ babel({ babelHelpers: 'bundled', presets: ['@babel/env'], - plugins: ['@babel/plugin-transform-class-properties'] + plugins: [ + '@babel/plugin-transform-class-properties', + '@babel/plugin-transform-private-methods' + ] }), nodeResolve(), isProd && terser(), @@ -69,6 +77,7 @@ export default [ build('page'), build('post'), build('misc'), + build('theme', { src: `${SRC_DEFAULT}/modules`, outputName: 'Theme' }), build('app', { src: SRC_PWA, jekyll: true }), build('sw', { src: SRC_PWA, jekyll: true }) ]; From c69914effc1f222d2b31d2ed14d1efda90575c9f Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Sun, 24 Nov 2024 02:08:13 +0800 Subject: [PATCH 2/7] ci: avoid repeated runs of stylelint (#2057) --- .github/workflows/style-lint.yml | 25 ----------------------- .stylelintrc.json | 30 +++++++++++++++++++++++++++ package.json | 35 -------------------------------- 3 files changed, 30 insertions(+), 60 deletions(-) delete mode 100644 .github/workflows/style-lint.yml create mode 100644 .stylelintrc.json diff --git a/.github/workflows/style-lint.yml b/.github/workflows/style-lint.yml deleted file mode 100644 index 5cb38a7..0000000 --- a/.github/workflows/style-lint.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Style Lint - -on: - push: - branches: - - master - - "hotfix/*" - paths: ["_sass/**/*.scss"] - pull_request: - paths: ["_sass/**/*.scss"] - -jobs: - stylelint: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: lts/* - - run: npm i - - run: npm test diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..57dd7d6 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,30 @@ +{ + "extends": "stylelint-config-standard-scss", + "rules": { + "no-descending-specificity": null, + "shorthand-property-no-redundant-values": null, + "at-rule-no-vendor-prefix": null, + "property-no-vendor-prefix": null, + "selector-no-vendor-prefix": null, + "value-no-vendor-prefix": null, + "color-function-notation": "legacy", + "alpha-value-notation": "number", + "selector-not-notation": "simple", + "color-hex-length": "long", + "declaration-block-single-line-max-declarations": 3, + "scss/operator-no-newline-after": null, + "rule-empty-line-before": [ + "always", + { + "ignore": ["after-comment", "first-nested"] + } + ], + "value-keyword-case": [ + "lower", + { + "ignoreProperties": ["/^\\$/"] + } + ], + "media-feature-range-notation": "prefix" + } +} diff --git a/package.json b/package.json index 3447784..d6beea0 100644 --- a/package.json +++ b/package.json @@ -68,41 +68,6 @@ ] } }, - "stylelint": { - "extends": "stylelint-config-standard-scss", - "rules": { - "no-descending-specificity": null, - "shorthand-property-no-redundant-values": null, - "at-rule-no-vendor-prefix": null, - "property-no-vendor-prefix": null, - "selector-no-vendor-prefix": null, - "value-no-vendor-prefix": null, - "color-function-notation": "legacy", - "alpha-value-notation": "number", - "selector-not-notation": "simple", - "color-hex-length": "long", - "declaration-block-single-line-max-declarations": 3, - "scss/operator-no-newline-after": null, - "rule-empty-line-before": [ - "always", - { - "ignore": [ - "after-comment", - "first-nested" - ] - } - ], - "value-keyword-case": [ - "lower", - { - "ignoreProperties": [ - "/^\\$/" - ] - } - ], - "media-feature-range-notation": "prefix" - } - }, "release": { "branches": [ "production" From 35c794cf5896565430389f35c660b88a93cebb17 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Mon, 25 Nov 2024 00:05:28 +0800 Subject: [PATCH 3/7] perf: modular sass architecture (#2052) - Modularized the Sass architecture to enhance code maintainability and reduce the output file size - Replaced deprecated `@import` with `@use` / `@forward` --- .gitignore | 2 +- .stylelintrc.json | 1 + _includes/head.html | 2 +- _posts/2019-08-09-getting-started.md | 2 - _sass/abstracts/_breakpoints.scss | 73 + _sass/abstracts/_index.scss | 4 + _sass/abstracts/_mixins.scss | 80 + .../_placeholders.scss} | 83 +- .../_variables.scss} | 4 - _sass/addon/commons.scss | 1526 ----------------- _sass/base/_base.scss | 476 +++++ _sass/base/_index.scss | 4 + _sass/base/_reset.scss | 41 + .../{addon/syntax.scss => base/_syntax.scss} | 131 +- _sass/base/_typography.scss | 266 +++ _sass/colors/syntax-dark.scss | 164 -- _sass/colors/syntax-light.scss | 210 --- _sass/colors/typography-light.scss | 112 -- _sass/components/_buttons.scss | 51 + _sass/components/_index.scss | 2 + _sass/components/_popups.scss | 172 ++ _sass/layout/_footer.scss | 36 + _sass/layout/_index.scss | 4 + _sass/layout/_panel.scss | 66 + _sass/layout/_sidebar.scss | 258 +++ _sass/layout/_topbar.scss | 86 + _sass/main.bundle.scss | 4 +- _sass/main.scss | 17 +- .../archives.scss => pages/_archives.scss} | 23 +- .../_categories.scss} | 11 +- .../_category-tag.scss} | 29 +- _sass/{layout/home.scss => pages/_home.scss} | 119 +- _sass/pages/_index.scss | 7 + _sass/{layout/post.scss => pages/_post.scss} | 219 +-- _sass/pages/_search.scss | 184 ++ _sass/{layout/tags.scss => pages/_tags.scss} | 10 +- .../_dark.scss} | 168 +- _sass/themes/_light.scss | 313 ++++ _sass/variables-hook.scss | 3 - assets/css/jekyll-theme-chirpy.scss | 2 +- package.json | 2 +- purgecss.config.js | 23 - purgecss.js | 30 + tools/init.sh | 3 +- tools/release.sh | 2 +- 45 files changed, 2523 insertions(+), 2502 deletions(-) create mode 100644 _sass/abstracts/_breakpoints.scss create mode 100644 _sass/abstracts/_index.scss create mode 100644 _sass/abstracts/_mixins.scss rename _sass/{addon/module.scss => abstracts/_placeholders.scss} (59%) rename _sass/{addon/variables.scss => abstracts/_variables.scss} (96%) delete mode 100644 _sass/addon/commons.scss create mode 100644 _sass/base/_base.scss create mode 100644 _sass/base/_index.scss create mode 100644 _sass/base/_reset.scss rename _sass/{addon/syntax.scss => base/_syntax.scss} (74%) create mode 100644 _sass/base/_typography.scss delete mode 100644 _sass/colors/syntax-dark.scss delete mode 100644 _sass/colors/syntax-light.scss delete mode 100644 _sass/colors/typography-light.scss create mode 100644 _sass/components/_buttons.scss create mode 100644 _sass/components/_index.scss create mode 100644 _sass/components/_popups.scss create mode 100644 _sass/layout/_footer.scss create mode 100644 _sass/layout/_index.scss create mode 100644 _sass/layout/_panel.scss create mode 100644 _sass/layout/_sidebar.scss create mode 100644 _sass/layout/_topbar.scss rename _sass/{layout/archives.scss => pages/_archives.scss} (95%) rename _sass/{layout/categories.scss => pages/_categories.scss} (87%) rename _sass/{layout/category-tag.scss => pages/_category-tag.scss} (79%) rename _sass/{layout/home.scss => pages/_home.scss} (73%) create mode 100644 _sass/pages/_index.scss rename _sass/{layout/post.scss => pages/_post.scss} (67%) create mode 100644 _sass/pages/_search.scss rename _sass/{layout/tags.scss => pages/_tags.scss} (71%) rename _sass/{colors/typography-dark.scss => themes/_dark.scss} (62%) create mode 100644 _sass/themes/_light.scss delete mode 100644 _sass/variables-hook.scss delete mode 100644 purgecss.config.js create mode 100644 purgecss.js diff --git a/.gitignore b/.gitignore index 0082d90..7dd7cef 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,5 @@ package-lock.json !.vscode/tasks.json # Misc -_sass/dist +_sass/vendors assets/js/dist diff --git a/.stylelintrc.json b/.stylelintrc.json index 57dd7d6..b890290 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,4 +1,5 @@ { + "ignoreFiles": ["_sass/vendors/**"], "extends": "stylelint-config-standard-scss", "rules": { "no-descending-specificity": null, diff --git a/_includes/head.html b/_includes/head.html index 310f52e..011187c 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -70,7 +70,7 @@ {% unless jekyll.environment == 'production' %} - + {% endunless %} diff --git a/_posts/2019-08-09-getting-started.md b/_posts/2019-08-09-getting-started.md index 3b41a3c..2681126 100644 --- a/_posts/2019-08-09-getting-started.md +++ b/_posts/2019-08-09-getting-started.md @@ -93,8 +93,6 @@ Social contact options are displayed at the bottom of the sidebar. You can enabl To customize the stylesheet, copy the theme's `assets/css/jekyll-theme-chirpy.scss`{: .filepath} file to the same path in your Jekyll site, and add your custom styles at the end of the file. -Starting with version `6.2.0`, if you want to overwrite the SASS variables defined in `_sass/addon/variables.scss`{: .filepath}, copy the main SASS file `_sass/main.scss`{: .filepath} to the `_sass`{: .filepath} directory in your site's source, then create a new file `_sass/variables-hook.scss`{: .filepath} and assign your new values there. - ### Customizing Static Assets Static assets configuration was introduced in version `5.1.0`. The CDN of the static assets is defined in `_data/origin/cors.yml`{: .filepath }. You can replace some of them based on the network conditions in the region where your website is published. diff --git a/_sass/abstracts/_breakpoints.scss b/_sass/abstracts/_breakpoints.scss new file mode 100644 index 0000000..e40cefe --- /dev/null +++ b/_sass/abstracts/_breakpoints.scss @@ -0,0 +1,73 @@ +@use 'sass:map'; + +$-breakpoints: ( + // 1 column + sm: 576px, + md: 768px, + // 2 columns + lg: 850px, + // 3 columns + xl: 1200px, + xxl: 1400px, + xxxl: 1650px +); + +@function get($breakpoint) { + @return map.get($-breakpoints, $breakpoint); +} + +/* Less than the given width */ +@mixin lt($width) { + @media all and (max-width: calc(#{$width} - 1px)) { + @content; + } +} + +/* Less than or equal to the given width */ +@mixin lte($width) { + @media all and (max-width: $width) { + @content; + } +} + +@mixin sm { + @media all and (min-width: get(sm)) { + @content; + } +} + +@mixin md { + @media all and (min-width: get(md)) { + @content; + } +} + +@mixin lg { + @media all and (min-width: get(lg)) { + @content; + } +} + +@mixin xl { + @media all and (min-width: get(xl)) { + @content; + } +} + +@mixin xxl { + @media all and (min-width: get(xxl)) { + @content; + } +} + +@mixin xxxl { + @media all and (min-width: get(xxxl)) { + @content; + } +} + +@mixin between($min, $max) { + @media all and (min-width: $min) and (max-width: $max) { + @content; + } +} diff --git a/_sass/abstracts/_index.scss b/_sass/abstracts/_index.scss new file mode 100644 index 0000000..6c9e21c --- /dev/null +++ b/_sass/abstracts/_index.scss @@ -0,0 +1,4 @@ +@forward 'variables'; +@forward 'mixins'; +@forward 'placeholders'; +@forward 'breakpoints'; diff --git a/_sass/abstracts/_mixins.scss b/_sass/abstracts/_mixins.scss new file mode 100644 index 0000000..c5eeee3 --- /dev/null +++ b/_sass/abstracts/_mixins.scss @@ -0,0 +1,80 @@ +@mixin text-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +@mixin mt-mb($value) { + margin-top: $value; + margin-bottom: $value; +} + +@mixin ml-mr($value) { + margin-left: $value; + margin-right: $value; +} + +@mixin pt-pb($val) { + padding-top: $val; + padding-bottom: $val; +} + +@mixin pl-pr($val, $important: false) { + @if $important { + padding-left: $val !important; + padding-right: $val !important; + } @else { + padding-left: $val; + padding-right: $val; + } +} + +@mixin placeholder { + color: var(--text-muted-color) !important; +} + +@mixin placeholder-focus { + opacity: 0.6; +} + +@mixin label($font-size: 1rem, $font-weight: 600, $color: var(--label-color)) { + color: $color; + font-size: $font-size; + font-weight: $font-weight; +} + +@mixin align-center { + position: relative; + left: 50%; + transform: translateX(-50%); +} + +@mixin prompt($type, $fa-content, $fa-style: 'solid', $rotate: 0) { + &.prompt-#{$type} { + background-color: var(--prompt-#{$type}-bg); + + &::before { + content: $fa-content; + color: var(--prompt-#{$type}-icon-color); + font: var(--fa-font-#{$fa-style}); + + @if $rotate != 0 { + transform: rotate(#{$rotate}deg); + } + } + } +} + +@mixin slide($append: null) { + $basic: transform 0.4s ease; + + @if $append { + transition: $basic, $append; + } @else { + transition: $basic; + } +} + +@mixin max-w-100 { + max-width: 100%; +} diff --git a/_sass/addon/module.scss b/_sass/abstracts/_placeholders.scss similarity index 59% rename from _sass/addon/module.scss rename to _sass/abstracts/_placeholders.scss index 1dfb735..e4c1bb0 100644 --- a/_sass/addon/module.scss +++ b/_sass/abstracts/_placeholders.scss @@ -1,13 +1,10 @@ -/* -* Mainly scss modules, only imported to `assets/css/main.scss` -*/ - -/* ---------- scss placeholder --------- */ +@use 'variables' as v; +@use 'mixins' as mx; %heading { color: var(--heading-color); font-weight: 400; - font-family: $font-family-heading; + font-family: v.$font-family-heading; scroll-margin-top: 3.5rem; } @@ -82,7 +79,7 @@ } %rounded { - border-radius: $radius-lg; + border-radius: v.$radius-lg; } %img-caption { @@ -112,14 +109,8 @@ -webkit-box-orient: vertical; } -@mixin text-ellipsis { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - %text-ellipsis { - @include text-ellipsis; + @include mx.text-ellipsis; } %text-highlight { @@ -151,65 +142,15 @@ } } -/* ---------- scss mixin --------- */ - -@mixin mt-mb($value) { - margin-top: $value; - margin-bottom: $value; +%code-snippet-bg { + background-color: var(--highlight-bg-color); } -@mixin ml-mr($value) { - margin-left: $value; - margin-right: $value; +%code-snippet-padding { + padding-left: 1rem; + padding-right: 1.5rem; } -@mixin pt-pb($val) { - padding-top: $val; - padding-bottom: $val; -} - -@mixin pl-pr($val, $important: false) { - @if $important { - padding-left: $val !important; - padding-right: $val !important; - } @else { - padding-left: $val; - padding-right: $val; - } -} - -@mixin placeholder { - color: var(--text-muted-color) !important; -} - -@mixin placeholder-focus { - opacity: 0.6; -} - -@mixin label($font-size: 1rem, $font-weight: 600, $color: var(--label-color)) { - color: $color; - font-size: $font-size; - font-weight: $font-weight; -} - -@mixin align-center { - position: relative; - left: 50%; - transform: translateX(-50%); -} - -@mixin prompt($type, $fa-content, $fa-style: 'solid', $rotate: 0) { - &.prompt-#{$type} { - background-color: var(--prompt-#{$type}-bg); - - &::before { - content: $fa-content; - color: var(--prompt-#{$type}-icon-color); - font: var(--fa-font-#{$fa-style}); - - @if $rotate != 0 { - transform: rotate(#{$rotate}deg); - } - } - } +%max-w-100 { + max-width: 100%; } diff --git a/_sass/addon/variables.scss b/_sass/abstracts/_variables.scss similarity index 96% rename from _sass/addon/variables.scss rename to _sass/abstracts/_variables.scss index 1d51cb1..0194e40 100644 --- a/_sass/addon/variables.scss +++ b/_sass/abstracts/_variables.scss @@ -1,7 +1,3 @@ -/* - * The SCSS variables - */ - /* sidebar */ $sidebar-width: 260px !default; /* the basic width */ diff --git a/_sass/addon/commons.scss b/_sass/addon/commons.scss deleted file mode 100644 index 5e8acea..0000000 --- a/_sass/addon/commons.scss +++ /dev/null @@ -1,1526 +0,0 @@ -/* The common styles */ - -html { - font-size: 16px; - - @media (prefers-color-scheme: light) { - &:not([data-mode]), - &[data-mode='light'] { - @include light-scheme; - } - - &[data-mode='dark'] { - @include dark-scheme; - } - } - - @media (prefers-color-scheme: dark) { - &:not([data-mode]), - &[data-mode='dark'] { - @include dark-scheme; - } - - &[data-mode='light'] { - @include light-scheme; - } - } -} - -body { - background: var(--main-bg); - padding: env(safe-area-inset-top) env(safe-area-inset-right) - env(safe-area-inset-bottom) env(safe-area-inset-left); - color: var(--text-color); - -webkit-font-smoothing: antialiased; - font-family: $font-family-base; -} - -/* --- Typography --- */ - -@for $i from 1 through 5 { - h#{$i} { - @extend %heading; - - @if $i > 1 { - @extend %anchor; - } - - @if $i < 5 { - $size-factor: 0.25rem; - - @if $i > 1 { - $size-factor: 0.18rem; - - main & { - @if $i == 2 { - margin: 2.5rem 0 1.25rem; - } @else { - margin: 2rem 0 1rem; - } - } - } - - & { - font-size: 1rem + (5 - $i) * $size-factor; - } - } @else { - font-size: 1.05rem; - } - } -} - -a { - @extend %link-color; - - text-decoration: none; -} - -img { - max-width: 100%; - height: auto; - transition: all 0.35s ease-in-out; - - .blur & { - $blur: 20px; - - -webkit-filter: blur($blur); - filter: blur($blur); - } -} - -blockquote { - border-left: 0.125rem solid var(--blockquote-border-color); - padding-left: 1rem; - color: var(--blockquote-text-color); - margin-top: 0.5rem; - - > p:last-child { - margin-bottom: 0; - } - - &[class^='prompt-'] { - border-left: 0; - position: relative; - padding: 1rem 1rem 1rem 3rem; - color: var(--prompt-text-color); - - @extend %rounded; - - &::before { - text-align: center; - width: 3rem; - position: absolute; - left: 0.25rem; - margin-top: 0.4rem; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - } - } - - @include prompt('tip', '\f0eb', $fa-style: 'regular'); - @include prompt('info', '\f06a', $rotate: 180); - @include prompt('warning', '\f06a'); - @include prompt('danger', '\f071'); -} - -kbd { - font-family: Lato, sans-serif; - display: inline-block; - vertical-align: middle; - line-height: 1.3rem; - min-width: 1.75rem; - text-align: center; - margin: 0 0.3rem; - padding-top: 0.1rem; - color: var(--kbd-text-color); - background-color: var(--kbd-bg-color); - border-radius: $radius-sm; - border: solid 1px var(--kbd-wrap-color); - box-shadow: inset 0 -2px 0 var(--kbd-wrap-color); -} - -hr { - border-color: var(--main-border-color); - opacity: 1; -} - -footer { - background-color: var(--main-bg); - height: $footer-height; - border-top: 1px solid var(--main-border-color); - - @extend %text-xs; - - a { - @extend %text-highlight; - - &:hover { - @extend %link-hover; - } - } - - em { - @extend %text-highlight; - } - - p { - text-align: center; - margin-bottom: 0; - } -} - -/* fontawesome icons */ -i { - &.far, - &.fas { - @extend %no-cursor; - } -} - -/* --- Panels --- */ - -.access { - top: 2rem; - transition: top 0.2s ease-in-out; - margin-top: 3rem; - margin-bottom: 4rem; - - &:only-child { - position: -webkit-sticky; - position: sticky; - } - - > section { - padding-left: 1rem; - border-left: 1px solid var(--main-border-color); - - &:not(:last-child) { - margin-bottom: 4rem; - } - } - - .content { - font-size: 0.9rem; - } -} - -#panel-wrapper { - /* the headings */ - .panel-heading { - font-family: inherit; - line-height: inherit; - - @include label(inherit); - } - - .post-tag { - line-height: 1.05rem; - font-size: 0.85rem; - border-radius: 0.8rem; - padding: 0.3rem 0.5rem; - margin: 0 0.35rem 0.5rem 0; - - &:hover { - transition: all 0.3s ease-in; - } - } -} - -#access-lastmod { - a { - color: inherit; - - &:hover { - @extend %link-hover; - } - - @extend %no-bottom-border; - } -} - -.footnotes > ol { - padding-left: 2rem; - margin-top: 0.5rem; - - > li { - &:not(:last-child) { - margin-bottom: 0.3rem; - } - - @extend %sup-fn-target; - - > p { - margin-left: 0.25em; - - @include mt-mb(0); - } - } -} - -.footnote { - @at-root a#{&} { - @include ml-mr(1px); - @include pl-pr(2px); - - border-bottom-style: none !important; - } -} - -sup { - @extend %sup-fn-target; -} - -.reversefootnote { - @at-root a#{&} { - font-size: 0.6rem; - line-height: 1; - position: relative; - bottom: 0.25em; - margin-left: 0.25em; - border-bottom-style: none !important; - } -} - -/* --- Begin of Markdown table style --- */ - -/* it will be created by Liquid */ -.table-wrapper { - overflow-x: auto; - margin-bottom: 1.5rem; - - > table { - min-width: 100%; - overflow-x: auto; - border-spacing: 0; - - thead { - border-bottom: solid 2px rgba(210, 215, 217, 0.75); - - th { - @extend %table-cell; - } - } - - tbody { - tr { - border-bottom: 1px solid var(--tb-border-color); - - &:nth-child(2n) { - background-color: var(--tb-even-bg); - } - - &:nth-child(2n + 1) { - background-color: var(--tb-odd-bg); - } - - td { - @extend %table-cell; - } - } - } /* tbody */ - } /* table */ -} - -/* --- post --- */ - -.preview-img { - aspect-ratio: 40 / 21; - width: 100%; - height: 100%; - overflow: hidden; - - @extend %rounded; - - &:not(.no-bg) { - background: var(--img-bg); - } - - img { - height: 100%; - -o-object-fit: cover; - object-fit: cover; - - @extend %rounded; - - @at-root #post-list & { - width: 100%; - } - } -} - -.post-preview { - @extend %rounded; - - border: 0; - background: var(--card-bg); - box-shadow: var(--card-shadow); - - &::before { - @extend %rounded; - - content: ''; - width: 100%; - height: 100%; - position: absolute; - background-color: var(--card-hovor-bg); - opacity: 0; - transition: opacity 0.35s ease-in-out; - } - - &:hover { - &::before { - opacity: 0.3; - } - } -} - -main { - line-height: 1.75; - - h1 { - margin-top: 2rem; - } - - p { - > a.popup { - &:not(.normal):not(.left):not(.right) { - @include align-center; - } - } - } - - .categories, - #tags, - #archives { - a:not(:hover) { - @extend %no-bottom-border; - } - } -} - -.post-meta { - @extend %text-sm; - - a { - &:not([class]):hover { - @extend %link-hover; - } - } - - em { - @extend %normal-font-style; - } -} - -.content { - font-size: 1.08rem; - margin-top: 2rem; - overflow-wrap: break-word; - - a { - &.popup { - @extend %no-cursor; - @extend %img-caption; - @include mt-mb(0.5rem); - - cursor: zoom-in; - } - - &:not(.img-link) { - @extend %link-underline; - - &:hover { - @extend %link-hover; - } - } - } - - ol, - ul { - &:not([class]), - &.task-list { - -webkit-padding-start: 1.75rem; - padding-inline-start: 1.75rem; - - li { - margin: 0.25rem 0; - padding-left: 0.25rem; - } - - ol, - ul { - -webkit-padding-start: 1.25rem; - padding-inline-start: 1.25rem; - margin: 0.5rem 0; - } - } - } - - ul.task-list { - -webkit-padding-start: 1.25rem; - padding-inline-start: 1.25rem; - - li { - list-style-type: none; - padding-left: 0; - - /* checkbox icon */ - > i { - width: 2rem; - margin-left: -1.25rem; - color: var(--checkbox-color); - - &.checked { - color: var(--checkbox-checked-color); - } - } - - ul { - -webkit-padding-start: 1.75rem; - padding-inline-start: 1.75rem; - } - } - - input[type='checkbox'] { - margin: 0 0.5rem 0.2rem -1.3rem; - vertical-align: middle; - } - } /* ul */ - - dl > dd { - margin-left: 1rem; - } - - ::marker { - color: var(--text-muted-color); - } -} /* .content */ - -.tag:hover { - @extend %tag-hover; -} - -.post-tag { - display: inline-block; - min-width: 2rem; - text-align: center; - border-radius: 0.5rem; - border: 1px solid var(--btn-border-color); - padding: 0 0.4rem; - color: var(--text-muted-color); - line-height: 1.3rem; - - &:not(:last-child) { - margin-right: 0.2rem; - } -} - -.rounded-10 { - border-radius: 10px !important; -} - -.img-link { - color: transparent; - display: inline-flex; -} - -.shimmer { - overflow: hidden; - position: relative; - background: var(--img-bg); - - &::before { - content: ''; - position: absolute; - background: var(--shimmer-bg); - height: 100%; - width: 100%; - -webkit-animation: shimmer 1.3s infinite; - animation: shimmer 1.3s infinite; - } - - @-webkit-keyframes shimmer { - 0% { - transform: translateX(-100%); - } - - 100% { - transform: translateX(100%); - } - } - - @keyframes shimmer { - 0% { - transform: translateX(-100%); - } - - 100% { - transform: translateX(100%); - } - } -} - -.embed-video { - width: 100%; - height: 100%; - margin-bottom: 1rem; - aspect-ratio: 16 / 9; - - @extend %rounded; - - &.twitch { - aspect-ratio: 310 / 189; - } - - &.file { - display: block; - width: auto; - height: auto; - max-width: 100%; - max-height: 100%; - margin: auto; - margin-bottom: 0; - } - - @extend %img-caption; -} - -.embed-audio { - width: 100%; - display: block; - - @extend %img-caption; -} - -/* --- buttons --- */ -.btn-lang { - border: 1px solid !important; - padding: 1px 3px; - border-radius: 3px; - color: var(--link-color); - - &:focus { - box-shadow: none; - } -} - -/* --- Effects classes --- */ - -.flex-grow-1 { - flex-grow: 1 !important; -} - -.btn-box-shadow { - box-shadow: var(--card-shadow); -} - -/* overwrite bootstrap muted */ -.text-muted { - color: var(--text-muted-color) !important; -} - -/* Overwrite bootstrap tooltip */ -.tooltip-inner { - font-size: 0.7rem; - max-width: 220px; - text-align: left; -} - -/* Overwrite bootstrap outline button */ -.btn.btn-outline-primary { - &:not(.disabled):hover { - border-color: #007bff !important; - } -} - -.disabled { - color: rgb(206, 196, 196); - pointer-events: auto; - cursor: not-allowed; -} - -.hide-border-bottom { - border-bottom: none !important; -} - -.input-focus { - box-shadow: none; - border-color: var(--input-focus-border-color) !important; - background: center !important; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; -} - -.left { - float: left; - margin: 0.75rem 1rem 1rem 0; -} - -.right { - float: right; - margin: 0.75rem 0 1rem 1rem; -} - -/* --- Overriding --- */ - -/* mermaid */ -.mermaid { - text-align: center; -} - -/* MathJax */ -mjx-container { - overflow-y: hidden; - min-width: auto !important; -} - -/* --- sidebar layout --- */ - -$sidebar-display: 'sidebar-display'; -$btn-border-width: 3px; -$btn-mb: 0.5rem; - -#sidebar { - @include pl-pr(0); - - position: fixed; - top: 0; - left: 0; - height: 100%; - overflow-y: auto; - width: $sidebar-width; - background: var(--sidebar-bg); - border-right: 1px solid var(--sidebar-border-color); - - /* Hide scrollbar for IE, Edge and Firefox */ - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ - - /* Hide scrollbar for Chrome, Safari and Opera */ - &::-webkit-scrollbar { - display: none; - } - - %sidebar-link-hover { - &:hover { - color: var(--sidebar-active-color); - } - } - - a { - @extend %sidebar-links; - } - - #avatar { - display: block; - width: 7rem; - height: 7rem; - overflow: hidden; - box-shadow: var(--avatar-border-color) 0 0 0 2px; - transform: translateZ(0); /* fixed the zoom in Safari */ - - img { - transition: transform 0.5s; - - &:hover { - transform: scale(1.2); - } - } - } - - .profile-wrapper { - @include mt-mb(2.5rem); - @extend %clickable-transition; - - padding-left: 2.5rem; - padding-right: 1.25rem; - width: 100%; - } - - .site-title { - @extend %clickable-transition; - @extend %sidebar-link-hover; - - font-family: inherit; - font-weight: 900; - font-size: 1.75rem; - line-height: 1.2; - letter-spacing: 0.25px; - margin-top: 1.25rem; - margin-bottom: 0.5rem; - width: fit-content; - color: var(--site-title-color); - } - - .site-subtitle { - font-size: 95%; - color: var(--site-subtitle-color); - margin-top: 0.25rem; - word-spacing: 1px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } - - ul { - margin-bottom: 2rem; - - li.nav-item { - opacity: 0.9; - width: 100%; - - @include pl-pr(1.5rem); - - a.nav-link { - @include pt-pb(0.6rem); - - display: flex; - align-items: center; - border-radius: 0.75rem; - font-weight: 600; - - &:hover { - background-color: var(--sidebar-hover-bg); - } - - i { - font-size: 95%; - opacity: 0.8; - margin-right: 1.5rem; - } - - span { - font-size: 90%; - letter-spacing: 0.2px; - } - } - - &.active { - .nav-link { - color: var(--sidebar-active-color); - background-color: var(--sidebar-hover-bg); - - span { - opacity: 1; - } - } - } - - &:not(:first-child) { - margin-top: 0.25rem; - } - } - } - - .sidebar-bottom { - padding-left: 2rem; - padding-right: 1rem; - margin-bottom: 1.5rem; - - $btn-size: 1.75rem; - - %button { - width: $btn-size; - height: $btn-size; - margin-bottom: $btn-mb; // multi line gap - border-radius: 50%; - color: var(--sidebar-btn-color); - background-color: var(--sidebar-btn-bg); - text-align: center; - display: flex; - align-items: center; - justify-content: center; - - &:not(:focus-visible) { - box-shadow: var(--sidebar-border-color) 0 0 0 1px; - } - - &:hover { - background-color: var(--sidebar-hover-bg); - } - } - - a { - @extend %button; - @extend %sidebar-link-hover; - @extend %clickable-transition; - - &:not(:last-child) { - margin-right: $sb-btn-gap; - } - } - - i { - line-height: $btn-size; - } - - #mode-toggle { - @extend %button; - @extend %sidebar-links; - @extend %sidebar-link-hover; - } - - .icon-border { - @extend %no-cursor; - @include ml-mr(calc(($sb-btn-gap - $btn-border-width) / 2)); - - background-color: var(--sidebar-btn-color); - content: ''; - width: $btn-border-width; - height: $btn-border-width; - border-radius: 50%; - margin-bottom: $btn-mb; - } - } /* .sidebar-bottom */ -} /* #sidebar */ - -@media (hover: hover) { - #sidebar ul > li:last-child::after { - transition: top 0.5s ease; - } - - .nav-link { - transition: background-color 0.3s ease-in-out; - } - - .post-preview { - transition: background-color 0.35s ease-in-out; - } -} - -#search-result-wrapper { - display: none; - height: 100%; - width: 100%; - overflow: auto; - - .content { - margin-top: 2rem; - } -} - -/* --- top-bar --- */ - -#topbar-wrapper { - height: $topbar-height; - background-color: var(--topbar-bg); -} - -#topbar { - @extend %btn-color; - - #breadcrumb { - font-size: 1rem; - color: var(--text-muted-color); - padding-left: 0.5rem; - - a:hover { - @extend %link-hover; - } - - span { - &:not(:last-child) { - &::after { - content: '›'; - padding: 0 0.3rem; - } - } - } - } -} /* #topbar */ - -::-webkit-input-placeholder { - @include placeholder; -} - -::-moz-placeholder { - @include placeholder; -} - -:-ms-input-placeholder { - @include placeholder; -} - -::-ms-input-placeholder { - @include placeholder; -} - -::placeholder { - @include placeholder; -} - -:focus::-webkit-input-placeholder { - @include placeholder-focus; -} - -:focus::-moz-placeholder { - @include placeholder-focus; -} - -:focus:-ms-input-placeholder { - @include placeholder-focus; -} - -:focus::-ms-input-placeholder { - @include placeholder-focus; -} - -:focus::placeholder { - @include placeholder-focus; -} - -search { - display: flex; - width: 100%; - border-radius: 1rem; - border: 1px solid var(--search-border-color); - background: var(--main-bg); - padding: 0 0.5rem; - - i { - z-index: 2; - font-size: 0.9rem; - color: var(--search-icon-color); - } -} - -#sidebar-trigger, -#search-trigger { - display: none; -} - -/* 'Cancel' link */ -#search-cancel { - color: var(--link-color); - display: none; - white-space: nowrap; - - @extend %cursor-pointer; -} - -#search-input { - background: center; - border: 0; - border-radius: 0; - padding: 0.18rem 0.3rem; - color: var(--text-color); - height: auto; - - &:focus { - box-shadow: none; - } -} - -#search-hints { - padding: 0 1rem; - - h4 { - margin-bottom: 1.5rem; - } - - .post-tag { - display: inline-block; - line-height: 1rem; - font-size: 1rem; - background: var(--search-tag-bg); - border: none; - padding: 0.5rem; - margin: 0 1.25rem 1rem 0; - - &::before { - content: '#'; - color: var(--text-muted-color); - padding-right: 0.2rem; - } - - @extend %link-color; - } -} - -#search-results { - padding-bottom: 3rem; - - a { - font-size: 1.4rem; - line-height: 1.5rem; - - &:hover { - @extend %link-hover; - } - - @extend %link-color; - @extend %no-bottom-border; - @extend %heading; - } - - > article { - width: 100%; - - &:not(:last-child) { - margin-bottom: 1rem; - } - - /* icons */ - i { - color: #818182; - margin-right: 0.15rem; - font-size: 80%; - } - - > p { - @extend %text-ellipsis; - - white-space: break-spaces; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - } - } -} /* #search-results */ - -#topbar-title { - display: none; - font-size: 1.1rem; - font-weight: 600; - font-family: sans-serif; - color: var(--topbar-text-color); - text-align: center; - width: 70%; - word-break: keep-all; -} - -#mask { - inset: 0 0 0 0; -} - -/* --- basic wrappers --- */ - -#main-wrapper { - position: relative; - - @include pl-pr(0); - - > .container { - min-height: 100vh; - } -} - -#topbar-wrapper.row, -#main-wrapper > .container > .row, -#search-result-wrapper > .row { - @include ml-mr(0); -} - -#tail-wrapper { - > :not(script) { - margin-top: 3rem; - } -} - -/* --- button back-to-top --- */ - -#back-to-top { - visibility: hidden; - opacity: 0; - z-index: 1; - cursor: pointer; - position: fixed; - right: 1rem; - bottom: calc($footer-height-large - $back2top-size / 2); - background: var(--button-bg); - color: var(--btn-backtotop-color); - padding: 0; - width: $back2top-size; - height: $back2top-size; - border-radius: 50%; - border: 1px solid var(--btn-backtotop-border-color); - transition: opacity 0.5s ease-in-out, transform 0.2s ease-out; - - &:hover { - transform: translate3d(0, -5px, 0); - -webkit-transform: translate3d(0, -5px, 0); - } - - i { - line-height: $back2top-size; - position: relative; - bottom: 2px; - } - - &.show { - opacity: 1; - visibility: visible; - } -} - -#notification { - @-webkit-keyframes popup { - from { - opacity: 0; - bottom: 0; - } - } - - @keyframes popup { - from { - opacity: 0; - bottom: 0; - } - } - - .toast-header { - background: none; - border-bottom: none; - color: inherit; - } - - .toast-body { - font-family: Lato, sans-serif; - line-height: 1.25rem; - - button { - font-size: 90%; - min-width: 4rem; - } - } - - &.toast { - &.show { - display: block; - min-width: 20rem; - border-radius: 0.5rem; - -webkit-backdrop-filter: blur(10px); - backdrop-filter: blur(10px); - background-color: rgba(255, 255, 255, 0.5); - color: #1b1b1eba; - position: fixed; - left: 50%; - bottom: 20%; - transform: translateX(-50%); - -webkit-animation: popup 0.8s; - animation: popup 0.8s; - } - } -} - -/* - Responsive Design: - - {sidebar, content, panel} >= 1200px screen width - {sidebar, content} >= 850px screen width - {content} <= 849px screen width - -*/ - -@media all and (max-width: 576px) { - main { - .content { - > blockquote[class^='prompt-'] { - @include ml-mr(-1rem); - - border-radius: 0; - max-width: none; - } - } - } - - #avatar { - width: 5rem; - height: 5rem; - } -} - -@media all and (max-width: 768px) { - %full-width { - max-width: 100%; - } - - #topbar { - @extend %full-width; - } - - #main-wrapper > .container { - @extend %full-width; - @include pl-pr(0); - } -} - -/* hide sidebar and panel */ -@media all and (max-width: 849px) { - @mixin slide($append: null) { - $basic: transform 0.4s ease; - - @if $append { - transition: $basic, $append; - } @else { - transition: $basic; - } - } - - footer { - @include slide; - - height: $footer-height-large; - padding: 1.5rem 0; - } - - [#{$sidebar-display}] { - #sidebar { - transform: translateX(0); - } - - #main-wrapper { - transform: translateX($sidebar-width); - } - - #back-to-top { - visibility: hidden; - } - } - - #sidebar { - @include slide; - - transform: translateX(-$sidebar-width); /* hide */ - -webkit-transform: translateX(-$sidebar-width); - } - - #main-wrapper { - @include slide; - } - - #topbar, - #main-wrapper > .container { - max-width: 100%; - } - - #search-result-wrapper { - width: 100%; - } - - #breadcrumb, - search { - display: none; - } - - #topbar-wrapper { - @include slide(top 0.2s ease); - - left: 0; - } - - main, - #panel-wrapper { - margin-top: 0; - } - - #topbar-title, - #sidebar-trigger, - #search-trigger { - display: block; - } - - #search-result-wrapper .content { - letter-spacing: 0; - } - - #tags { - justify-content: center !important; - } - - h1.dynamic-title { - display: none; - - ~ .content { - margin-top: 2.5rem; - } - } -} /* max-width: 849px */ - -/* Sidebar is visible */ -@media all and (min-width: 850px) { - /* Solved jumping scrollbar */ - html { - overflow-y: scroll; - } - - #main-wrapper { - margin-left: $sidebar-width; - } - - #sidebar { - .profile-wrapper { - margin-top: 3rem; - } - } - - #search-hints { - display: none; - } - - search { - max-width: $search-max-width; - } - - #search-result-wrapper { - max-width: $main-content-max-width; - justify-content: start !important; - } - - main { - h1 { - margin-top: 3rem; - } - } - - div.content .table-wrapper > table { - min-width: 70%; - } - - /* button 'back-to-Top' position */ - #back-to-top { - right: 5%; - bottom: calc($footer-height - $back2top-size / 2); - } - - #topbar-title { - text-align: left; - } -} - -/* Pad horizontal */ -@media all and (min-width: 992px) and (max-width: 1199px) { - #main-wrapper > .container .col-lg-11 { - flex: 0 0 96%; - max-width: 96%; - } -} - -/* Compact icons in sidebar & panel hidden */ -@media all and (min-width: 850px) and (max-width: 1199px) { - #search-results > div { - max-width: 700px; - } - - #breadcrumb { - width: 65%; - overflow: hidden; - text-overflow: ellipsis; - word-break: keep-all; - white-space: nowrap; - } -} - -/* panel hidden */ -@media all and (max-width: 1199px) { - #panel-wrapper { - display: none; - } - - #main-wrapper > .container > div.row { - justify-content: center !important; - } -} - -/* --- desktop mode, both sidebar and panel are visible --- */ - -@media all and (min-width: 1200px) { - search { - margin-right: 4rem; - } - - #search-input { - transition: all 0.3s ease-in-out; - } - - #search-results > article { - width: 45%; - - &:nth-child(odd) { - margin-right: 1.5rem; - } - - &:nth-child(even) { - margin-left: 1.5rem; - } - - &:last-child:nth-child(odd) { - position: relative; - right: 24.3%; - } - } - - .content { - font-size: 1.03rem; - } -} - -@media all and (min-width: 1400px) { - #back-to-top { - right: calc((100vw - $sidebar-width - 1140px) / 2 + 3rem); - } -} - -@media all and (min-width: 1650px) { - $icon-gap: 1rem; - - #main-wrapper { - margin-left: $sidebar-width-large; - } - - #topbar-wrapper { - left: $sidebar-width-large; - } - - search { - margin-right: calc( - $main-content-max-width / 4 - $search-max-width - 0.75rem - ); - } - - #main-wrapper > .container { - max-width: $main-content-max-width; - - @include pl-pr(1.75rem, true); - } - - main.col-12, - #tail-wrapper { - padding-right: 4.5rem !important; - } - - #back-to-top { - right: calc( - (100vw - $sidebar-width-large - $main-content-max-width) / 2 + 2rem - ); - } - - #sidebar { - width: $sidebar-width-large; - - .profile-wrapper { - margin-top: 3.5rem; - margin-bottom: 2.5rem; - padding-left: 3.5rem; - } - - ul { - li.nav-item { - @include pl-pr(2.75rem); - } - } - - .sidebar-bottom { - padding-left: 2.75rem; - margin-bottom: 1.75rem; - - a:not(:last-child) { - margin-right: $sb-btn-gap-lg; - } - - .icon-border { - @include ml-mr(calc(($sb-btn-gap-lg - $btn-border-width) / 2)); - } - } - } -} /* min-width: 1650px */ diff --git a/_sass/base/_base.scss b/_sass/base/_base.scss new file mode 100644 index 0000000..19f153b --- /dev/null +++ b/_sass/base/_base.scss @@ -0,0 +1,476 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; +@use '../themes/light'; +@use '../themes/dark'; + +:root { + font-size: 16px; +} + +html { + @media (prefers-color-scheme: light) { + &:not([data-mode]), + &[data-mode='light'] { + @include light.styles; + } + + &[data-mode='dark'] { + @include dark.styles; + } + } + + @media (prefers-color-scheme: dark) { + &:not([data-mode]), + &[data-mode='dark'] { + @include dark.styles; + } + + &[data-mode='light'] { + @include light.styles; + } + } + + @include bp.lg { + overflow-y: scroll; + } +} + +body { + background: var(--main-bg); + padding: env(safe-area-inset-top) env(safe-area-inset-right) + env(safe-area-inset-bottom) env(safe-area-inset-left); + color: var(--text-color); + -webkit-font-smoothing: antialiased; + font-family: v.$font-family-base; +} + +h1.dynamic-title { + @include bp.lt(bp.get(lg)) { + display: none; + + ~ .content { + margin-top: 2.5rem; + } + } +} + +main { + &.col-12 { + @include bp.xxxl { + padding-right: 4.5rem !important; + } + } +} + +.preview-img { + aspect-ratio: 40 / 21; + width: 100%; + height: 100%; + overflow: hidden; + + @extend %rounded; + + &:not(.no-bg) { + background: var(--img-bg); + } + + img { + height: 100%; + -o-object-fit: cover; + object-fit: cover; + + @extend %rounded; + + @at-root #post-list & { + width: 100%; + } + } +} + +.post-preview { + @extend %rounded; + + border: 0; + background: var(--card-bg); + box-shadow: var(--card-shadow); + + &::before { + @extend %rounded; + + content: ''; + width: 100%; + height: 100%; + position: absolute; + background-color: var(--card-hovor-bg); + opacity: 0; + transition: opacity 0.35s ease-in-out; + } + + &:hover { + &::before { + opacity: 0.3; + } + } +} + +.post-meta { + @extend %text-sm; + + a { + &:not([class]):hover { + @extend %link-hover; + } + } + + em { + @extend %normal-font-style; + } +} + +.content { + font-size: 1.08rem; + margin-top: 2rem; + overflow-wrap: break-word; + + @include bp.xl { + font-size: 1.03rem; + } + + a { + &.popup { + @extend %no-cursor; + @extend %img-caption; + @include mx.mt-mb(0.5rem); + + cursor: zoom-in; + } + + &:not(.img-link) { + @extend %link-underline; + + &:hover { + @extend %link-hover; + } + } + } + + ol, + ul { + &:not([class]), + &.task-list { + -webkit-padding-start: 1.75rem; + padding-inline-start: 1.75rem; + + li { + margin: 0.25rem 0; + padding-left: 0.25rem; + } + + ol, + ul { + -webkit-padding-start: 1.25rem; + padding-inline-start: 1.25rem; + margin: 0.5rem 0; + } + } + } + + ul.task-list { + -webkit-padding-start: 1.25rem; + padding-inline-start: 1.25rem; + + li { + list-style-type: none; + padding-left: 0; + + /* checkbox icon */ + > i { + width: 2rem; + margin-left: -1.25rem; + color: var(--checkbox-color); + + &.checked { + color: var(--checkbox-checked-color); + } + } + + ul { + -webkit-padding-start: 1.75rem; + padding-inline-start: 1.75rem; + } + } + + input[type='checkbox'] { + margin: 0 0.5rem 0.2rem -1.3rem; + vertical-align: middle; + } + } /* ul */ + + dl > dd { + margin-left: 1rem; + } + + ::marker { + color: var(--text-muted-color); + } + + .table-wrapper > table { + @include bp.lg { + min-width: 70%; + } + } +} /* .content */ + +.tag:hover { + @extend %tag-hover; +} + +.post-tag { + display: inline-block; + min-width: 2rem; + text-align: center; + border-radius: 0.5rem; + border: 1px solid var(--btn-border-color); + padding: 0 0.4rem; + color: var(--text-muted-color); + line-height: 1.3rem; + + &:not(:last-child) { + margin-right: 0.2rem; + } +} + +.rounded-10 { + border-radius: 10px !important; +} + +.img-link { + color: transparent; + display: inline-flex; +} + +.shimmer { + overflow: hidden; + position: relative; + background: var(--img-bg); + + &::before { + content: ''; + position: absolute; + background: var(--shimmer-bg); + height: 100%; + width: 100%; + -webkit-animation: shimmer 1.3s infinite; + animation: shimmer 1.3s infinite; + } + + @-webkit-keyframes shimmer { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(100%); + } + } + + @keyframes shimmer { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(100%); + } + } +} + +.embed-video { + width: 100%; + height: 100%; + margin-bottom: 1rem; + aspect-ratio: 16 / 9; + + @extend %rounded; + + &.twitch { + aspect-ratio: 310 / 189; + } + + &.file { + display: block; + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + margin: auto; + margin-bottom: 0; + } + + @extend %img-caption; +} + +.embed-audio { + width: 100%; + display: block; + + @extend %img-caption; +} + +/* --- Effects classes --- */ + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.btn-box-shadow { + box-shadow: var(--card-shadow); +} + +/* overwrite bootstrap muted */ +.text-muted { + color: var(--text-muted-color) !important; +} + +/* Overwrite bootstrap tooltip */ +.tooltip-inner { + font-size: 0.7rem; + max-width: 220px; + text-align: left; +} + +/* Overwrite bootstrap outline button */ +.btn.btn-outline-primary { + &:not(.disabled):hover { + border-color: #007bff !important; + } +} + +.disabled { + color: rgb(206, 196, 196); + pointer-events: auto; + cursor: not-allowed; +} + +.hide-border-bottom { + border-bottom: none !important; +} + +.input-focus { + box-shadow: none; + border-color: var(--input-focus-border-color) !important; + background: center !important; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} + +.left { + float: left; + margin: 0.75rem 1rem 1rem 0; +} + +.right { + float: right; + margin: 0.75rem 0 1rem 1rem; +} + +/* --- Overriding --- */ + +/* mermaid */ +.mermaid { + text-align: center; +} + +/* MathJax */ +mjx-container { + overflow-y: hidden; + min-width: auto !important; +} + +@media (hover: hover) { + #sidebar ul > li:last-child::after { + transition: top 0.5s ease; + } + + .nav-link { + transition: background-color 0.3s ease-in-out; + } + + .post-preview { + transition: background-color 0.35s ease-in-out; + } +} + +#mask { + inset: 0 0 0 0; +} + +#main-wrapper { + position: relative; + + @include mx.pl-pr(0); + + @include bp.lt(bp.get(lg)) { + @include mx.slide; + } + + @include bp.lg { + margin-left: v.$sidebar-width; + } + + @include bp.xxxl { + margin-left: v.$sidebar-width-large; + } + + > .container { + min-height: 100vh; + + @include bp.lte(bp.get(md)) { + @include mx.max-w-100; + @include mx.pl-pr(0); + } + + @include bp.lt(bp.get(lg)) { + max-width: 100%; + } + + /* Pad horizontal */ + @include bp.between(992px, calc(#{bp.get(xl)} - 1px)) { + .col-lg-11 { + flex: 0 0 96%; + max-width: 96%; + } + } + + @include bp.lt(bp.get(xl)) { + > .row { + justify-content: center !important; + } + } + + @include bp.xxxl { + max-width: v.$main-content-max-width; + + @include mx.pl-pr(1.75rem, true); + } + } +} + +/* --- basic wrappers --- */ + +#topbar-wrapper.row, +#main-wrapper > .container > .row, +#search-result-wrapper > .row { + @include mx.ml-mr(0); +} + +#tail-wrapper { + @include bp.xxxl { + padding-right: 4.5rem !important; + } + + > :not(script) { + margin-top: 3rem; + } +} diff --git a/_sass/base/_index.scss b/_sass/base/_index.scss new file mode 100644 index 0000000..611d28f --- /dev/null +++ b/_sass/base/_index.scss @@ -0,0 +1,4 @@ +@forward 'reset'; +@forward 'base'; +@forward 'typography'; +@forward 'syntax'; diff --git a/_sass/base/_reset.scss b/_sass/base/_reset.scss new file mode 100644 index 0000000..1e5a629 --- /dev/null +++ b/_sass/base/_reset.scss @@ -0,0 +1,41 @@ +@use '../abstracts/mixins' as *; + +::-webkit-input-placeholder { + @include placeholder; +} + +::-moz-placeholder { + @include placeholder; +} + +:-ms-input-placeholder { + @include placeholder; +} + +::-ms-input-placeholder { + @include placeholder; +} + +::placeholder { + @include placeholder; +} + +:focus::-webkit-input-placeholder { + @include placeholder-focus; +} + +:focus::-moz-placeholder { + @include placeholder-focus; +} + +:focus:-ms-input-placeholder { + @include placeholder-focus; +} + +:focus::-ms-input-placeholder { + @include placeholder-focus; +} + +:focus::placeholder { + @include placeholder-focus; +} diff --git a/_sass/addon/syntax.scss b/_sass/base/_syntax.scss similarity index 74% rename from _sass/addon/syntax.scss rename to _sass/base/_syntax.scss index 6bd7b40..69924fc 100644 --- a/_sass/addon/syntax.scss +++ b/_sass/base/_syntax.scss @@ -1,44 +1,7 @@ -/* -* The syntax highlight. -*/ - -@import 'colors/syntax-light'; -@import 'colors/syntax-dark'; - -html { - @media (prefers-color-scheme: light) { - &:not([data-mode]), - &[data-mode='light'] { - @include light-syntax; - } - - &[data-mode='dark'] { - @include dark-syntax; - } - } - - @media (prefers-color-scheme: dark) { - &:not([data-mode]), - &[data-mode='dark'] { - @include dark-syntax; - } - - &[data-mode='light'] { - @include light-syntax; - } - } -} - -/* -- code snippets -- */ - -%code-snippet-bg { - background-color: var(--highlight-bg-color); -} - -%code-snippet-padding { - padding-left: 1rem; - padding-right: 1.5rem; -} +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; .highlighter-rouge { color: var(--highlighter-rouge-color); @@ -59,7 +22,7 @@ html { pre { margin-bottom: 0; - font-size: $code-font-size; + font-size: v.$code-font-size; line-height: 1.4rem; word-wrap: normal; /* Fixed Safari overflow-x */ } @@ -101,10 +64,10 @@ code { color: var(--code-color); &.highlighter-rouge { - font-size: $code-font-size; + font-size: v.$code-font-size; padding: 3px 5px; word-break: break-word; - border-radius: $radius-sm; + border-radius: v.$radius-sm; background-color: var(--inline-code-bg); } @@ -150,9 +113,42 @@ div[class^='language-'] { box-shadow: var(--language-border-color) 0 0 0 1px; .content > & { - @include ml-mr(-1rem); + @include mx.ml-mr(-1rem); border-radius: 0; + + @include bp.sm { + @include mx.ml-mr(0); + + border-radius: v.$radius-lg; + } + } + + .code-header { + @include bp.sm { + @include mx.ml-mr(0); + + $dot-margin: 1rem; + + &::before { + content: ''; + display: inline-block; + margin-left: $dot-margin; + width: v.$code-dot-size; + height: v.$code-dot-size; + border-radius: 50%; + background-color: var(--code-header-muted-color); + box-shadow: (v.$code-dot-size + v.$code-dot-gap) 0 0 + var(--code-header-muted-color), + (v.$code-dot-size + v.$code-dot-gap) * 2 0 0 + var(--code-header-muted-color); + } + + span { + // center the text of label + margin-left: calc(($dot-margin + v.$code-dot-size) / 2 * -1); + } + } } .highlight { @@ -184,18 +180,18 @@ div { display: flex; justify-content: space-between; align-items: center; - height: $code-header-height; + height: v.$code-header-height; margin-left: 0.75rem; margin-right: 0.25rem; /* the label block */ span { - line-height: $code-header-height; + line-height: v.$code-header-height; /* label icon */ i { font-size: 1rem; - width: $code-icon-width; + width: v.$code-icon-width; color: var(--code-header-icon-color); &.small { @@ -223,8 +219,8 @@ div { @extend %rounded; border: 1px solid transparent; - height: $code-header-height; - width: $code-header-height; + height: v.$code-header-height; + width: v.$code-header-height; padding: 0; background-color: inherit; @@ -255,38 +251,3 @@ div { } } } - -@media all and (min-width: 576px) { - div[class^='language-'] { - .content > & { - @include ml-mr(0); - - border-radius: $radius-lg; - } - - .code-header { - @include ml-mr(0); - - $dot-margin: 1rem; - - &::before { - content: ''; - display: inline-block; - margin-left: $dot-margin; - width: $code-dot-size; - height: $code-dot-size; - border-radius: 50%; - background-color: var(--code-header-muted-color); - box-shadow: ($code-dot-size + $code-dot-gap) 0 0 - var(--code-header-muted-color), - ($code-dot-size + $code-dot-gap) * 2 0 0 - var(--code-header-muted-color); - } - - span { - // center the text of label - margin-left: calc(($dot-margin + $code-dot-size) / 2 * -1); - } - } - } -} diff --git a/_sass/base/_typography.scss b/_sass/base/_typography.scss new file mode 100644 index 0000000..4cf3964 --- /dev/null +++ b/_sass/base/_typography.scss @@ -0,0 +1,266 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; + +@for $i from 1 through 5 { + h#{$i} { + @extend %heading; + + @if $i > 1 { + @extend %anchor; + } + + @if $i < 5 { + $size-factor: 0.25rem; + + @if $i > 1 { + $size-factor: 0.18rem; + + main & { + @if $i == 2 { + margin: 2.5rem 0 1.25rem; + } @else { + margin: 2rem 0 1rem; + } + } + } + + & { + font-size: 1rem + (5 - $i) * $size-factor; + } + } @else { + font-size: 1.05rem; + } + } +} + +a { + @extend %link-color; + + text-decoration: none; +} + +img { + max-width: 100%; + height: auto; + transition: all 0.35s ease-in-out; + + .blur & { + $blur: 20px; + + -webkit-filter: blur($blur); + filter: blur($blur); + } +} + +blockquote { + border-left: 0.125rem solid var(--blockquote-border-color); + padding-left: 1rem; + color: var(--blockquote-text-color); + margin-top: 0.5rem; + + > p:last-child { + margin-bottom: 0; + } + + &[class^='prompt-'] { + border-left: 0; + position: relative; + padding: 1rem 1rem 1rem 3rem; + color: var(--prompt-text-color); + + @extend %rounded; + + &::before { + text-align: center; + width: 3rem; + position: absolute; + left: 0.25rem; + margin-top: 0.4rem; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + } + } + + @include mx.prompt('tip', '\f0eb', $fa-style: 'regular'); + @include mx.prompt('info', '\f06a', $rotate: 180); + @include mx.prompt('warning', '\f06a'); + @include mx.prompt('danger', '\f071'); +} + +kbd { + font-family: Lato, sans-serif; + display: inline-block; + vertical-align: middle; + line-height: 1.3rem; + min-width: 1.75rem; + text-align: center; + margin: 0 0.3rem; + padding-top: 0.1rem; + color: var(--kbd-text-color); + background-color: var(--kbd-bg-color); + border-radius: v.$radius-sm; + border: solid 1px var(--kbd-wrap-color); + box-shadow: inset 0 -2px 0 var(--kbd-wrap-color); +} + +hr { + border-color: var(--main-border-color); + opacity: 1; +} + +footer { + background-color: var(--main-bg); + height: v.$footer-height; + border-top: 1px solid var(--main-border-color); + + @extend %text-xs; + + a { + @extend %text-highlight; + + &:hover { + @extend %link-hover; + } + } + + em { + @extend %text-highlight; + } + + p { + text-align: center; + margin-bottom: 0; + } +} + +/* fontawesome icons */ +i { + &.far, + &.fas { + @extend %no-cursor; + } +} + +sup { + @extend %sup-fn-target; +} + +main { + line-height: 1.75; + + h1 { + margin-top: 2rem; + + @include bp.lg { + margin-top: 3rem; + } + } + + p { + > a.popup { + &:not(.normal):not(.left):not(.right) { + @include mx.align-center; + } + } + } + + .categories, + #tags, + #archives { + a:not(:hover) { + @extend %no-bottom-border; + } + } + + @include bp.lte(bp.get(sm)) { + .content { + > blockquote[class^='prompt-'] { + @include mx.ml-mr(-1rem); + + border-radius: 0; + max-width: none; + } + } + } +} + +.footnotes > ol { + padding-left: 2rem; + margin-top: 0.5rem; + + > li { + &:not(:last-child) { + margin-bottom: 0.3rem; + } + + @extend %sup-fn-target; + + > p { + margin-left: 0.25em; + + @include mx.mt-mb(0); + } + } +} + +.footnote { + @at-root a#{&} { + @include mx.ml-mr(1px); + @include mx.pl-pr(2px); + + border-bottom-style: none !important; + } +} + +.reversefootnote { + @at-root a#{&} { + font-size: 0.6rem; + line-height: 1; + position: relative; + bottom: 0.25em; + margin-left: 0.25em; + border-bottom-style: none !important; + } +} + +/* --- Begin of Markdown table style --- */ + +/* it will be created by Liquid */ +.table-wrapper { + overflow-x: auto; + margin-bottom: 1.5rem; + + > table { + min-width: 100%; + overflow-x: auto; + border-spacing: 0; + + thead { + border-bottom: solid 2px rgba(210, 215, 217, 0.75); + + th { + @extend %table-cell; + } + } + + tbody { + tr { + border-bottom: 1px solid var(--tb-border-color); + + &:nth-child(2n) { + background-color: var(--tb-even-bg); + } + + &:nth-child(2n + 1) { + background-color: var(--tb-odd-bg); + } + + td { + @extend %table-cell; + } + } + } /* tbody */ + } /* table */ +} diff --git a/_sass/colors/syntax-dark.scss b/_sass/colors/syntax-dark.scss deleted file mode 100644 index eb92204..0000000 --- a/_sass/colors/syntax-dark.scss +++ /dev/null @@ -1,164 +0,0 @@ -/* - * The syntax dark mode styles. - */ - -@mixin dark-syntax { - --language-border-color: #2d2d2d; - --highlight-bg-color: #151515; - --highlighter-rouge-color: #c9def1; - --highlight-lineno-color: #808080; - --inline-code-bg: rgba(255, 255, 255, 0.05); - --code-color: #b0b0b0; - --code-header-text-color: #6a6a6a; - --code-header-muted-color: #353535; - --code-header-icon-color: #565656; - --clipboard-checked-color: #2bcc2b; - --filepath-text-color: #cacaca; - - .highlight .gp { - color: #87939d; - } - - /* --- Syntax highlight theme from `rougify style base16.dark` --- */ - - .highlight table td { - padding: 5px; - } - - .highlight table pre { - margin: 0; - } - - .highlight, - .highlight .w { - color: #d0d0d0; - background-color: #151515; - } - - .highlight .err { - color: #151515; - background-color: #ac4142; - } - - .highlight .c, - .highlight .ch, - .highlight .cd, - .highlight .cm, - .highlight .cpf, - .highlight .c1, - .highlight .cs { - color: #848484; - } - - .highlight .cp { - color: #f4bf75; - } - - .highlight .nt { - color: #f4bf75; - } - - .highlight .o, - .highlight .ow { - color: #d0d0d0; - } - - .highlight .p, - .highlight .pi { - color: #d0d0d0; - } - - .highlight .gi { - color: #90a959; - } - - .highlight .gd { - color: #f08a8b; - background-color: #320000; - } - - .highlight .gh { - color: #6a9fb5; - background-color: #151515; - font-weight: bold; - } - - .highlight .k, - .highlight .kn, - .highlight .kp, - .highlight .kr, - .highlight .kv { - color: #aa759f; - } - - .highlight .kc { - color: #d28445; - } - - .highlight .kt { - color: #d28445; - } - - .highlight .kd { - color: #d28445; - } - - .highlight .s, - .highlight .sb, - .highlight .sc, - .highlight .dl, - .highlight .sd, - .highlight .s2, - .highlight .sh, - .highlight .sx, - .highlight .s1 { - color: #90a959; - } - - .highlight .sa { - color: #aa759f; - } - - .highlight .sr { - color: #75b5aa; - } - - .highlight .si { - color: #b76d45; - } - - .highlight .se { - color: #b76d45; - } - - .highlight .nn { - color: #f4bf75; - } - - .highlight .nc { - color: #f4bf75; - } - - .highlight .no { - color: #f4bf75; - } - - .highlight .na { - color: #6a9fb5; - } - - .highlight .m, - .highlight .mb, - .highlight .mf, - .highlight .mh, - .highlight .mi, - .highlight .il, - .highlight .mo, - .highlight .mx { - color: #90a959; - } - - .highlight .ss { - color: #90a959; - } -} diff --git a/_sass/colors/syntax-light.scss b/_sass/colors/syntax-light.scss deleted file mode 100644 index 76aa669..0000000 --- a/_sass/colors/syntax-light.scss +++ /dev/null @@ -1,210 +0,0 @@ -/* - * The syntax light mode code snippet colors. - */ - -@mixin light-syntax { - /* --- custom light colors --- */ - --language-border-color: #ececec; - --highlight-bg-color: #f6f8fa; - --highlighter-rouge-color: #3f596f; - --highlight-lineno-color: #9e9e9e; - --inline-code-bg: rgba(25, 25, 28, 0.05); - --code-color: #3a3a3a; - --code-header-text-color: #a3a3a3; - --code-header-muted-color: #e5e5e5; - --code-header-icon-color: #c9c8c8; - --clipboard-checked-color: #43c743; - - /* --- Syntax highlight theme from `rougify style github` --- */ - - .highlight table td { - padding: 5px; - } - - .highlight table pre { - margin: 0; - } - - .highlight, - .highlight .w { - color: #24292f; - background-color: #f6f8fa; - } - - .highlight .k, - .highlight .kd, - .highlight .kn, - .highlight .kp, - .highlight .kr, - .highlight .kt, - .highlight .kv { - color: #cf222e; - } - - .highlight .gr { - color: #f6f8fa; - } - - .highlight .gd { - color: #82071e; - background-color: #ffebe9; - } - - .highlight .nb { - color: #953800; - } - - .highlight .nc { - color: #953800; - } - - .highlight .no { - color: #953800; - } - - .highlight .nn { - color: #953800; - } - - .highlight .sr { - color: #116329; - } - - .highlight .na { - color: #116329; - } - - .highlight .nt { - color: #116329; - } - - .highlight .gi { - color: #116329; - background-color: #dafbe1; - } - - .highlight .kc { - color: #0550ae; - } - - .highlight .l, - .highlight .ld, - .highlight .m, - .highlight .mb, - .highlight .mf, - .highlight .mh, - .highlight .mi, - .highlight .il, - .highlight .mo, - .highlight .mx { - color: #0550ae; - } - - .highlight .sb { - color: #0550ae; - } - - .highlight .bp { - color: #0550ae; - } - - .highlight .ne { - color: #0550ae; - } - - .highlight .nl { - color: #0550ae; - } - - .highlight .py { - color: #0550ae; - } - - .highlight .nv, - .highlight .vc, - .highlight .vg, - .highlight .vi, - .highlight .vm { - color: #0550ae; - } - - .highlight .o, - .highlight .ow { - color: #0550ae; - } - - .highlight .gh { - color: #0550ae; - font-weight: bold; - } - - .highlight .gu { - color: #0550ae; - font-weight: bold; - } - - .highlight .s, - .highlight .sa, - .highlight .sc, - .highlight .dl, - .highlight .sd, - .highlight .s2, - .highlight .se, - .highlight .sh, - .highlight .sx, - .highlight .s1, - .highlight .ss { - color: #0a3069; - } - - .highlight .nd { - color: #8250df; - } - - .highlight .nf, - .highlight .fm { - color: #8250df; - } - - .highlight .err { - color: #f6f8fa; - background-color: #82071e; - } - - .highlight .c, - .highlight .ch, - .highlight .cd, - .highlight .cm, - .highlight .cp, - .highlight .cpf, - .highlight .c1, - .highlight .cs { - color: #68717a; - } - - .highlight .gl { - color: #68717a; - } - - .highlight .gt { - color: #68717a; - } - - .highlight .ni { - color: #24292f; - } - - .highlight .si { - color: #24292f; - } - - .highlight .ge { - color: #24292f; - font-style: italic; - } - - .highlight .gs { - color: #24292f; - font-weight: bold; - } -} /* light-syntax */ diff --git a/_sass/colors/typography-light.scss b/_sass/colors/typography-light.scss deleted file mode 100644 index b6fc561..0000000 --- a/_sass/colors/typography-light.scss +++ /dev/null @@ -1,112 +0,0 @@ -/* - * The syntax light mode typography colors - */ - -@mixin light-scheme { - /* Framework color */ - --main-bg: white; - --mask-bg: #c1c3c5; - --main-border-color: #f3f3f3; - - /* Common color */ - --text-color: #34343c; - --text-muted-color: #757575; - --text-muted-highlight-color: inherit; - --heading-color: #2a2a2a; - --label-color: #585858; - --blockquote-border-color: #eeeeee; - --blockquote-text-color: #757575; - --link-color: #0056b2; - --link-underline-color: #dee2e6; - --button-bg: #ffffff; - --btn-border-color: #e9ecef; - --btn-backtotop-color: #686868; - --btn-backtotop-border-color: #f1f1f1; - --checkbox-color: #c5c5c5; - --checkbox-checked-color: #07a8f7; - --img-bg: radial-gradient( - circle, - rgb(255, 255, 255) 0%, - rgb(239, 239, 239) 100% - ); - --shimmer-bg: linear-gradient( - 90deg, - rgba(250, 250, 250, 0) 0%, - rgba(232, 230, 230, 1) 50%, - rgba(250, 250, 250, 0) 100% - ); - - /* Sidebar */ - --site-title-color: rgb(113, 113, 113); - --site-subtitle-color: #717171; - --sidebar-bg: #f6f8fa; - --sidebar-border-color: #efefef; - --sidebar-muted-color: #545454; - --sidebar-active-color: #1d1d1d; - --sidebar-hover-bg: rgb(223, 233, 241, 0.64); - --sidebar-btn-bg: white; - --sidebar-btn-color: #8e8e8e; - --avatar-border-color: white; - - /* Topbar */ - --topbar-bg: rgb(255, 255, 255, 0.7); - --topbar-text-color: rgb(78, 78, 78); - --search-border-color: rgb(240, 240, 240); - --search-icon-color: #c2c6cc; - --input-focus-border-color: #b8b8b8; - - /* Home page */ - --post-list-text-color: dimgray; - --btn-patinator-text-color: #555555; - --btn-paginator-hover-color: var(--sidebar-bg); - - /* Posts */ - --toc-highlight: #0550ae; - --toc-popup-border-color: lightgray; - --btn-share-color: gray; - --btn-share-hover-color: #0d6efd; - --card-bg: white; - --card-hovor-bg: #e2e2e2; - --card-shadow: rgb(104, 104, 104, 0.05) 0 2px 6px 0, - rgba(211, 209, 209, 0.15) 0 0 0 1px; - --footnote-target-bg: lightcyan; - --tb-odd-bg: #fbfcfd; - --tb-border-color: #eaeaea; - --dash-color: silver; - --kbd-wrap-color: #bdbdbd; - --kbd-text-color: var(--text-color); - --kbd-bg-color: white; - --prompt-text-color: rgb(46, 46, 46, 0.77); - --prompt-tip-bg: rgb(123, 247, 144, 0.2); - --prompt-tip-icon-color: #03b303; - --prompt-info-bg: #e1f5fe; - --prompt-info-icon-color: #0070cb; - --prompt-warning-bg: rgb(255, 243, 205); - --prompt-warning-icon-color: #ef9c03; - --prompt-danger-bg: rgb(248, 215, 218, 0.56); - --prompt-danger-icon-color: #df3c30; - - /* Tags */ - --tag-border: #dee2e6; - --tag-shadow: var(--btn-border-color); - --tag-hover: rgb(222, 226, 230); - --search-tag-bg: #f8f9fa; - - /* Categories */ - --categories-border: rgba(0, 0, 0, 0.125); - --categories-hover-bg: var(--btn-border-color); - --categories-icon-hover-color: darkslategray; - - /* Archive */ - --timeline-color: rgba(0, 0, 0, 0.075); - --timeline-node-bg: #c2c6cc; - --timeline-year-dot-color: #ffffff; - - [class^='prompt-'] { - --link-underline-color: rgb(219, 216, 216); - } - - .dark { - display: none; - } -} /* light-scheme */ diff --git a/_sass/components/_buttons.scss b/_sass/components/_buttons.scss new file mode 100644 index 0000000..bd7363e --- /dev/null +++ b/_sass/components/_buttons.scss @@ -0,0 +1,51 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; + +#back-to-top { + visibility: hidden; + opacity: 0; + z-index: 1; + cursor: pointer; + position: fixed; + right: 1rem; + bottom: calc(v.$footer-height-large - v.$back2top-size / 2); + background: var(--button-bg); + color: var(--btn-backtotop-color); + padding: 0; + width: v.$back2top-size; + height: v.$back2top-size; + border-radius: 50%; + border: 1px solid var(--btn-backtotop-border-color); + transition: opacity 0.5s ease-in-out, transform 0.2s ease-out; + + @include bp.lg { + right: 5%; + bottom: calc(v.$footer-height - v.$back2top-size / 2); + } + + @include bp.xxl { + right: calc((100vw - v.$sidebar-width - 1140px) / 2 + 3rem); + } + + @include bp.xxxl { + right: calc( + (100vw - v.$sidebar-width-large - v.$main-content-max-width) / 2 + 2rem + ); + } + + &:hover { + transform: translate3d(0, -5px, 0); + -webkit-transform: translate3d(0, -5px, 0); + } + + i { + line-height: v.$back2top-size; + position: relative; + bottom: 2px; + } + + &.show { + opacity: 1; + visibility: visible; + } +} diff --git a/_sass/components/_index.scss b/_sass/components/_index.scss new file mode 100644 index 0000000..ffbb908 --- /dev/null +++ b/_sass/components/_index.scss @@ -0,0 +1,2 @@ +@forward 'buttons'; +@forward 'popups'; diff --git a/_sass/components/_popups.scss b/_sass/components/_popups.scss new file mode 100644 index 0000000..ca3e2fc --- /dev/null +++ b/_sass/components/_popups.scss @@ -0,0 +1,172 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/placeholders'; + +/* PWA update popup */ +#notification { + @-webkit-keyframes popup { + from { + opacity: 0; + bottom: 0; + } + } + + @keyframes popup { + from { + opacity: 0; + bottom: 0; + } + } + + .toast-header { + background: none; + border-bottom: none; + color: inherit; + } + + .toast-body { + font-family: Lato, sans-serif; + line-height: 1.25rem; + + button { + font-size: 90%; + min-width: 4rem; + } + } + + &.toast { + &.show { + display: block; + min-width: 20rem; + border-radius: 0.5rem; + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + background-color: rgba(255, 255, 255, 0.5); + color: #1b1b1eba; + position: fixed; + left: 50%; + bottom: 20%; + transform: translateX(-50%); + -webkit-animation: popup 0.8s; + animation: popup 0.8s; + } + } +} + +#toc-popup { + $slide-in: slide-in 0.3s ease-out; + $slide-out: slide-out 0.3s ease-out; + $curtain-height: 2rem; + $backdrop: blur(5px); + + border-color: var(--toc-popup-border-color); + border-width: 1px; + border-radius: v.$radius-lg; + color: var(--text-color); + background: var(--card-bg); + margin-top: v.$topbar-height; + min-width: 20rem; + font-size: 1.05rem; + + @include bp.sm { + max-width: 32rem; + } + + &[open] { + -webkit-animation: $slide-in; + animation: $slide-in; + } + + &[closing] { + -webkit-animation: $slide-out; + animation: $slide-out; + } + + @include bp.lg { + left: v.$sidebar-width; + } + + .header { + @extend %btn-color; + + position: -webkit-sticky; + position: sticky; + top: 0; + background-color: inherit; + border-bottom: 1px solid var(--main-border-color); + + .label { + font-family: v.$font-family-heading; + } + } + + button { + > i { + font-size: 1.25rem; + vertical-align: middle; + } + + &:focus-visible { + box-shadow: none; + } + } + + ul { + list-style-type: none; + padding-left: 0; + + li { + ul, + & + li { + margin-top: 0.25rem; + } + + a { + display: flex; + line-height: 1.5; + padding: 0.375rem 0; + padding-right: 1.125rem; + + &.toc-link::before { + display: none; + } + } + } + } + + @for $i from 2 through 4 { + .node-name--H#{$i} { + padding-left: 1.125rem * ($i - 1); + } + } + + .is-active-link { + color: var(--toc-highlight) !important; + font-weight: 600; + } + + &::-webkit-backdrop { + -webkit-backdrop-filter: $backdrop; + backdrop-filter: $backdrop; + } + + &::backdrop { + -webkit-backdrop-filter: $backdrop; + backdrop-filter: $backdrop; + } + + &::after { + display: flex; + content: ''; + position: relative; + background: linear-gradient(transparent, var(--card-bg) 70%); + height: $curtain-height; + } + + #toc-popup-content { + overflow: auto; + max-height: calc(100vh - 4 * v.$topbar-height); + font-family: v.$font-family-heading; + margin-bottom: -$curtain-height; + } +} diff --git a/_sass/layout/_footer.scss b/_sass/layout/_footer.scss new file mode 100644 index 0000000..fd49ea0 --- /dev/null +++ b/_sass/layout/_footer.scss @@ -0,0 +1,36 @@ +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/variables' as v; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; + +footer { + background-color: var(--main-bg); + height: v.$footer-height; + border-top: 1px solid var(--main-border-color); + + @extend %text-xs; + + @include bp.lt(bp.get(lg)) { + @include mx.slide; + + height: v.$footer-height-large; + padding: 1.5rem 0; + } + + a { + @extend %text-highlight; + + &:hover { + @extend %link-hover; + } + } + + em { + @extend %text-highlight; + } + + p { + text-align: center; + margin-bottom: 0; + } +} diff --git a/_sass/layout/_index.scss b/_sass/layout/_index.scss new file mode 100644 index 0000000..fa75daf --- /dev/null +++ b/_sass/layout/_index.scss @@ -0,0 +1,4 @@ +@forward 'sidebar'; +@forward 'topbar'; +@forward 'panel'; +@forward 'footer'; diff --git a/_sass/layout/_panel.scss b/_sass/layout/_panel.scss new file mode 100644 index 0000000..bb5c2bc --- /dev/null +++ b/_sass/layout/_panel.scss @@ -0,0 +1,66 @@ +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; + +.access { + top: 2rem; + transition: top 0.2s ease-in-out; + margin-top: 3rem; + margin-bottom: 4rem; + + &:only-child { + position: -webkit-sticky; + position: sticky; + } + + > section { + padding-left: 1rem; + border-left: 1px solid var(--main-border-color); + + &:not(:last-child) { + margin-bottom: 4rem; + } + } + + .content { + font-size: 0.9rem; + } +} + +#panel-wrapper { + /* the headings */ + .panel-heading { + font-family: inherit; + line-height: inherit; + + @include mx.label(inherit); + } + + .post-tag { + line-height: 1.05rem; + font-size: 0.85rem; + border-radius: 0.8rem; + padding: 0.3rem 0.5rem; + margin: 0 0.35rem 0.5rem 0; + + &:hover { + transition: all 0.3s ease-in; + } + } + + @include bp.lt(bp.get(xl)) { + display: none; + } +} + +#access-lastmod { + a { + color: inherit; + + &:hover { + @extend %link-hover; + } + + @extend %no-bottom-border; + } +} diff --git a/_sass/layout/_sidebar.scss b/_sass/layout/_sidebar.scss new file mode 100644 index 0000000..eaad470 --- /dev/null +++ b/_sass/layout/_sidebar.scss @@ -0,0 +1,258 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/mixins' as mx; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/placeholders'; + +$btn-border-width: 3px; +$btn-mb: 0.5rem; +$sidebar-display: 'sidebar-display'; /* the attribute for sidebar display */ + +#sidebar { + @include mx.pl-pr(0); + + position: fixed; + top: 0; + left: 0; + height: 100%; + overflow-y: auto; + width: v.$sidebar-width; + background: var(--sidebar-bg); + border-right: 1px solid var(--sidebar-border-color); + + /* Hide scrollbar for IE, Edge and Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + + /* Hide scrollbar for Chrome, Safari and Opera */ + &::-webkit-scrollbar { + display: none; + } + + @include bp.lt(bp.get(lg)) { + @include mx.slide; + + transform: translateX(-#{v.$sidebar-width}); /* hide */ + -webkit-transform: translateX(-#{v.$sidebar-width}); + + [#{$sidebar-display}] & { + transform: translateX(0); + } + } + + @include bp.xxxl { + width: v.$sidebar-width-large; + } + + %sidebar-link-hover { + &:hover { + color: var(--sidebar-active-color); + } + } + + a { + @extend %sidebar-links; + } + + #avatar { + display: block; + width: 6.5rem; + height: 6.5rem; + overflow: hidden; + box-shadow: var(--avatar-border-color) 0 0 0 2px; + transform: translateZ(0); /* fixed the zoom in Safari */ + + @include bp.sm { + width: 7rem; + height: 7rem; + } + + img { + transition: transform 0.5s; + + &:hover { + transform: scale(1.2); + } + } + } + + .profile-wrapper { + @include mx.mt-mb(2.5rem); + @extend %clickable-transition; + + padding-left: 2.5rem; + padding-right: 1.25rem; + width: 100%; + + @include bp.lg { + margin-top: 3rem; + } + + @include bp.xxxl { + margin-top: 3.5rem; + margin-bottom: 2.5rem; + padding-left: 3.5rem; + } + } + + .site-title { + @extend %clickable-transition; + @extend %sidebar-link-hover; + + font-family: inherit; + font-weight: 900; + font-size: 1.75rem; + line-height: 1.2; + letter-spacing: 0.25px; + margin-top: 1.25rem; + margin-bottom: 0.5rem; + width: fit-content; + color: var(--site-title-color); + } + + .site-subtitle { + font-size: 95%; + color: var(--site-subtitle-color); + margin-top: 0.25rem; + word-spacing: 1px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + ul { + margin-bottom: 2rem; + + li.nav-item { + opacity: 0.9; + width: 100%; + + @include mx.pl-pr(1.5rem); + + @include bp.xxxl { + @include mx.pl-pr(2.75rem); + } + + a.nav-link { + @include mx.pt-pb(0.6rem); + + display: flex; + align-items: center; + border-radius: 0.75rem; + font-weight: 600; + + &:hover { + background-color: var(--sidebar-hover-bg); + } + + i { + font-size: 95%; + opacity: 0.8; + margin-right: 1.5rem; + } + + span { + font-size: 90%; + letter-spacing: 0.2px; + } + } + + &.active { + .nav-link { + color: var(--sidebar-active-color); + background-color: var(--sidebar-hover-bg); + + span { + opacity: 1; + } + } + } + + &:not(:first-child) { + margin-top: 0.25rem; + } + } + } + + .sidebar-bottom { + padding-left: 2rem; + padding-right: 1rem; + margin-bottom: 1.5rem; + + @include bp.xxxl { + padding-left: 2.75rem; + margin-bottom: 1.75rem; + } + + $btn-size: 1.75rem; + + %button { + width: $btn-size; + height: $btn-size; + margin-bottom: $btn-mb; // multi line gap + border-radius: 50%; + color: var(--sidebar-btn-color); + background-color: var(--sidebar-btn-bg); + text-align: center; + display: flex; + align-items: center; + justify-content: center; + + &:not(:focus-visible) { + box-shadow: var(--sidebar-border-color) 0 0 0 1px; + } + + &:hover { + background-color: var(--sidebar-hover-bg); + } + } + + a { + @extend %button; + @extend %sidebar-link-hover; + @extend %clickable-transition; + + &:not(:last-child) { + margin-right: v.$sb-btn-gap; + + @include bp.xxxl { + margin-right: v.$sb-btn-gap-lg; + } + } + } + + i { + line-height: $btn-size; + } + + #mode-toggle { + @extend %button; + @extend %sidebar-links; + @extend %sidebar-link-hover; + } + + .icon-border { + @extend %no-cursor; + @include mx.ml-mr(calc((v.$sb-btn-gap - $btn-border-width) / 2)); + + background-color: var(--sidebar-btn-color); + content: ''; + width: $btn-border-width; + height: $btn-border-width; + border-radius: 50%; + margin-bottom: $btn-mb; + + @include bp.xxxl { + @include mx.ml-mr(calc((v.$sb-btn-gap-lg - $btn-border-width) / 2)); + } + } + } /* .sidebar-bottom */ +} /* #sidebar */ + +[#{$sidebar-display}] { + #main-wrapper { + @include bp.lt(bp.get(lg)) { + transform: translateX(v.$sidebar-width); + } + } +} diff --git a/_sass/layout/_topbar.scss b/_sass/layout/_topbar.scss new file mode 100644 index 0000000..eb0aea9 --- /dev/null +++ b/_sass/layout/_topbar.scss @@ -0,0 +1,86 @@ +@use '../abstracts/variables' as v; +@use '../abstracts/mixins' as mx; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/placeholders'; + +#topbar-wrapper { + height: v.$topbar-height; + background-color: var(--topbar-bg); + + @include bp.lt(bp.get(lg)) { + @include mx.slide(top 0.2s ease); + + left: 0; + } +} + +#topbar { + @extend %btn-color; + + #breadcrumb { + font-size: 1rem; + color: var(--text-muted-color); + padding-left: 0.5rem; + + a:hover { + @extend %link-hover; + } + + span { + &:not(:last-child) { + &::after { + content: '›'; + padding: 0 0.3rem; + } + } + } + + @include bp.lt(bp.get(lg)) { + display: none; + } + + @include bp.between(bp.get(lg), calc(#{bp.get(xl)} - 1px)) { + width: 65%; + overflow: hidden; + text-overflow: ellipsis; + word-break: keep-all; + white-space: nowrap; + } + } + + @include bp.lte(bp.get(md)) { + @include mx.max-w-100; + } + + @include bp.lt(bp.get(lg)) { + max-width: 100%; + } +} + +#topbar-title { + display: none; + font-size: 1.1rem; + font-weight: 600; + font-family: sans-serif; + color: var(--topbar-text-color); + text-align: center; + width: 70%; + word-break: keep-all; + + @include bp.lt(bp.get(lg)) { + display: block; + } + + @include bp.lg { + text-align: left; + } +} + +#sidebar-trigger, +#search-trigger { + display: none; + + @include bp.lt(bp.get(lg)) { + display: block; + } +} diff --git a/_sass/main.bundle.scss b/_sass/main.bundle.scss index 52e893f..5d84f93 100644 --- a/_sass/main.bundle.scss +++ b/_sass/main.bundle.scss @@ -1,2 +1,2 @@ -@import 'dist/bootstrap'; -@import 'main'; +@use 'vendors/bootstrap'; +@use 'main'; diff --git a/_sass/main.scss b/_sass/main.scss index 1c2311d..3bbb70d 100644 --- a/_sass/main.scss +++ b/_sass/main.scss @@ -1,13 +1,4 @@ -@import 'colors/typography-light'; -@import 'colors/typography-dark'; -@import 'addon/variables'; -@import 'variables-hook'; -@import 'addon/module'; -@import 'addon/syntax'; -@import 'addon/commons'; -@import 'layout/home'; -@import 'layout/post'; -@import 'layout/tags'; -@import 'layout/archives'; -@import 'layout/categories'; -@import 'layout/category-tag'; +@forward 'base'; +@forward 'components'; +@forward 'layout'; +@forward 'pages'; diff --git a/_sass/layout/archives.scss b/_sass/pages/_archives.scss similarity index 95% rename from _sass/layout/archives.scss rename to _sass/pages/_archives.scss index fd1979b..86e77a8 100644 --- a/_sass/layout/archives.scss +++ b/_sass/pages/_archives.scss @@ -1,10 +1,17 @@ -/* - Style for Archives -*/ +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/placeholders'; #archives { letter-spacing: 0.03rem; + @include bp.lt(bp.get(sm)) { + margin-top: -1rem; + + ul { + letter-spacing: 0; + } + } + $timeline-width: 4px; %timeline { @@ -131,13 +138,3 @@ } } } /* #archives */ - -@media all and (max-width: 576px) { - #archives { - margin-top: -1rem; - - ul { - letter-spacing: 0; - } - } -} diff --git a/_sass/layout/categories.scss b/_sass/pages/_categories.scss similarity index 87% rename from _sass/layout/categories.scss rename to _sass/pages/_categories.scss index f12b963..64a2df5 100644 --- a/_sass/layout/categories.scss +++ b/_sass/pages/_categories.scss @@ -1,8 +1,7 @@ -/* - Style for Tab Categories -*/ +@use '../abstracts/variables' as v; +@use '../abstracts/placeholders'; -%category-icon-color { +%-category-icon-color { color: gray; } @@ -16,7 +15,7 @@ } .card-header { - $radius: calc($radius-lg - 1px); + $radius: calc(v.$radius-lg - 1px); padding: 0.75rem; border-radius: $radius; @@ -29,7 +28,7 @@ } i { - @extend %category-icon-color; + @extend %-category-icon-color; font-size: 86%; /* fontawesome icons */ } diff --git a/_sass/layout/category-tag.scss b/_sass/pages/_category-tag.scss similarity index 79% rename from _sass/layout/category-tag.scss rename to _sass/pages/_category-tag.scss index fe7d99c..0a82712 100644 --- a/_sass/layout/category-tag.scss +++ b/_sass/pages/_category-tag.scss @@ -1,6 +1,6 @@ -/* - Style for page Category and Tag -*/ +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; .dash { margin: 0 0.5rem 0.6rem 0.5rem; @@ -24,6 +24,10 @@ position: relative; top: 0.6rem; margin-right: 0.5rem; + + @include bp.lt(bp.get(sm)) { + margin: 0 0.5rem; + } } /* post's title */ @@ -31,6 +35,10 @@ @extend %no-bottom-border; font-size: 1.1rem; + + @include bp.lt(bp.get(sm)) { + @include mx.text-ellipsis; + } } } } @@ -53,18 +61,3 @@ margin-bottom: -1px; /* Avoid jumping */ } } - -@media all and (max-width: 576px) { - #page-category, - #page-tag { - ul > li { - &::before { - margin: 0 0.5rem; - } - - > a { - @include text-ellipsis; - } - } - } -} diff --git a/_sass/layout/home.scss b/_sass/pages/_home.scss similarity index 73% rename from _sass/layout/home.scss rename to _sass/pages/_home.scss index 7fff3ba..7a4bbf9 100644 --- a/_sass/layout/home.scss +++ b/_sass/pages/_home.scss @@ -1,10 +1,14 @@ -/* - Style for Homepage -*/ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/placeholders'; #post-list { margin-top: 2rem; + @include bp.lg { + margin-top: 2.5rem; + } + .card-wrapper { &:hover { text-decoration: none; @@ -20,7 +24,11 @@ background: none; %img-radius { - border-radius: $radius-lg $radius-lg 0 0; + border-radius: v.$radius-lg v.$radius-lg 0 0; + + @include bp.md { + border-radius: 0 v.$radius-lg v.$radius-lg 0; + } } .preview-img { @@ -35,6 +43,10 @@ height: 100%; padding: 1rem; + @include bp.md { + padding: 1.75rem 1.75rem 1.25rem; + } + .card-title { @extend %text-clip; @@ -46,14 +58,20 @@ color: var(--text-muted-color) !important; } - .card-text.content { - @extend %muted; + .card-text { + @include bp.md { + display: inherit !important; + } - p { - @extend %text-clip; + &.content { + @extend %muted; - line-height: 1.5; - margin: 0; + p { + @extend %text-clip; + + line-height: 1.5; + margin: 0; + } } } @@ -63,6 +81,10 @@ i { &:not(:first-child) { margin-left: 1.5rem; + + @include bp.md { + margin-left: 1.75rem; + } } } @@ -87,11 +109,28 @@ font-family: Lato, sans-serif; justify-content: space-evenly; + @include bp.lg { + font-size: 0.85rem; + justify-content: center; + } + a:hover { text-decoration: none; } .page-item { + @include bp.lt(bp.get(lg)) { + &:not(:first-child):not(:last-child) { + display: none; + } + } + + @include bp.lg { + &:not(:last-child) { + margin-right: 0.7rem; + } + } + .page-link { color: var(--btn-patinator-text-color); padding: 0 0.6rem; @@ -125,64 +164,10 @@ } } } /* .page-item */ -} /* .pagination */ -/* Tablet */ -@media all and (min-width: 768px) { - %img-radius { - border-radius: 0 $radius-lg $radius-lg 0; - } - - #post-list { - .card { - .card-body { - padding: 1.75rem 1.75rem 1.25rem 1.75rem; - - .card-text { - display: inherit !important; - } - - .post-meta { - i { - &:not(:first-child) { - margin-left: 1.75rem; - } - } - } - } - } - } -} - -/* Hide SideBar and TOC */ -@media all and (max-width: 830px) { - .pagination { - .page-item { - &:not(:first-child):not(:last-child) { - display: none; - } - } - } -} - -/* Sidebar is visible */ -@media all and (min-width: 831px) { - #post-list { - margin-top: 2.5rem; - } - - .pagination { - font-size: 0.85rem; - justify-content: center; - - .page-item { - &:not(:last-child) { - margin-right: 0.7rem; - } - } - - .page-index { + .page-index { + @include bp.lg { display: none; } - } /* .pagination */ + } } diff --git a/_sass/pages/_index.scss b/_sass/pages/_index.scss new file mode 100644 index 0000000..74e9ea6 --- /dev/null +++ b/_sass/pages/_index.scss @@ -0,0 +1,7 @@ +@forward 'search'; +@forward 'home'; +@forward 'post'; +@forward 'categories'; +@forward 'tags'; +@forward 'archives'; +@forward 'category-tag'; diff --git a/_sass/layout/post.scss b/_sass/pages/_post.scss similarity index 67% rename from _sass/layout/post.scss rename to _sass/pages/_post.scss index 891479e..d789050 100644 --- a/_sass/layout/post.scss +++ b/_sass/pages/_post.scss @@ -1,14 +1,15 @@ -/** - * Post-specific styles - */ +@use '../abstracts/variables' as v; +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/mixins' as mx; +@use '../abstracts/placeholders'; -%btn-post-nav { +%-btn-post-nav { width: 50%; position: relative; border-color: var(--btn-border-color); } -@mixin dot($pl: 0.25rem, $pr: 0.25rem) { +@mixin -dot($pl: 0.25rem, $pr: 0.25rem) { content: '\2022'; padding-left: $pl; padding-right: $pr; @@ -24,7 +25,7 @@ header { .post-meta { span + span::before { - @include dot; + @include -dot; } em, @@ -113,9 +114,20 @@ header { } /* .share-wrapper */ } +.post-tail-bottom { + @include bp.lte(bp.get(sm)) { + flex-wrap: wrap-reverse !important; + + > div:first-child { + width: 100%; + margin-top: 1rem; + } + } +} + .share-mastodon { /* See: https://github.com/justinribeiro/share-to-mastodon#properties */ - --wc-stm-font-family: $font-family-base; + --wc-stm-font-family: v.$font-family-base; --wc-stm-dialog-background-color: var(--card-bg); --wc-stm-form-button-border: 1px solid var(--btn-border-color); --wc-stm-form-submit-background-color: var(--sidebar-btn-bg); @@ -139,8 +151,13 @@ header { } .post-navigation { + @include bp.lt(bp.get(lg)) { + @include mx.pl-pr(0); + @include mx.ml-mr(-0.5rem); + } + .btn { - @extend %btn-post-nav; + @extend %-btn-post-nav; &:not(:hover) { color: var(--link-color); @@ -153,7 +170,7 @@ header { } &.disabled { - @extend %btn-post-nav; + @extend %-btn-post-nav; pointer-events: auto; cursor: not-allowed; @@ -173,12 +190,12 @@ header { } &:first-child { - border-radius: $radius-lg 0 0 $radius-lg; + border-radius: v.$radius-lg 0 0 v.$radius-lg; left: 0.5px; } &:last-child { - border-radius: 0 $radius-lg $radius-lg 0; + border-radius: 0 v.$radius-lg v.$radius-lg 0; right: 0.5px; } } @@ -298,23 +315,27 @@ header { top: 0; z-index: 1; margin: 0 -1rem; - height: $topbar-height; + height: v.$topbar-height; background: var(--main-bg); border-bottom: 1px solid var(--main-border-color); transition: all 0.2s ease-in-out; @extend %btn-color; + @include bp.xl { + display: none !important; + } + .label { @extend %heading; - margin-left: 0.25rem; + margin-left: 0.375rem; padding: 0 0.75rem; color: inherit; } &.invisible { - top: -$topbar-height; + top: -#{v.$topbar-height}; transition: none; } } @@ -322,11 +343,15 @@ header { #toc-solo-trigger { color: var(--text-muted-color); border-color: var(--btn-border-color); - border-radius: $radius-lg; + border-radius: v.$radius-lg; + + @include bp.xl { + display: none !important; + } .label { font-size: 1rem; - font-family: $font-family-heading; + font-family: v.$font-family-heading; } &:hover { @@ -338,7 +363,7 @@ header { @mixin slide-in { from { opacity: 0.7; - transform: translateY(-$topbar-height); + transform: translateY(-#{v.$topbar-height}); } to { @@ -354,7 +379,7 @@ header { } 100% { - transform: translateY(-$topbar-height); + transform: translateY(-#{v.$topbar-height}); opacity: 0; } } @@ -375,129 +400,11 @@ header { @include slide-out; } -#toc-popup { - $slide-in: slide-in 0.3s ease-out; - $slide-out: slide-out 0.3s ease-out; - $curtain-height: 2rem; - $backdrop: blur(5px); - - border-color: var(--toc-popup-border-color); - border-width: 1px; - border-radius: $radius-lg; - color: var(--text-color); - background: var(--card-bg); - margin-top: $topbar-height; - min-width: 20rem; - font-size: 1.05rem; - - @media all and (min-width: 576px) { - max-width: 32rem; - } - - &[open] { - -webkit-animation: $slide-in; - animation: $slide-in; - } - - &[closing] { - -webkit-animation: $slide-out; - animation: $slide-out; - } - - @media all and (min-width: 850px) { - left: $sidebar-width; - } - - .header { - @extend %btn-color; - - position: -webkit-sticky; - position: sticky; - top: 0; - background-color: inherit; - border-bottom: 1px solid var(--main-border-color); - - .label { - font-family: $font-family-heading; - } - } - - button { - > i { - font-size: 1.25rem; - vertical-align: middle; - } - - &:focus-visible { - box-shadow: none; - } - } - - ul { - list-style-type: none; - padding-left: 0; - - li { - ul, - & + li { - margin-top: 0.25rem; - } - - a { - display: flex; - line-height: 1.5; - padding: 0.375rem 0; - padding-right: 1.125rem; - - &.toc-link::before { - display: none; - } - } - } - } - - @for $i from 2 through 4 { - .node-name--H#{$i} { - padding-left: 1.125rem * ($i - 1); - } - } - - .is-active-link { - color: var(--toc-highlight) !important; - font-weight: 600; - } - - &::-webkit-backdrop { - -webkit-backdrop-filter: $backdrop; - backdrop-filter: $backdrop; - } - - &::backdrop { - -webkit-backdrop-filter: $backdrop; - backdrop-filter: $backdrop; - } - - &::after { - display: flex; - content: ''; - position: relative; - background: linear-gradient(transparent, var(--card-bg) 70%); - height: $curtain-height; - } - - #toc-popup-content { - overflow: auto; - max-height: calc(100vh - 4 * $topbar-height); - font-family: $font-family-heading; - margin-bottom: -$curtain-height; - } -} - /* --- Related Posts --- */ #related-posts { > h3 { - @include label(1.1rem, 600); + @include mx.label(1.1rem, 600); } time { @@ -540,47 +447,23 @@ header { } .share-label { - @include label(inherit, 400, inherit); + @include mx.label(inherit, 400, inherit); &::after { content: ':'; } } -@media all and (max-width: 576px) { - .post-tail-bottom { - flex-wrap: wrap-reverse !important; - - > div:first-child { - width: 100%; - margin-top: 1rem; - } - } -} - -@media all and (max-width: 768px) { - .content > p > img { +.content > p > img { + @include bp.lte(bp.get(md)) { max-width: calc(100% + 1rem); } } -/* Hide SideBar and TOC */ -@media all and (max-width: 849px) { - .post-navigation { - @include pl-pr(0); - @include ml-mr(-0.5rem); - } -} - -@media all and (min-width: 1200px) { - h2, - h3, - h4 { +h2, +h3, +h4 { + @include bp.xl { scroll-margin-top: 2rem; } - - #toc-bar, - #toc-solo-trigger { - display: none !important; - } } diff --git a/_sass/pages/_search.scss b/_sass/pages/_search.scss new file mode 100644 index 0000000..dfb044e --- /dev/null +++ b/_sass/pages/_search.scss @@ -0,0 +1,184 @@ +@use '../abstracts/breakpoints' as bp; +@use '../abstracts/variables' as v; +@use '../abstracts/placeholders'; + +search { + display: flex; + width: 100%; + border-radius: 1rem; + border: 1px solid var(--search-border-color); + background: var(--main-bg); + padding: 0 0.5rem; + + i { + z-index: 2; + font-size: 0.9rem; + color: var(--search-icon-color); + } + + @include bp.lt(bp.get(lg)) { + display: none; + } + + @include bp.lg { + max-width: v.$search-max-width; + } + + @include bp.xl { + margin-right: 4rem; + } + + @include bp.xxxl { + margin-right: calc( + v.$main-content-max-width / 4 - v.$search-max-width - 0.75rem + ); + } +} + +#search-result-wrapper { + display: none; + height: 100%; + width: 100%; + overflow: auto; + + .content { + margin-top: 2rem; + } + + @include bp.lt(bp.get(lg)) { + width: 100%; + + .content { + letter-spacing: 0; + } + } + + @include bp.lg { + max-width: v.$main-content-max-width; + justify-content: start !important; + } +} + +#search-results { + padding-bottom: 3rem; + + @include bp.between(bp.get(lg), calc(#{bp.get(xl)} - 1px)) { + > div { + max-width: 700px; + } + } + + a { + font-size: 1.4rem; + line-height: 1.5rem; + + &:hover { + @extend %link-hover; + } + + @extend %link-color; + @extend %no-bottom-border; + @extend %heading; + } + + > article { + width: 100%; + + &:not(:last-child) { + margin-bottom: 1rem; + } + + @include bp.xl { + width: 45%; + + &:nth-child(odd) { + margin-right: 1.5rem; + } + + &:nth-child(even) { + margin-left: 1.5rem; + } + + &:last-child:nth-child(odd) { + position: relative; + right: 24.3%; + } + } + + h2 { + line-height: 2.5rem; + } + + /* icons */ + i { + color: #818182; + margin-right: 0.15rem; + font-size: 80%; + } + + > p { + @extend %text-ellipsis; + + white-space: break-spaces; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + } + } +} + +/* 'Cancel' link */ +#search-cancel { + color: var(--link-color); + display: none; + white-space: nowrap; + + @extend %cursor-pointer; +} + +#search-input { + background: center; + border: 0; + border-radius: 0; + padding: 0.18rem 0.3rem; + color: var(--text-color); + height: auto; + + &:focus { + box-shadow: none; + } + + @include bp.xl { + transition: all 0.3s ease-in-out; + } +} + +#search-hints { + padding: 0 1rem; + + @include bp.lg { + display: none; + } + + h4 { + margin-bottom: 1.5rem; + } + + .post-tag { + display: inline-block; + line-height: 1rem; + font-size: 1rem; + background: var(--search-tag-bg); + border: none; + padding: 0.5rem; + margin: 0 1.25rem 1rem 0; + + &::before { + content: '#'; + color: var(--text-muted-color); + padding-right: 0.2rem; + } + + @extend %link-color; + } +} diff --git a/_sass/layout/tags.scss b/_sass/pages/_tags.scss similarity index 71% rename from _sass/layout/tags.scss rename to _sass/pages/_tags.scss index 4cf5d3b..d22f20d 100644 --- a/_sass/layout/tags.scss +++ b/_sass/pages/_tags.scss @@ -1,6 +1,4 @@ -/* - Styles for Tab Tags -*/ +@use '../abstracts/breakpoints' as bp; .tag { border-radius: 0.7em; @@ -17,3 +15,9 @@ font-family: Oswald, sans-serif; } } + +#tags { + @include bp.lt(bp.get(lg)) { + justify-content: center !important; + } +} diff --git a/_sass/colors/typography-dark.scss b/_sass/themes/_dark.scss similarity index 62% rename from _sass/colors/typography-dark.scss rename to _sass/themes/_dark.scss index 664c936..8c2f6ea 100644 --- a/_sass/colors/typography-dark.scss +++ b/_sass/themes/_dark.scss @@ -1,8 +1,6 @@ -/* - * The main dark mode styles - */ +@mixin styles { + color-scheme: dark; -@mixin dark-scheme { /* Framework color */ --main-bg: rgb(27, 27, 30); --mask-bg: rgb(68, 69, 70); @@ -100,7 +98,18 @@ --timeline-color: rgb(63, 65, 68); --timeline-year-dot-color: var(--timeline-color); - color-scheme: dark; + /* Code highlight colors */ + --language-border-color: #2d2d2d; + --highlight-bg-color: #151515; + --highlighter-rouge-color: #c9def1; + --highlight-lineno-color: #808080; + --inline-code-bg: rgba(255, 255, 255, 0.05); + --code-color: #b0b0b0; + --code-header-text-color: #6a6a6a; + --code-header-muted-color: #353535; + --code-header-icon-color: #565656; + --clipboard-checked-color: #2bcc2b; + --filepath-text-color: #cacaca; .light { display: none; @@ -144,4 +153,151 @@ #disqus_thread { color-scheme: none; } -} /* dark-scheme */ + + /* --- Syntax highlight theme from `rougify style base16.dark` --- */ + + .highlight .gp { + color: #87939d; + } + + .highlight table td { + padding: 5px; + } + + .highlight table pre { + margin: 0; + } + + .highlight, + .highlight .w { + color: #d0d0d0; + background-color: #151515; + } + + .highlight .err { + color: #151515; + background-color: #ac4142; + } + + .highlight .c, + .highlight .ch, + .highlight .cd, + .highlight .cm, + .highlight .cpf, + .highlight .c1, + .highlight .cs { + color: #848484; + } + + .highlight .cp { + color: #f4bf75; + } + + .highlight .nt { + color: #f4bf75; + } + + .highlight .o, + .highlight .ow { + color: #d0d0d0; + } + + .highlight .p, + .highlight .pi { + color: #d0d0d0; + } + + .highlight .gi { + color: #90a959; + } + + .highlight .gd { + color: #f08a8b; + background-color: #320000; + } + + .highlight .gh { + color: #6a9fb5; + background-color: #151515; + font-weight: bold; + } + + .highlight .k, + .highlight .kn, + .highlight .kp, + .highlight .kr, + .highlight .kv { + color: #aa759f; + } + + .highlight .kc { + color: #d28445; + } + + .highlight .kt { + color: #d28445; + } + + .highlight .kd { + color: #d28445; + } + + .highlight .s, + .highlight .sb, + .highlight .sc, + .highlight .dl, + .highlight .sd, + .highlight .s2, + .highlight .sh, + .highlight .sx, + .highlight .s1 { + color: #90a959; + } + + .highlight .sa { + color: #aa759f; + } + + .highlight .sr { + color: #75b5aa; + } + + .highlight .si { + color: #b76d45; + } + + .highlight .se { + color: #b76d45; + } + + .highlight .nn { + color: #f4bf75; + } + + .highlight .nc { + color: #f4bf75; + } + + .highlight .no { + color: #f4bf75; + } + + .highlight .na { + color: #6a9fb5; + } + + .highlight .m, + .highlight .mb, + .highlight .mf, + .highlight .mh, + .highlight .mi, + .highlight .il, + .highlight .mo, + .highlight .mx { + color: #90a959; + } + + .highlight .ss { + color: #90a959; + } +} diff --git a/_sass/themes/_light.scss b/_sass/themes/_light.scss new file mode 100644 index 0000000..14c3962 --- /dev/null +++ b/_sass/themes/_light.scss @@ -0,0 +1,313 @@ +@mixin styles { + /* Framework color */ + --main-bg: white; + --mask-bg: #c1c3c5; + --main-border-color: #f3f3f3; + + /* Common color */ + --text-color: #34343c; + --text-muted-color: #757575; + --text-muted-highlight-color: inherit; + --heading-color: #2a2a2a; + --label-color: #585858; + --blockquote-border-color: #eeeeee; + --blockquote-text-color: #757575; + --link-color: #0056b2; + --link-underline-color: #dee2e6; + --button-bg: #ffffff; + --btn-border-color: #e9ecef; + --btn-backtotop-color: #686868; + --btn-backtotop-border-color: #f1f1f1; + --checkbox-color: #c5c5c5; + --checkbox-checked-color: #07a8f7; + --img-bg: radial-gradient( + circle, + rgb(255, 255, 255) 0%, + rgb(239, 239, 239) 100% + ); + --shimmer-bg: linear-gradient( + 90deg, + rgba(250, 250, 250, 0) 0%, + rgba(232, 230, 230, 1) 50%, + rgba(250, 250, 250, 0) 100% + ); + + /* Sidebar */ + --site-title-color: rgb(113, 113, 113); + --site-subtitle-color: #717171; + --sidebar-bg: #f6f8fa; + --sidebar-border-color: #efefef; + --sidebar-muted-color: #545454; + --sidebar-active-color: #1d1d1d; + --sidebar-hover-bg: rgb(223, 233, 241, 0.64); + --sidebar-btn-bg: white; + --sidebar-btn-color: #8e8e8e; + --avatar-border-color: white; + + /* Topbar */ + --topbar-bg: rgb(255, 255, 255, 0.7); + --topbar-text-color: rgb(78, 78, 78); + --search-border-color: rgb(240, 240, 240); + --search-icon-color: #c2c6cc; + --input-focus-border-color: #b8b8b8; + + /* Home page */ + --post-list-text-color: dimgray; + --btn-patinator-text-color: #555555; + --btn-paginator-hover-color: var(--sidebar-bg); + + /* Posts */ + --toc-highlight: #0550ae; + --toc-popup-border-color: lightgray; + --btn-share-color: gray; + --btn-share-hover-color: #0d6efd; + --card-bg: white; + --card-hovor-bg: #e2e2e2; + --card-shadow: rgb(104, 104, 104, 0.05) 0 2px 6px 0, + rgba(211, 209, 209, 0.15) 0 0 0 1px; + --footnote-target-bg: lightcyan; + --tb-odd-bg: #fbfcfd; + --tb-border-color: #eaeaea; + --dash-color: silver; + --kbd-wrap-color: #bdbdbd; + --kbd-text-color: var(--text-color); + --kbd-bg-color: white; + --prompt-text-color: rgb(46, 46, 46, 0.77); + --prompt-tip-bg: rgb(123, 247, 144, 0.2); + --prompt-tip-icon-color: #03b303; + --prompt-info-bg: #e1f5fe; + --prompt-info-icon-color: #0070cb; + --prompt-warning-bg: rgb(255, 243, 205); + --prompt-warning-icon-color: #ef9c03; + --prompt-danger-bg: rgb(248, 215, 218, 0.56); + --prompt-danger-icon-color: #df3c30; + + /* Tags */ + --tag-border: #dee2e6; + --tag-shadow: var(--btn-border-color); + --tag-hover: rgb(222, 226, 230); + --search-tag-bg: #f8f9fa; + + /* Categories */ + --categories-border: rgba(0, 0, 0, 0.125); + --categories-hover-bg: var(--btn-border-color); + --categories-icon-hover-color: darkslategray; + + /* Archive */ + --timeline-color: rgba(0, 0, 0, 0.075); + --timeline-node-bg: #c2c6cc; + --timeline-year-dot-color: #ffffff; + + /* --- Custom code light mode colors --- */ + --language-border-color: #ececec; + --highlight-bg-color: #f6f8fa; + --highlighter-rouge-color: #3f596f; + --highlight-lineno-color: #9e9e9e; + --inline-code-bg: rgba(25, 25, 28, 0.05); + --code-color: #3a3a3a; + --code-header-text-color: #a3a3a3; + --code-header-muted-color: #e5e5e5; + --code-header-icon-color: #c9c8c8; + --clipboard-checked-color: #43c743; + + [class^='prompt-'] { + --link-underline-color: rgb(219, 216, 216); + } + + .dark { + display: none; + } + + /* --- Syntax highlight theme from `rougify style github` --- */ + + .highlight table td { + padding: 5px; + } + + .highlight table pre { + margin: 0; + } + + .highlight, + .highlight .w { + color: #24292f; + background-color: #f6f8fa; + } + + .highlight .k, + .highlight .kd, + .highlight .kn, + .highlight .kp, + .highlight .kr, + .highlight .kt, + .highlight .kv { + color: #cf222e; + } + + .highlight .gr { + color: #f6f8fa; + } + + .highlight .gd { + color: #82071e; + background-color: #ffebe9; + } + + .highlight .nb { + color: #953800; + } + + .highlight .nc { + color: #953800; + } + + .highlight .no { + color: #953800; + } + + .highlight .nn { + color: #953800; + } + + .highlight .sr { + color: #116329; + } + + .highlight .na { + color: #116329; + } + + .highlight .nt { + color: #116329; + } + + .highlight .gi { + color: #116329; + background-color: #dafbe1; + } + + .highlight .kc { + color: #0550ae; + } + + .highlight .l, + .highlight .ld, + .highlight .m, + .highlight .mb, + .highlight .mf, + .highlight .mh, + .highlight .mi, + .highlight .il, + .highlight .mo, + .highlight .mx { + color: #0550ae; + } + + .highlight .sb { + color: #0550ae; + } + + .highlight .bp { + color: #0550ae; + } + + .highlight .ne { + color: #0550ae; + } + + .highlight .nl { + color: #0550ae; + } + + .highlight .py { + color: #0550ae; + } + + .highlight .nv, + .highlight .vc, + .highlight .vg, + .highlight .vi, + .highlight .vm { + color: #0550ae; + } + + .highlight .o, + .highlight .ow { + color: #0550ae; + } + + .highlight .gh { + color: #0550ae; + font-weight: bold; + } + + .highlight .gu { + color: #0550ae; + font-weight: bold; + } + + .highlight .s, + .highlight .sa, + .highlight .sc, + .highlight .dl, + .highlight .sd, + .highlight .s2, + .highlight .se, + .highlight .sh, + .highlight .sx, + .highlight .s1, + .highlight .ss { + color: #0a3069; + } + + .highlight .nd { + color: #8250df; + } + + .highlight .nf, + .highlight .fm { + color: #8250df; + } + + .highlight .err { + color: #f6f8fa; + background-color: #82071e; + } + + .highlight .c, + .highlight .ch, + .highlight .cd, + .highlight .cm, + .highlight .cp, + .highlight .cpf, + .highlight .c1, + .highlight .cs { + color: #68717a; + } + + .highlight .gl { + color: #68717a; + } + + .highlight .gt { + color: #68717a; + } + + .highlight .ni { + color: #24292f; + } + + .highlight .si { + color: #24292f; + } + + .highlight .ge { + color: #24292f; + font-style: italic; + } + + .highlight .gs { + color: #24292f; + font-weight: bold; + } +} diff --git a/_sass/variables-hook.scss b/_sass/variables-hook.scss deleted file mode 100644 index f27e0eb..0000000 --- a/_sass/variables-hook.scss +++ /dev/null @@ -1,3 +0,0 @@ -/* - Appending custom SCSS variables will override the default ones in `_sass/addon/variables.scsss` -*/ diff --git a/assets/css/jekyll-theme-chirpy.scss b/assets/css/jekyll-theme-chirpy.scss index d20545b..7ff89bf 100644 --- a/assets/css/jekyll-theme-chirpy.scss +++ b/assets/css/jekyll-theme-chirpy.scss @@ -1,7 +1,7 @@ --- --- -@import 'main +@use 'main {%- if jekyll.environment == 'production' -%} .bundle {%- endif -%} diff --git a/package.json b/package.json index d6beea0..aa83ee7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "homepage": "https://github.com/cotes2020/jekyll-theme-chirpy/", "scripts": { "build": "concurrently npm:build:*", - "build:css": "purgecss -c purgecss.config.js", + "build:css": "node purgecss.js", "build:js": "rollup -c --bundleConfigAsCjs --environment BUILD:production", "watch:js": "rollup -c --bundleConfigAsCjs -w", "lint:scss": "stylelint _sass/**/*.scss", diff --git a/purgecss.config.js b/purgecss.config.js deleted file mode 100644 index de370de..0000000 --- a/purgecss.config.js +++ /dev/null @@ -1,23 +0,0 @@ -const fs = require('fs'); -const DIST_PATH = '_sass/dist'; - -fs.rm(DIST_PATH, { recursive: true, force: true }, (err) => { - if (err) { - throw err; - } - - fs.mkdirSync(DIST_PATH); -}); - -module.exports = { - content: ['_includes/**/*.html', '_layouts/**/*.html', '_javascript/**/*.js'], - css: ['node_modules/bootstrap/dist/css/bootstrap.min.css'], - keyframes: true, - variables: true, - output: `${DIST_PATH}/bootstrap.css`, - // The `safelist` should be changed appropriately for future development - safelist: { - standard: [/^collaps/, /^w-/, 'shadow', 'border', 'kbd'], - greedy: [/^col-/, /tooltip/] - } -}; diff --git a/purgecss.js b/purgecss.js new file mode 100644 index 0000000..ad42db2 --- /dev/null +++ b/purgecss.js @@ -0,0 +1,30 @@ +const fs = require('fs').promises; +const { PurgeCSS } = require('purgecss'); +const DIST_PATH = '_sass/vendors'; +const output = `${DIST_PATH}/_bootstrap.scss`; + +const config = { + content: ['_includes/**/*.html', '_layouts/**/*.html', '_javascript/**/*.js'], + css: ['node_modules/bootstrap/dist/css/bootstrap.min.css'], + keyframes: true, + variables: true, + // The `safelist` should be changed appropriately for future development + safelist: { + standard: [/^collaps/, /^w-/, 'shadow', 'border', 'kbd'], + greedy: [/^col-/, /tooltip/] + } +}; + +function main() { + fs.rm(DIST_PATH, { recursive: true, force: true }) + .then(() => fs.mkdir(DIST_PATH)) + .then(() => new PurgeCSS().purge(config)) + .then((result) => { + return fs.writeFile(output, result[0].css); + }) + .catch((err) => { + console.error('Error during PurgeCSS process:', err); + }); +} + +main(); diff --git a/tools/init.sh b/tools/init.sh index 2ad72ab..d710182 100755 --- a/tools/init.sh +++ b/tools/init.sh @@ -92,7 +92,8 @@ init_files() { npm i && npm run build # track the CSS/JS output - _sedi "/.*\/dist$/d" .gitignore + _sedi "/^_sass\/vendors/d" .gitignore + _sedi "/^assets\/js\/dist/d" .gitignore } commit() { diff --git a/tools/release.sh b/tools/release.sh index 522c892..36ca88a 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -15,7 +15,7 @@ NODE_SPEC="package.json" CHANGELOG="docs/CHANGELOG.md" CONFIG="_config.yml" -CSS_DIST="_sass/dist" +CSS_DIST="_sass/vendors" JS_DIST="assets/js/dist" FILES=( From 5756b8fc2636071de9bf7a137fec1dec811a9043 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Mon, 25 Nov 2024 00:18:06 +0800 Subject: [PATCH 4/7] build(deps-dev): upgrade dependencies Close #2058 --- package.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index aa83ee7..36f77e5 100644 --- a/package.json +++ b/package.json @@ -28,25 +28,25 @@ "bootstrap": "^5.3.3" }, "devDependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-private-methods": "^7.25.7", - "@babel/preset-env": "^7.25.4", - "@commitlint/cli": "^19.5.0", - "@commitlint/config-conventional": "^19.5.0", + "@babel/core": "^7.26.0", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/preset-env": "^7.26.0", + "@commitlint/cli": "^19.6.0", + "@commitlint/config-conventional": "^19.6.0", "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", "@semantic-release/changelog": "^6.0.3", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", - "concurrently": "^9.0.1", + "concurrently": "^9.1.0", "conventional-changelog-conventionalcommits": "^8.0.0", - "husky": "^9.1.6", - "purgecss": "^6.0.0", - "rollup": "^4.21.3", - "semantic-release": "^24.1.1", - "stylelint": "^16.9.0", + "husky": "^9.1.7", + "purgecss": "^7.0.2", + "rollup": "^4.27.4", + "semantic-release": "^24.2.0", + "stylelint": "^16.10.0", "stylelint-config-standard-scss": "^13.1.0" }, "prettier": { From 11647697bbacb84df6171a0ac7947a0e4fdef5da Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Mon, 25 Nov 2024 03:55:11 +0800 Subject: [PATCH 5/7] build(deps): update dependencies version --- _data/origin/cors.yml | 8 ++++---- assets/lib | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_data/origin/cors.yml b/_data/origin/cors.yml index afdb3d9..e9bb4eb 100644 --- a/_data/origin/cors.yml +++ b/_data/origin/cors.yml @@ -20,17 +20,17 @@ webfonts: https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Sour # Libraries toc: - css: https://cdn.jsdelivr.net/npm/tocbot@4.29.0/dist/tocbot.min.css - js: https://cdn.jsdelivr.net/npm/tocbot@4.29.0/dist/tocbot.min.js + css: https://cdn.jsdelivr.net/npm/tocbot@4.32.2/dist/tocbot.min.css + js: https://cdn.jsdelivr.net/npm/tocbot@4.32.2/dist/tocbot.min.js fontawesome: - css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.6.0/css/all.min.css + css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.7.1/css/all.min.css search: js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js mermaid: - js: https://cdn.jsdelivr.net/npm/mermaid@11.0.2/dist/mermaid.min.js + js: https://cdn.jsdelivr.net/npm/mermaid@11.4.0/dist/mermaid.min.js dayjs: js: diff --git a/assets/lib b/assets/lib index a231bc7..b9e18a1 160000 --- a/assets/lib +++ b/assets/lib @@ -1 +1 @@ -Subproject commit a231bc7e2c67198e604950cb2be9147a0b2020c0 +Subproject commit b9e18a1510e3be5de250ed34205da318b76474e0 From 5265b039741555943f9a6f0451287aefb6810f28 Mon Sep 17 00:00:00 2001 From: Cotes Chung <11371340+cotes2020@users.noreply.github.com> Date: Thu, 28 Nov 2024 02:58:25 +0800 Subject: [PATCH 6/7] feat: support vertical scrolling for toc in desktop mode (#2064) --- _includes/toc.html | 5 +-- _layouts/default.html | 2 +- _sass/abstracts/_placeholders.scss | 4 +++ _sass/layout/_panel.scss | 14 ++++++--- _sass/pages/_post.scss | 49 +++++++++++++++++++++++++++--- 5 files changed, 61 insertions(+), 13 deletions(-) diff --git a/_includes/toc.html b/_includes/toc.html index 49c8f90..883bf13 100644 --- a/_includes/toc.html +++ b/_includes/toc.html @@ -1,8 +1,9 @@ {% include toc-status.html %} {% if enable_toc %} -
-

{{- site.data.locales[include.lang].panel.toc -}}

+
+
+

{{- site.data.locales[include.lang].panel.toc -}}

{% endif %} diff --git a/_layouts/default.html b/_layouts/default.html index c83c561..a55bfef 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -33,7 +33,7 @@ layout: compress -