diff --git a/scripts/assets/moon.svg b/scripts/assets/moon.svg new file mode 100644 index 0000000..80efdd2 --- /dev/null +++ b/scripts/assets/moon.svg @@ -0,0 +1,3 @@ + + + diff --git a/scripts/assets/sun.svg b/scripts/assets/sun.svg new file mode 100644 index 0000000..eeb7198 --- /dev/null +++ b/scripts/assets/sun.svg @@ -0,0 +1,3 @@ + + + diff --git a/scripts/create.mjs b/scripts/create.mjs index c5083f4..d7cab9e 100644 --- a/scripts/create.mjs +++ b/scripts/create.mjs @@ -10,7 +10,7 @@ import { header } from './nodes/header.mjs'; import { rehypeUrls } from './utils/rehypeUrls.mjs'; import { tooltips } from './utils/tooltips.mjs'; import { homeCardIcons } from './utils/homeCardIcons.mjs'; -import { getTocsTree } from './utils/getTocsTree.mjs' +import { getTocsTree } from './utils/getTocsTree.mjs'; const favicon = `data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%221em%22%20width%3D%221em%22%3E%20%3Cpath%20opacity%3D%22.4%22%20d%3D%22m21.66%2010.44-.98%204.18c-.84%203.61-2.5%205.07-5.62%204.77-.5-.04-1.04-.13-1.62-.27l-1.68-.4c-4.17-.99-5.46-3.05-4.48-7.23l.98-4.19c.2-.85.44-1.59.74-2.2%201.17-2.42%203.16-3.07%206.5-2.28l1.67.39c4.19.98%205.47%203.05%204.49%207.23Z%22%20fill%3D%22%23777%22%2F%3E%20%3Cpath%20d%3D%22M15.06%2019.39c-.62.42-1.4.77-2.35%201.08l-1.58.52c-3.97%201.28-6.06.21-7.35-3.76L2.5%2013.28c-1.28-3.97-.22-6.07%203.75-7.35l1.58-.52c.41-.13.8-.24%201.17-.31-.3.61-.54%201.35-.74%202.2l-.98%204.19c-.98%204.18.31%206.24%204.48%207.23l1.68.4c.58.14%201.12.23%201.62.27Zm2.43-8.88c-.06%200-.12-.01-.19-.02l-4.85-1.23a.75.75%200%200%201%20.37-1.45l4.85%201.23a.748.748%200%200%201-.18%201.47Z%22%20fill%3D%22%23999%22%20%2F%3E%20%3Cpath%20d%3D%22M14.56%2013.89c-.06%200-.12-.01-.19-.02l-2.91-.74a.75.75%200%200%201%20.37-1.45l2.91.74c.4.1.64.51.54.91-.08.34-.38.56-.72.56Z%22%20fill%3D%22%23999%22%20%2F%3E%20%3C%2Fsvg%3E`; diff --git a/scripts/nodes/header.mjs b/scripts/nodes/header.mjs index 6d0e5a1..68f4e35 100644 --- a/scripts/nodes/header.mjs +++ b/scripts/nodes/header.mjs @@ -1,18 +1,22 @@ import path from 'path'; import { github, editor } from './logo.mjs'; import { getSVGNode } from '../utils/getSVGNode.mjs'; +import { darkMode } from '../utils/darkMode.mjs'; const ICONS_PATH = path.resolve(process.cwd(), 'scripts/assets/quickreference.svg') export function header({ homePath, githubURL = '' }) { const svgNode = getSVGNode(ICONS_PATH) const data = [ { + menu: true, href: githubURL, target: '__blank', label: '编辑', children: [editor] }, + ...darkMode(), { + menu: true, href: 'https://github.com/jaywcjlove/reference', target: '__blank', children: [github] @@ -59,7 +63,8 @@ export function header({ homePath, githubURL = '' }) { properties: { class: ['menu'], }, - children: data.map(({ href, label, children = [], ...props }) => { + children: data.map(({ href, label, menu, children = [], ...props }) => { + if (!menu) return { children, ...props }; const childs = { type: 'element', tagName: 'a', diff --git a/scripts/style.css b/scripts/style.css index cacf9e9..c5c636b 100644 --- a/scripts/style.css +++ b/scripts/style.css @@ -6,9 +6,114 @@ body { font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; } +[data-color-mode*='dark'] body .dark { + display: none; +} +[data-color-mode*='dark'] body .light { + display: block; +} +[data-color-mode*='light'] body .dark { + display: block; +} +[data-color-mode*='light'] body .light { + display: none; +} + +[data-color-mode*='light'], [data-color-mode*='light'] body { + --color-prettylights-syntax-comment: #b1bac3; + --color-prettylights-syntax-constant: #0550ae; + --color-prettylights-syntax-entity: #8250df; + --color-prettylights-syntax-storage-modifier-import: #24292f; + --color-prettylights-syntax-entity-tag: #116329; + --color-prettylights-syntax-keyword: #cf222e; + --color-prettylights-syntax-string: #0a3069; + --color-prettylights-syntax-variable: #953800; + --color-prettylights-syntax-brackethighlighter-unmatched: #82071e; + --color-prettylights-syntax-invalid-illegal-text: #f6f8fa; + --color-prettylights-syntax-invalid-illegal-bg: #82071e; + --color-prettylights-syntax-carriage-return-text: #f6f8fa; + --color-prettylights-syntax-carriage-return-bg: #cf222e; + --color-prettylights-syntax-string-regexp: #116329; + --color-prettylights-syntax-markup-list: #3b2300; + --color-prettylights-syntax-markup-heading: #0550ae; + --color-prettylights-syntax-markup-italic: #24292f; + --color-prettylights-syntax-markup-bold: #24292f; + --color-prettylights-syntax-markup-deleted-text: #82071e; + --color-prettylights-syntax-markup-deleted-bg: #FFEBE9; + --color-prettylights-syntax-markup-inserted-text: #116329; + --color-prettylights-syntax-markup-inserted-bg: #dafbe1; + --color-prettylights-syntax-markup-changed-text: #953800; + --color-prettylights-syntax-markup-changed-bg: #ffd8b5; + --color-prettylights-syntax-markup-ignored-text: #eaeef2; + --color-prettylights-syntax-markup-ignored-bg: #0550ae; + --color-prettylights-syntax-meta-diff-range: #8250df; + --color-prettylights-syntax-brackethighlighter-angle: #57606a; + --color-prettylights-syntax-sublimelinter-gutter-mark: #8c959f; + --color-prettylights-syntax-constant-other-reference-link: #0a3069; + --color-fg-default: #24292f; + --color-fg-muted: #57606a; + --color-fg-subtle: #6e7781; + --color-canvas-default: #f1f5f9; + --color-canvas-subtle: #fff; + --color-bg-subtle: #f8f9fa; + --color-border-default: #d0d7de; + --color-border-muted: #ececec94; + --color-neutral-muted: rgba(175,184,193,0.2); + --color-accent-fg: #0969da; + --color-accent-emphasis: #0969da; + --color-attention-subtle: #fff8c5; + --color-danger-fg: #cf222e; +} + +[data-color-mode*='dark'], [data-color-mode*='dark'] body { + --color-prettylights-syntax-comment: #8b949e; + --color-prettylights-syntax-constant: #79c0ff; + --color-prettylights-syntax-entity: #d2a8ff; + --color-prettylights-syntax-storage-modifier-import: #c9d1d9; + --color-prettylights-syntax-entity-tag: #7ee787; + --color-prettylights-syntax-keyword: #ff7b72; + --color-prettylights-syntax-string: #a5d6ff; + --color-prettylights-syntax-variable: #ffa657; + --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; + --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; + --color-prettylights-syntax-invalid-illegal-bg: #8e1519; + --color-prettylights-syntax-carriage-return-text: #f0f6fc; + --color-prettylights-syntax-carriage-return-bg: #b62324; + --color-prettylights-syntax-string-regexp: #7ee787; + --color-prettylights-syntax-markup-list: #f2cc60; + --color-prettylights-syntax-markup-heading: #1f6feb; + --color-prettylights-syntax-markup-italic: #c9d1d9; + --color-prettylights-syntax-markup-bold: #c9d1d9; + --color-prettylights-syntax-markup-deleted-text: #ffdcd7; + --color-prettylights-syntax-markup-deleted-bg: #67060c; + --color-prettylights-syntax-markup-inserted-text: #aff5b4; + --color-prettylights-syntax-markup-inserted-bg: #033a16; + --color-prettylights-syntax-markup-changed-text: #ffdfb6; + --color-prettylights-syntax-markup-changed-bg: #5a1e02; + --color-prettylights-syntax-markup-ignored-text: #c9d1d9; + --color-prettylights-syntax-markup-ignored-bg: #1158c7; + --color-prettylights-syntax-meta-diff-range: #d2a8ff; + --color-prettylights-syntax-brackethighlighter-angle: #8b949e; + --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; + --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; + --color-fg-default: #c9d1d9; + --color-fg-muted: #8b949e; + --color-fg-subtle: #94a3b8; + --color-canvas-default: #0f172a; + --color-canvas-subtle: #1e293b; + --color-bg-subtle: rgb(15 23 42/0.3); + --color-border-default: #404f5f; + --color-border-muted: rgb(51 65 85/0.5); + --color-neutral-muted: rgb(51 65 85/0.3); + --color-accent-fg: #58a6ff; + --color-accent-emphasis: #1f6feb; + --color-attention-subtle: rgba(187,128,9,0.15); + --color-danger-fg: #f85149; +} + body { - background-color: rgb(15 23 42/1); - color: rgb(203 213 225/1); + color: var(--color-fg-default); + background-color: var(--color-canvas-default); } *, ::before, ::after { @@ -44,13 +149,13 @@ table { } table td:not(:last-child)>code, table td:not(:last-child)>del>code, ul li > code, kbd { - background-color: rgb(51 65 85/0.5); - color: rgb(203 213 225/1); + background-color: var(--color-neutral-muted); + color: var(--color-fg-subtle); box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000; letter-spacing: 0.075rem; padding: 0.1em 0.54em; - border: 1px solid rgb(204,204,204); - border-color: rgb(51 65 85/1); + border: 1px solid var(--color-border-muted); + border-color: var(--color-border-default); line-height: 1.5; font-family: Arial,Helvetica,sans-serif; font-size: 12px; @@ -60,7 +165,7 @@ table td:not(:last-child)>code, table td:not(:last-child)>del>code, ul li > code table tr+tr { border-top: solid 1px #ececec94; - border-color: rgb(51 65 85/0.5); + border-color: var(--color-border-muted); } table td, table th { padding: 9px 14px; @@ -86,8 +191,7 @@ table td:first-child>code { } table td:first-child>del>code { text-decoration: inherit; - --text-opacity: 1; - color: rgb(244 67 54/var(--text-opacity)); + color: var(--color-danger-fg); } table.show-header thead { @@ -251,11 +355,11 @@ a.text-grey { font-size: 40px; } -.header-nav .menu a:hover { - background-color: rgb(30 41 59/1); +.header-nav .menu a:hover, .header-nav .menu button:hover { + background-color: var(--color-neutral-muted); } -.header-nav .menu a { +.header-nav .menu a, .header-nav .menu button { padding-left: 0.75rem; padding-right: 0.75rem; padding-top: 0.5rem; @@ -270,9 +374,21 @@ a.text-grey { .header-nav .menu a > span { font-size: 0.9rem; } +.header-nav .menu button { + font-family: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + -webkit-appearance: button; + background-color: transparent; + background-image: none; + color: var(--color-fg-default); + cursor: pointer; + font-size: 18px; +} .header-nav a, .header-nav a:visited { - color: rgb(209 213 219/1); + color: var(--color-fg-default); line-height: 1.2; gap: 0.3rem; } @@ -284,7 +400,7 @@ a.text-grey { } .wrap-header.h1wrap .wrap-body { - color: rgb(71 85 105/1); + color: var(--color-fg-subtle); } .wrap-header.h1wrap > h1 { @@ -321,8 +437,7 @@ a.text-grey { body:not(.home) .h2wrap > h2 a::after { content: '#'; padding-right: 0.5rem; - --tw-text-opacity: 1; - color: rgb(16 185 129/var(--tw-text-opacity)); + color: rgb(16 185 129/1); } .wrap-header.h3wrap { @@ -358,23 +473,25 @@ body:not(.home) .h2wrap > h2 a::after { padding-right: 1rem; padding-top: 0.75rem; padding-bottom: 0.75rem; - color: rgb(148 163 184/1); - background-color: rgb(15 23 42/0.3); + color: var(--color-fg-subtle); + background-color: var(--color-bg-subtle); } .wrap-header.h3wrap > .wrap-body p:first-child:before { - background-color: rgb(15 23 42/0.3); + background-color: var(--color-bg-subtle); color: rgb(30 41 59/0); content: '-'; - line-height: 1.75rem; - top: -4px; + line-height: 1.50rem; + top: 0; position: absolute; left: 0px; width: 100%; + border-radius: 0.5rem 0.5rem 0 0; } .wrap-header.h3wrap > .wrap-body p:not(:first-child):last-child { margin-top: auto; + border-radius: 0 0 0.5rem 0.5rem; } .wrap-header.h3wrap > .wrap-body { @@ -386,9 +503,9 @@ body:not(.home) .h2wrap > h2 a::after { } .h4wrap > h4 { - border-color: rgb(51 65 85/0.5); - background-color: rgb(51 65 85/0.3); - color: rgb(203 213 225/1); + border-color: transparent; + background-color: var(--color-neutral-muted); + color: var(--color-fg-default); margin: 0px; border-top-width: 1px; @@ -419,7 +536,7 @@ body:not(.home) .h2wrap > h2 a::after { padding: 9px; padding-left: 26px; position: relative; - border-bottom: solid 1px rgb(51 65 85/0.5); + border-bottom: solid 1px var(--color-border-muted); } .h2wrap-body ul:not(.style-none)>li::before { @@ -449,7 +566,7 @@ body:not(.home) .h2wrap > h2 a::after { } .h3wrap hr { - border-bottom: 1px solid #475060; + border-bottom: 1px solid var(--color-border-default); } .h2wrap-body { @@ -460,8 +577,7 @@ body:not(.home) .h2wrap > h2 a::after { } .h2wrap-body > .wrap { - background-color: #1e293b; - color: rgb(203 213 225/1); + background-color: var(--color-canvas-subtle); position: relative; display: flex; flex-direction: column; @@ -554,96 +670,6 @@ body:not(.home) .h2wrap > h2 a::after { opacity: 1; } -[data-color-mode*='light'], [data-color-mode*='light'] body { - --color-prettylights-syntax-comment: #6e7781; - --color-prettylights-syntax-constant: #0550ae; - --color-prettylights-syntax-entity: #8250df; - --color-prettylights-syntax-storage-modifier-import: #24292f; - --color-prettylights-syntax-entity-tag: #116329; - --color-prettylights-syntax-keyword: #cf222e; - --color-prettylights-syntax-string: #0a3069; - --color-prettylights-syntax-variable: #953800; - --color-prettylights-syntax-brackethighlighter-unmatched: #82071e; - --color-prettylights-syntax-invalid-illegal-text: #f6f8fa; - --color-prettylights-syntax-invalid-illegal-bg: #82071e; - --color-prettylights-syntax-carriage-return-text: #f6f8fa; - --color-prettylights-syntax-carriage-return-bg: #cf222e; - --color-prettylights-syntax-string-regexp: #116329; - --color-prettylights-syntax-markup-list: #3b2300; - --color-prettylights-syntax-markup-heading: #0550ae; - --color-prettylights-syntax-markup-italic: #24292f; - --color-prettylights-syntax-markup-bold: #24292f; - --color-prettylights-syntax-markup-deleted-text: #82071e; - --color-prettylights-syntax-markup-deleted-bg: #FFEBE9; - --color-prettylights-syntax-markup-inserted-text: #116329; - --color-prettylights-syntax-markup-inserted-bg: #dafbe1; - --color-prettylights-syntax-markup-changed-text: #953800; - --color-prettylights-syntax-markup-changed-bg: #ffd8b5; - --color-prettylights-syntax-markup-ignored-text: #eaeef2; - --color-prettylights-syntax-markup-ignored-bg: #0550ae; - --color-prettylights-syntax-meta-diff-range: #8250df; - --color-prettylights-syntax-brackethighlighter-angle: #57606a; - --color-prettylights-syntax-sublimelinter-gutter-mark: #8c959f; - --color-prettylights-syntax-constant-other-reference-link: #0a3069; - --color-fg-default: #24292f; - --color-fg-muted: #57606a; - --color-fg-subtle: #6e7781; - --color-canvas-default: #ffffff; - --color-canvas-subtle: #f6f8fa; - --color-border-default: #d0d7de; - --color-border-muted: hsla(210,18%,87%,1); - --color-neutral-muted: rgba(175,184,193,0.2); - --color-accent-fg: #0969da; - --color-accent-emphasis: #0969da; - --color-attention-subtle: #fff8c5; - --color-danger-fg: #cf222e; -} - -[data-color-mode*='dark'], [data-color-mode*='dark'] body { - --color-prettylights-syntax-comment: #8b949e; - --color-prettylights-syntax-constant: #79c0ff; - --color-prettylights-syntax-entity: #d2a8ff; - --color-prettylights-syntax-storage-modifier-import: #c9d1d9; - --color-prettylights-syntax-entity-tag: #7ee787; - --color-prettylights-syntax-keyword: #ff7b72; - --color-prettylights-syntax-string: #a5d6ff; - --color-prettylights-syntax-variable: #ffa657; - --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; - --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; - --color-prettylights-syntax-invalid-illegal-bg: #8e1519; - --color-prettylights-syntax-carriage-return-text: #f0f6fc; - --color-prettylights-syntax-carriage-return-bg: #b62324; - --color-prettylights-syntax-string-regexp: #7ee787; - --color-prettylights-syntax-markup-list: #f2cc60; - --color-prettylights-syntax-markup-heading: #1f6feb; - --color-prettylights-syntax-markup-italic: #c9d1d9; - --color-prettylights-syntax-markup-bold: #c9d1d9; - --color-prettylights-syntax-markup-deleted-text: #ffdcd7; - --color-prettylights-syntax-markup-deleted-bg: #67060c; - --color-prettylights-syntax-markup-inserted-text: #aff5b4; - --color-prettylights-syntax-markup-inserted-bg: #033a16; - --color-prettylights-syntax-markup-changed-text: #ffdfb6; - --color-prettylights-syntax-markup-changed-bg: #5a1e02; - --color-prettylights-syntax-markup-ignored-text: #c9d1d9; - --color-prettylights-syntax-markup-ignored-bg: #1158c7; - --color-prettylights-syntax-meta-diff-range: #d2a8ff; - --color-prettylights-syntax-brackethighlighter-angle: #8b949e; - --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; - --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; - --color-fg-default: #c9d1d9; - --color-fg-muted: #8b949e; - --color-fg-subtle: #484f58; - --color-canvas-default: #0d1117; - --color-canvas-subtle: #161b22; - --color-border-default: #30363d; - --color-border-muted: #21262d; - --color-neutral-muted: rgba(110,118,129,0.4); - --color-accent-fg: #58a6ff; - --color-accent-emphasis: #1f6feb; - --color-attention-subtle: rgba(187,128,9,0.15); - --color-danger-fg: #f85149; -} - /* 代码高亮 Start */ .token.comment, .token.prolog, .token.doctype, .token.cdata { color: var(--color-prettylights-syntax-comment); @@ -718,7 +744,7 @@ body:not(.home) .h2wrap > h2 a::after { .footer-wrap { margin-top: 3.5rem; color: rgb(100 116 139/1); - background-color: rgb(30 41 59/1); + background-color: var(--color-canvas-subtle); text-align: center; } diff --git a/scripts/utils/darkMode.mjs b/scripts/utils/darkMode.mjs new file mode 100644 index 0000000..9f9ed25 --- /dev/null +++ b/scripts/utils/darkMode.mjs @@ -0,0 +1,40 @@ +import path from 'path'; +import { getSVGNode } from './getSVGNode.mjs'; + +const scripts = ` + const button = document.querySelector('#darkMode'); + button.onclick = () => { + const theme = document.documentElement.dataset.colorMode; + document.documentElement.setAttribute('data-color-mode', theme === 'light' ? 'dark' : 'light'); + } +`; + +const ICONS_PATH = path.resolve(process.cwd(), 'scripts/assets'); + +export function darkMode() { + const iconSunPath = path.resolve(ICONS_PATH, `sun.svg`); + const iconMoonPath = path.resolve(ICONS_PATH, `moon.svg`); + const sunNode = getSVGNode(iconSunPath) + const moonNode = getSVGNode(iconMoonPath) + return [ + { + type: 'element', + tagName: 'button', + properties: { + id: 'darkMode', + type: 'button' + }, + children: [ + ...sunNode, + ...moonNode + ] + }, { + type: 'element', + tagName: 'script', + children: [{ + type: 'text', + value: scripts, + }] + } + ]; +}