@scribdown/ui-handdrawn 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scribdown/ui-handdrawn",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Scribdown 手绘风格视觉组件:设计 Token、样式与 SVG 资产。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" width="200" height="6" viewBox="0 0 200 6" preserveAspectRatio="none">
2
2
  <g fill="none" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
3
- <path d="M-0.8885389623697847 2.835747448122129 C5.98063496722219 3.023836115614201, 26.163666460150857 3.3836979418154813, 39.665068303281444 3.2720676984544848 C53.16647014641203 3.160437455093488, 66.7766827083969 2.1343503594553717, 80.11987209641376 2.165965987956151 C93.46306148443061 2.1975816164569304, 106.29286793692347 3.454849899923429, 119.72420463138259 3.4617614694591614 C133.1555413258417 3.468673038994894, 147.18285253716945 2.1781550389683497, 160.7078922631685 2.207435405170545 C174.23293198916755 2.23671577137274, 194.21855270786523 3.414428028380498, 200.87444298737682 3.637443666672334" />
4
- <path d="M19.680227263411506 2.550232136854902 C29.60333365944421 2.7579639204105155, 59.151220776611524 4.316996703819475, 78.98881145630342 4.451140555848057 C98.82640213599532 4.585284407876639, 118.8756678476671 3.468230293965381, 138.7057713415629 3.355095249026393 C158.53587483545869 3.2419602040874045, 188.1445200029088 3.586171521686224, 197.96943241967818 3.772330286214128" />
3
+ <path d="M-0.8885389623697847 3.835747448122129 C5.98063496722219 3.023836115614201, 26.163666460150857 3.3836979418154813, 39.665068303281444 3.2720676984544848 C53.16647014641203 3.160437455093488, 66.7766827083969 2.1343503594553717, 80.11987209641376 2.165965987956151 C93.46306148443061 2.1975816164569304, 106.29286793692347 3.454849899923429, 119.72420463138259 3.4617614694591614 C133.1555413258417 3.468673038994894, 147.18285253716945 2.1781550389683497, 160.7078922631685 2.207435405170545 C174.23293198916755 2.23671577137274, 194.21855270786523 3.414428028380498, 200.87444298737682 3.637443666672334" />
4
+ <path d="M19.680227263411506 3.150232136854902 C29.60333365944421 2.7579639204105155, 59.151220776611524 4.316996703819475, 78.98881145630342 4.451140555848057 C98.82640213599532 4.585284407876639, 118.8756678476671 3.468230293965381, 138.7057713415629 3.355095249026393 C158.53587483545869 3.2419602040874045, 188.1445200029088 3.586171521686224, 197.96943241967818 3.772330286214128" />
5
5
  </g>
6
6
  </svg>
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="63.653" height="48" viewBox="9.239 0 63.653 48" role="img" aria-label="handdrawn tag">
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="66" height="48" viewBox="8.5 0 66 48" overflow="visible" role="img" aria-label="handdrawn tag">
2
2
  <style>
3
3
  .tag-fill-rect,
4
4
  .tag-fill-triangle {
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="27.005" height="48" viewBox="66.898 0 27.005 48" role="img" aria-label="handdrawn tag">
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="39.903" height="48" viewBox="54 0 39.903 48" role="img" aria-label="handdrawn tag">
2
2
  <style>
3
3
  .tag-fill-rect,
4
4
  .tag-fill-triangle {
@@ -46,6 +46,7 @@
46
46
  }
47
47
  }
48
48
  </style>
49
- <path class="tag-fill-triangle" d="M70.4237706752122 38.26480130717802 C70.4237706752122 38.26480130717802, 70.4237706752122 38.26480130717802, 70.4237706752122 38.26480130717802 M70.4237706752122 38.26480130717802 C70.4237706752122 38.26480130717802, 70.4237706752122 38.26480130717802, 70.4237706752122 38.26480130717802 M73.4469873344831 34.961023081565735 C71.98366817648477 34.92708062922884, 70.7358433989635 34.0037472716233, 69.65509930142562 33.548700574279295 M73.23832219498306 35.43807427456835 C72.42446913007835 34.919960507517374, 71.30799972853754 34.08322924600833, 70.07104369940784 33.19273557353439 M76.5357928189563 33.42369589327702 C74.45869046134862 32.16536178402244, 73.65220244846036 31.623668278793918, 71.33012385428177 28.142944509685588 M77.0673001471015 32.83793279051462 C75.78428859805638 31.925655383893602, 73.7963050097036 30.692979392591912, 70.73638699292616 28.654910013385663 M81.40515983046376 31.11584017612848 C76.77450155702314 27.40595785081873, 75.45937306562682 26.063533288112236, 68.98331095065755 22.689056984875517 M81.17489882759814 30.016970849787512 C77.56428261934575 28.943711123239098, 74.3713812424317 27.418133071113882, 70.55178897645438 24.121840223328377 M83.02022981597217 30.024242458629196 C79.73132477057155 27.218537660092817, 79.66303306730408 23.704551460609764, 72.31423250233638 18.24733109030525 M84.80078985781608 28.356022306177536 C82.42944170955137 26.229222188616355, 78.6040136950766 25.548900884630427, 69.7489131964685 20.105117541481988 M90.45063426493722 26.022530256870056 C83.23151616946713 22.896816911298135, 80.423212605641 19.511513666320518, 67.79809519127251 12.42297204475464 M89.33360597220305 27.2298116854642 C83.34628217243005 22.688003253096234, 78.43521476428062 19.85982467862676, 69.27251050574944 13.404617160983252" />
49
+ <!-- 关键步骤:左端笔画以不同距离越过切片边界,裁切后形成自然、不整齐的拼接起笔。 -->
50
+ <path class="tag-fill-triangle" d="M58.4237706752122 9.26480130717802 C66.4237706752122 12.56480130717802, 84.2237706752122 18.86480130717802, 91.1067660103552 22.50208585606888 M62.15509930142562 12.548700574279295 C69.75509930142562 16.148700574279295, 84.53509930142562 21.248700574279295, 90.8853535654489 25.101957783615216 M57.17104369940784 15.19273557353439 C65.57104369940784 18.89273557353439, 83.45104369940784 23.89273557353439, 89.33360597220305 27.2298116854642 M60.23012385428177 18.142944509685588 C68.93012385428177 21.642944509685588, 80.73012385428177 26.242944509685588, 87.02022981597217 29.524242458629196 M55.63638699292616 21.654910013385663 C63.23638699292616 24.654910013385663, 78.93638699292616 28.754910013385663, 84.80078985781608 31.356022306177536 M60.38331095065755 24.689056984875517 C66.98331095065755 27.289056984875517, 76.28331095065755 30.689056984875517, 81.40515983046376 33.11584017612848 M58.15178897645438 27.521840223328377 C65.45178897645438 29.821840223328377, 74.55178897645438 32.32184022332838, 77.0673001471015 34.83793279051462 M64.09809519127251 30.42297204475464 C67.59809519127251 31.82297204475464, 72.89809519127251 33.92297204475464, 73.4469873344831 36.961023081565735 M61.67251050574944 33.40461716098325 C66.07251050574944 34.10461716098325, 71.27251050574944 35.60461716098325, 70.4237706752122 38.26480130717802" />
50
51
 
51
52
  </svg>
@@ -46,7 +46,7 @@
46
46
  }
47
47
  }
48
48
  </style>
49
- <path class="tag-outline-triangle" d="M67.81899030609057 8.78106529759243 C77.54079624171952 12.693676162540212, 84.65957415774115 21.805816044128733, 91.1067660103552 22.50208585606888 M67.59937126510776 10.550338016962632 C78.38768789225605 15.400502316764324, 85.76194378321408 19.722923510445984, 90.8853535654489 25.101957783615216" />
50
- <path class="tag-outline-triangle" d="M91.00484327096493 24.589532747678458 C86.15963499819627 30.161803733457344, 77.65431767267874 31.346669881318228, 70.49413215536624 39.2532716838643 M93.00340586742387 23.704626417253166 C83.19385184191401 29.44669538330985, 75.75757446244593 35.71291955639376, 69.36792313596234 38.81769603798166" />
49
+ <path class="tag-outline-triangle" d="M67.81899030609057 8.18106529759243 C77.54079624171952 12.693676162540212, 84.65957415774115 21.805816044128733, 91.1067660103552 22.50208585606888 M67.59937126510776 10.550338016962632 C78.38768789225605 15.400502316764324, 85.76194378321408 19.722923510445984, 90.8853535654489 25.101957783615216" />
50
+ <path class="tag-outline-triangle" d="M91.00484327096493 24.589532747678458 C81.15963499819627 31.161803733457344, 77.65431767267874 31.346669881318228, 67.49413215536624 38.5532716838643 M93.00340586742387 23.704626417253166 C83.19385184191401 29.44669538330985, 75.75757446244593 35.71291955639376, 69.36792313596234 38.81769603798166" />
51
51
 
52
52
  </svg>
@@ -75,7 +75,7 @@
75
75
  var(--scribdown-frame-edge-vertical), var(--scribdown-frame-edge-vertical);
76
76
  background-position:
77
77
  left top,
78
- 50% bottom,
78
+ 80% bottom,
79
79
  left 40%,
80
80
  right top;
81
81
  background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
@@ -111,7 +111,7 @@
111
111
  border-radius: inherit;
112
112
  pointer-events: none;
113
113
  background-image: var(--scribdown-code-block-rect-shadow);
114
- background-position: center;
114
+ background-position: left top;
115
115
  background-repeat: repeat-x;
116
116
  background-size: auto 100%;
117
117
  }
@@ -135,7 +135,7 @@
135
135
  background-image: var(--scribdown-frame-edge-horizontal);
136
136
  background-repeat: repeat-x;
137
137
  background-size: var(--scribdown-frame-edge-tile-horizontal);
138
- background-position: left bottom;
138
+ background-position: 40% bottom;
139
139
  }
140
140
 
141
141
  @supports ((mask-image: url("")) or (-webkit-mask-image: url(""))) {
@@ -148,7 +148,7 @@
148
148
  var(--scribdown-frame-edge-vertical), var(--scribdown-frame-edge-vertical);
149
149
  -webkit-mask-position:
150
150
  left top,
151
- 50% bottom,
151
+ 80% bottom,
152
152
  left 40%,
153
153
  right top;
154
154
  -webkit-mask-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
@@ -163,7 +163,7 @@
163
163
  var(--scribdown-frame-edge-vertical), var(--scribdown-frame-edge-vertical);
164
164
  mask-position:
165
165
  left top,
166
- 50% bottom,
166
+ 80% bottom,
167
167
  left 40%,
168
168
  right top;
169
169
  mask-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
@@ -180,12 +180,12 @@
180
180
  background-color: var(--scribdown-code-block-chrome-shadow-fill);
181
181
  background-image: none;
182
182
  -webkit-mask-image: var(--scribdown-code-block-rect-shadow);
183
- -webkit-mask-position: center;
183
+ -webkit-mask-position: left top;
184
184
  -webkit-mask-repeat: repeat-x;
185
185
  -webkit-mask-size: auto 100%;
186
186
  -webkit-mask-mode: alpha;
187
187
  mask-image: var(--scribdown-code-block-rect-shadow);
188
- mask-position: center;
188
+ mask-position: left top;
189
189
  mask-repeat: repeat-x;
190
190
  mask-size: auto 100%;
191
191
  mask-mode: alpha;
@@ -197,12 +197,12 @@
197
197
  -webkit-mask-image: var(--scribdown-frame-edge-horizontal);
198
198
  -webkit-mask-repeat: repeat-x;
199
199
  -webkit-mask-size: var(--scribdown-frame-edge-tile-horizontal);
200
- -webkit-mask-position: left bottom;
200
+ -webkit-mask-position: 40% bottom;
201
201
  -webkit-mask-mode: alpha;
202
202
  mask-image: var(--scribdown-frame-edge-horizontal);
203
203
  mask-repeat: repeat-x;
204
204
  mask-size: var(--scribdown-frame-edge-tile-horizontal);
205
- mask-position: left bottom;
205
+ mask-position: 40% bottom;
206
206
  mask-mode: alpha;
207
207
  }
208
208
  }
@@ -0,0 +1,51 @@
1
+ /* Markdown 通用复制按钮:Mermaid 与表格复用同一图标和成功反馈。 */
2
+ .scribdown-copy-button {
3
+ display: inline-flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ width: 32px;
7
+ height: 32px;
8
+ margin: 0;
9
+ padding: 0;
10
+ border: 0;
11
+ border-radius: 8px 9px 7px 10px;
12
+ background: transparent;
13
+ color: var(--scribdown-color-text-primary);
14
+ cursor: pointer;
15
+ pointer-events: auto;
16
+ transition:
17
+ background var(--scribdown-duration-fast) var(--scribdown-easing-standard),
18
+ transform var(--scribdown-duration-fast) var(--scribdown-easing-standard);
19
+ }
20
+
21
+ .scribdown-copy-button:hover {
22
+ background: color-mix(in srgb, currentColor 14%, transparent);
23
+ }
24
+
25
+ .scribdown-copy-button:active {
26
+ transform: translateY(1px);
27
+ }
28
+
29
+ .scribdown-copy-button:focus-visible {
30
+ outline: 2px solid var(--scribdown-color-accent);
31
+ outline-offset: 2px;
32
+ }
33
+
34
+ .scribdown-copy-button__icon {
35
+ width: 18px;
36
+ height: 18px;
37
+ flex: none;
38
+ }
39
+
40
+ .scribdown-copy-button[data-scribdown-copied="true"] .scribdown-copy-button__icon--copy {
41
+ display: none;
42
+ }
43
+
44
+ .scribdown-copy-button__icon--check {
45
+ display: none;
46
+ }
47
+
48
+ .scribdown-copy-button[data-scribdown-copied="true"] .scribdown-copy-button__icon--check {
49
+ display: inline-block;
50
+ color: var(--scribdown-color-accent);
51
+ }
@@ -1,5 +1,11 @@
1
1
  /* ImageViewer:运行时注入的全图查看层,支持按钮和快捷键缩放。 */
2
2
  .scribdown-image-viewer {
3
+ /* 与 Mermaid 共用控件样式,仅由宿主决定全屏按钮尺寸。 */
4
+ --scribdown-viewer-control-size: 36px;
5
+ --scribdown-viewer-control-font-size: 16px;
6
+ --scribdown-viewer-zoom-value-min-width: 56px;
7
+ --scribdown-viewer-zoom-value-font-size: 14px;
8
+
3
9
  width: 100vw;
4
10
  max-width: none;
5
11
  height: 100dvh;
@@ -84,48 +90,6 @@
84
90
  gap: var(--scribdown-space-2);
85
91
  }
86
92
 
87
- .scribdown-image-viewer__button {
88
- display: inline-flex;
89
- align-items: center;
90
- justify-content: center;
91
- width: 36px;
92
- height: 36px;
93
- padding: 0;
94
- border: 1px solid color-mix(in srgb, var(--scribdown-color-border) 72%, transparent);
95
- border-radius: 8px 10px 9px 11px;
96
- background: color-mix(
97
- in srgb,
98
- var(--scribdown-color-surface) 88%,
99
- var(--scribdown-color-mark) 12%
100
- );
101
- box-shadow: var(--scribdown-shadow-sm);
102
- color: var(--scribdown-color-text-primary);
103
- cursor: pointer;
104
- font-family: var(--scribdown-font-code);
105
- font-size: 16px;
106
- font-weight: 700;
107
- line-height: 1;
108
- }
109
-
110
- .scribdown-image-viewer__button:hover {
111
- background: color-mix(
112
- in srgb,
113
- var(--scribdown-color-surface) 78%,
114
- var(--scribdown-color-mark) 22%
115
- );
116
- }
117
-
118
- .scribdown-image-viewer__button:focus-visible {
119
- outline: 2px solid var(--scribdown-color-accent);
120
- outline-offset: 3px;
121
- }
122
-
123
- .scribdown-image-viewer__button:disabled {
124
- box-shadow: none;
125
- cursor: default;
126
- opacity: 0.46;
127
- }
128
-
129
93
  .scribdown-image-viewer__button--close {
130
94
  background: color-mix(
131
95
  in srgb,
@@ -134,19 +98,6 @@
134
98
  );
135
99
  }
136
100
 
137
- .scribdown-image-viewer__zoom-value {
138
- display: inline-flex;
139
- align-items: center;
140
- justify-content: center;
141
- min-width: 56px;
142
- height: 36px;
143
- color: var(--scribdown-color-text-primary);
144
- font-family: var(--scribdown-font-code);
145
- font-size: 14px;
146
- font-weight: 700;
147
- line-height: 1;
148
- }
149
-
150
101
  .scribdown-image-viewer__viewport {
151
102
  min-width: 0;
152
103
  min-height: 0;
@@ -157,6 +108,7 @@
157
108
  padding: var(--scribdown-space-5);
158
109
  overflow: auto;
159
110
  overscroll-behavior: contain;
111
+ scrollbar-gutter: stable both-edges;
160
112
  touch-action: none;
161
113
  }
162
114
 
@@ -197,9 +149,8 @@
197
149
  width: 100%;
198
150
  }
199
151
 
200
- .scribdown-image-viewer__button {
201
- width: 34px;
202
- height: 34px;
152
+ .scribdown-image-viewer {
153
+ --scribdown-viewer-control-size: 34px;
203
154
  }
204
155
 
205
156
  .scribdown-image-viewer__hint {
@@ -18,8 +18,13 @@
18
18
  display: flex;
19
19
  align-items: center;
20
20
  justify-content: space-between;
21
+ gap: var(--scribdown-space-2);
21
22
  padding: 6px 12px;
22
- background: color-mix(in srgb, var(--scribdown-color-surface) 90%, var(--scribdown-color-border) 10%);
23
+ background: color-mix(
24
+ in srgb,
25
+ var(--scribdown-color-surface) 90%,
26
+ var(--scribdown-color-border) 10%
27
+ );
23
28
  border-bottom: 1px dashed color-mix(in srgb, var(--scribdown-color-border) 60%, transparent);
24
29
  }
25
30
 
@@ -32,11 +37,25 @@
32
37
  text-transform: uppercase;
33
38
  }
34
39
 
40
+ .scribdown-markdown .scribdown-mermaid__controls {
41
+ display: inline-flex;
42
+ align-items: center;
43
+ justify-content: flex-end;
44
+ gap: 4px;
45
+ min-width: 0;
46
+ overflow-x: auto;
47
+ scrollbar-width: none;
48
+ }
49
+
50
+ .scribdown-markdown .scribdown-mermaid__controls::-webkit-scrollbar {
51
+ display: none;
52
+ }
53
+
35
54
  .scribdown-markdown .scribdown-mermaid__body {
36
55
  position: relative;
37
56
  display: flex;
38
- align-items: center;
39
- justify-content: center;
57
+ align-items: safe center;
58
+ justify-content: safe center;
40
59
  /* 给 body 一个确定高度,使内部 canvas 的 height:100% 能解析,
41
60
  从而让 SVG 的 max-height:100% 触发等比缩放,避免极端长宽比图表被压成一条。 */
42
61
  height: clamp(280px, 50vh, 480px);
@@ -48,70 +67,47 @@
48
67
  background-size:
49
68
  32px 29px,
50
69
  auto;
70
+ overflow: auto;
71
+ overscroll-behavior: contain;
72
+ scrollbar-gutter: stable both-edges;
51
73
  }
52
74
 
53
- /* 右下角悬浮全屏按钮:默认轻量呈现,hover 后增强对比。 */
75
+ /* 全屏按钮沿用工具按钮尺寸,图标跟随 currentColor。 */
54
76
  .scribdown-markdown .scribdown-mermaid__fullscreen {
55
- position: absolute;
56
- right: 12px;
57
- bottom: 12px;
58
- z-index: 3;
59
- display: inline-flex;
60
- align-items: center;
61
- justify-content: center;
62
- width: 32px;
63
- height: 32px;
64
- padding: 0;
65
- border: 1px solid color-mix(in srgb, var(--scribdown-color-border) 70%, transparent);
66
- border-radius: 8px 10px 9px 11px;
67
- background: color-mix(in srgb, var(--scribdown-color-surface) 92%, transparent);
68
- color: var(--scribdown-color-text-primary);
69
- cursor: pointer;
70
- box-shadow: 0 2px 0 color-mix(in srgb, var(--scribdown-color-border) 40%, transparent);
71
- opacity: 0.75;
72
- transition:
73
- opacity 120ms ease,
74
- transform 120ms ease;
77
+ opacity: 0.82;
75
78
  }
76
79
 
77
- .scribdown-markdown .scribdown-mermaid__fullscreen:hover {
78
- opacity: 1;
79
- transform: translateY(-1px);
80
- background: color-mix(in srgb, var(--scribdown-color-surface) 80%, var(--scribdown-color-mark) 20%);
80
+ .scribdown-markdown .scribdown-mermaid__fullscreen svg {
81
+ display: block;
81
82
  }
82
83
 
83
- .scribdown-markdown .scribdown-mermaid__fullscreen:focus-visible {
84
- outline: 2px solid var(--scribdown-color-accent);
85
- outline-offset: 2px;
84
+ .scribdown-markdown .scribdown-mermaid__canvas {
85
+ display: block;
86
+ flex: 0 0 auto;
87
+ user-select: text;
86
88
  }
87
89
 
88
- .scribdown-markdown .scribdown-mermaid__fullscreen:disabled {
89
- cursor: default;
90
- opacity: 0;
91
- pointer-events: none;
90
+ /* SVG 尺寸由运行时 canvas 统一控制,选择模式下保留文本选择能力。 */
91
+ .scribdown-markdown .scribdown-mermaid__canvas svg {
92
+ display: block;
93
+ width: 100%;
94
+ height: 100%;
95
+ max-width: none;
96
+ max-height: none;
92
97
  }
93
98
 
94
- .scribdown-markdown .scribdown-mermaid__fullscreen svg {
95
- display: block;
99
+ .scribdown-markdown .scribdown-mermaid--drag-mode .scribdown-mermaid__body {
100
+ cursor: grab;
101
+ touch-action: none;
102
+ user-select: none;
96
103
  }
97
104
 
98
- .scribdown-markdown .scribdown-mermaid__canvas {
99
- display: flex;
100
- align-items: center;
101
- justify-content: center;
102
- width: 100%;
103
- height: 100%;
104
- overflow: hidden;
105
+ .scribdown-markdown .scribdown-mermaid--dragging .scribdown-mermaid__body {
106
+ cursor: grabbing;
105
107
  }
106
108
 
107
- /* SVG 用 max-width/max-height 100% + auto 让浏览器按 viewBox 等比缩放,
108
- 总有一边贴合 canvas 边缘,保证整图可见;细节由右下角全屏查看器提供。 */
109
- .scribdown-markdown .scribdown-mermaid__canvas svg {
110
- display: block;
111
- width: auto;
112
- height: auto;
113
- max-width: 100%;
114
- max-height: 100%;
109
+ .scribdown-markdown .scribdown-mermaid--dragging .scribdown-mermaid__canvas {
110
+ pointer-events: none;
115
111
  }
116
112
 
117
113
  /* Loading 态:画布尚未填充 SVG 时的占位脉冲。 */
@@ -119,14 +115,13 @@
119
115
  width: 100%;
120
116
  min-height: 180px;
121
117
  border-radius: 6px;
122
- background:
123
- repeating-linear-gradient(
124
- 45deg,
125
- color-mix(in srgb, var(--scribdown-color-border) 22%, transparent),
126
- color-mix(in srgb, var(--scribdown-color-border) 22%, transparent) 8px,
127
- transparent 8px,
128
- transparent 16px
129
- );
118
+ background: repeating-linear-gradient(
119
+ 45deg,
120
+ color-mix(in srgb, var(--scribdown-color-border) 22%, transparent),
121
+ color-mix(in srgb, var(--scribdown-color-border) 22%, transparent) 8px,
122
+ transparent 8px,
123
+ transparent 16px
124
+ );
130
125
  opacity: 0.6;
131
126
  animation: scribdown-mermaid-loading 1.6s linear infinite;
132
127
  }
@@ -165,7 +160,11 @@
165
160
  width: 52px;
166
161
  height: 52px;
167
162
  border: 2px solid var(--scribdown-color-text-primary);
168
- background: color-mix(in srgb, var(--scribdown-color-surface) 80%, var(--scribdown-color-warning) 12%);
163
+ background: color-mix(
164
+ in srgb,
165
+ var(--scribdown-color-surface) 80%,
166
+ var(--scribdown-color-warning) 12%
167
+ );
169
168
  transform: rotate(-2deg);
170
169
  }
171
170
 
@@ -203,7 +202,11 @@
203
202
  max-width: 100%;
204
203
  margin: 0;
205
204
  padding: 8px 12px;
206
- background: color-mix(in srgb, var(--scribdown-color-surface) 86%, var(--scribdown-color-border) 14%);
205
+ background: color-mix(
206
+ in srgb,
207
+ var(--scribdown-color-surface) 86%,
208
+ var(--scribdown-color-border) 14%
209
+ );
207
210
  border-radius: 6px;
208
211
  color: var(--scribdown-color-text-secondary);
209
212
  font-family: var(--scribdown-font-code);
@@ -216,6 +219,12 @@
216
219
 
217
220
  /* MermaidViewer:mermaid 全屏查看器,与图片查看器并列,整体风格保持一致。 */
218
221
  .scribdown-mermaid-viewer {
222
+ /* 与行内 Mermaid 共用控件样式,仅通过变量放大全屏触控尺寸。 */
223
+ --scribdown-viewer-control-size: 36px;
224
+ --scribdown-viewer-control-font-size: 16px;
225
+ --scribdown-viewer-zoom-value-min-width: 56px;
226
+ --scribdown-viewer-zoom-value-font-size: 14px;
227
+
219
228
  width: 100vw;
220
229
  max-width: none;
221
230
  height: 100dvh;
@@ -284,48 +293,6 @@
284
293
  gap: var(--scribdown-space-2);
285
294
  }
286
295
 
287
- .scribdown-mermaid-viewer__button {
288
- display: inline-flex;
289
- align-items: center;
290
- justify-content: center;
291
- width: 36px;
292
- height: 36px;
293
- padding: 0;
294
- border: 1px solid color-mix(in srgb, var(--scribdown-color-border) 72%, transparent);
295
- border-radius: 8px 10px 9px 11px;
296
- background: color-mix(
297
- in srgb,
298
- var(--scribdown-color-surface) 88%,
299
- var(--scribdown-color-mark) 12%
300
- );
301
- box-shadow: var(--scribdown-shadow-sm);
302
- color: var(--scribdown-color-text-primary);
303
- cursor: pointer;
304
- font-family: var(--scribdown-font-code);
305
- font-size: 16px;
306
- font-weight: 700;
307
- line-height: 1;
308
- }
309
-
310
- .scribdown-mermaid-viewer__button:hover {
311
- background: color-mix(
312
- in srgb,
313
- var(--scribdown-color-surface) 78%,
314
- var(--scribdown-color-mark) 22%
315
- );
316
- }
317
-
318
- .scribdown-mermaid-viewer__button:focus-visible {
319
- outline: 2px solid var(--scribdown-color-accent);
320
- outline-offset: 3px;
321
- }
322
-
323
- .scribdown-mermaid-viewer__button:disabled {
324
- box-shadow: none;
325
- cursor: default;
326
- opacity: 0.46;
327
- }
328
-
329
296
  .scribdown-mermaid-viewer__button--close {
330
297
  background: color-mix(
331
298
  in srgb,
@@ -334,19 +301,6 @@
334
301
  );
335
302
  }
336
303
 
337
- .scribdown-mermaid-viewer__zoom-value {
338
- display: inline-flex;
339
- align-items: center;
340
- justify-content: center;
341
- min-width: 56px;
342
- height: 36px;
343
- color: var(--scribdown-color-text-primary);
344
- font-family: var(--scribdown-font-code);
345
- font-size: 14px;
346
- font-weight: 700;
347
- line-height: 1;
348
- }
349
-
350
304
  .scribdown-mermaid-viewer__viewport {
351
305
  min-width: 0;
352
306
  min-height: 0;
@@ -356,17 +310,19 @@
356
310
  padding: var(--scribdown-space-5);
357
311
  overflow: auto;
358
312
  overscroll-behavior: contain;
359
- touch-action: none;
313
+ scrollbar-gutter: stable both-edges;
314
+ touch-action: auto;
360
315
  }
361
316
 
362
- .scribdown-mermaid-viewer--zoomed .scribdown-mermaid-viewer__viewport {
317
+ .scribdown-mermaid-viewer--drag-mode .scribdown-mermaid-viewer__viewport {
363
318
  cursor: grab;
319
+ touch-action: none;
320
+ user-select: none;
364
321
  }
365
322
 
366
- .scribdown-mermaid-viewer--zoomed.scribdown-mermaid-viewer--dragging
323
+ .scribdown-mermaid-viewer--drag-mode.scribdown-mermaid-viewer--dragging
367
324
  .scribdown-mermaid-viewer__viewport {
368
325
  cursor: grabbing;
369
- user-select: none;
370
326
  }
371
327
 
372
328
  .scribdown-mermaid-viewer__canvas {
@@ -375,6 +331,10 @@
375
331
  background: var(--scribdown-color-surface);
376
332
  border-radius: 6px 7px 5px 6px;
377
333
  box-shadow: 6px 8px 0 color-mix(in srgb, var(--scribdown-color-text-primary) 26%, transparent);
334
+ user-select: text;
335
+ }
336
+
337
+ .scribdown-mermaid-viewer--drag-mode .scribdown-mermaid-viewer__canvas {
378
338
  user-select: none;
379
339
  }
380
340
 
@@ -394,9 +354,8 @@
394
354
  width: 100%;
395
355
  }
396
356
 
397
- .scribdown-mermaid-viewer__button {
398
- width: 34px;
399
- height: 34px;
357
+ .scribdown-mermaid-viewer {
358
+ --scribdown-viewer-control-size: 34px;
400
359
  }
401
360
 
402
361
  .scribdown-mermaid-viewer__viewport {
@@ -54,6 +54,69 @@
54
54
  box-shadow: none;
55
55
  }
56
56
 
57
+ /* 表格交互壳层:复制按钮固定在右上角,不随表格横向滚动。 */
58
+ .scribdown-markdown .scribdown-table {
59
+ --scribdown-table-ink-token: var(--scribdown-color-accent);
60
+ position: relative;
61
+ width: max-content;
62
+ max-width: 100%;
63
+ margin: 0 0 var(--scribdown-space-3);
64
+ }
65
+
66
+ .scribdown-markdown .scribdown-table > table {
67
+ margin: 0;
68
+ }
69
+
70
+ /* 为右上角复制按钮预留首行末列空间,避免遮住表头内容。 */
71
+ .scribdown-markdown
72
+ .scribdown-table
73
+ > table
74
+ > :is(thead, tbody, tfoot)
75
+ > tr:first-child
76
+ > *:last-child,
77
+ .scribdown-markdown .scribdown-table > table > tr:first-child > *:last-child {
78
+ padding-right: 52px;
79
+ }
80
+
81
+ .scribdown-markdown .scribdown-table__copy {
82
+ position: absolute;
83
+ z-index: 4;
84
+ top: 7px;
85
+ right: 8px;
86
+ opacity: 0;
87
+ background: color-mix(in srgb, var(--scribdown-color-surface) 88%, transparent);
88
+ box-shadow: 0 1px 0 color-mix(in srgb, var(--scribdown-table-ink-token) 34%, transparent);
89
+ color: var(--scribdown-table-ink-token);
90
+ pointer-events: none;
91
+ transition:
92
+ opacity var(--scribdown-duration-fast) var(--scribdown-easing-standard),
93
+ background var(--scribdown-duration-fast) var(--scribdown-easing-standard);
94
+ }
95
+
96
+ /* 鼠标进入表格或键盘焦点进入壳层时展示;复制反馈期间保持可见。 */
97
+ .scribdown-markdown .scribdown-table:hover > .scribdown-table__copy,
98
+ .scribdown-markdown .scribdown-table:focus-within > .scribdown-table__copy,
99
+ .scribdown-markdown .scribdown-table > .scribdown-table__copy[data-scribdown-copied="true"] {
100
+ opacity: 1;
101
+ pointer-events: auto;
102
+ }
103
+
104
+ .scribdown-markdown .scribdown-table__copy:hover {
105
+ background: color-mix(
106
+ in srgb,
107
+ var(--scribdown-color-surface) 72%,
108
+ var(--scribdown-table-ink-token) 16%
109
+ );
110
+ }
111
+
112
+ /* 无 hover 能力的触屏设备始终展示入口,避免复制能力不可发现。 */
113
+ @media (hover: none) {
114
+ .scribdown-markdown .scribdown-table__copy {
115
+ opacity: 1;
116
+ pointer-events: auto;
117
+ }
118
+ }
119
+
57
120
  /* 关键步骤:表格外框复用代码块同款边条结构。 */
58
121
  .scribdown-markdown table::after {
59
122
  content: "";
@@ -72,10 +135,8 @@
72
135
  right -1px top 0px;
73
136
  background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
74
137
  background-size:
75
- var(--scribdown-table-border-tile-horizontal),
76
- var(--scribdown-table-border-tile-horizontal),
77
- var(--scribdown-table-border-tile-vertical),
78
- var(--scribdown-table-border-tile-vertical);
138
+ var(--scribdown-table-border-tile-horizontal), var(--scribdown-table-border-tile-horizontal),
139
+ var(--scribdown-table-border-tile-vertical), var(--scribdown-table-border-tile-vertical);
79
140
  }
80
141
 
81
142
  .scribdown-markdown th,
@@ -228,10 +289,8 @@
228
289
  right top;
229
290
  -webkit-mask-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
230
291
  -webkit-mask-size:
231
- var(--scribdown-table-border-tile-horizontal),
232
- var(--scribdown-table-border-tile-horizontal),
233
- var(--scribdown-table-border-tile-vertical),
234
- var(--scribdown-table-border-tile-vertical);
292
+ var(--scribdown-table-border-tile-horizontal), var(--scribdown-table-border-tile-horizontal),
293
+ var(--scribdown-table-border-tile-vertical), var(--scribdown-table-border-tile-vertical);
235
294
  -webkit-mask-mode: alpha, alpha, alpha, alpha;
236
295
  mask-image:
237
296
  var(--scribdown-rough-line-shadow-horizontal), var(--scribdown-rough-line-shadow-horizontal),
@@ -243,10 +302,8 @@
243
302
  right -1px top 0px;
244
303
  mask-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
245
304
  mask-size:
246
- var(--scribdown-table-border-tile-horizontal),
247
- var(--scribdown-table-border-tile-horizontal),
248
- var(--scribdown-table-border-tile-vertical),
249
- var(--scribdown-table-border-tile-vertical);
305
+ var(--scribdown-table-border-tile-horizontal), var(--scribdown-table-border-tile-horizontal),
306
+ var(--scribdown-table-border-tile-vertical), var(--scribdown-table-border-tile-vertical);
250
307
  mask-mode: alpha, alpha, alpha, alpha;
251
308
  }
252
309
  }
@@ -1,60 +1,125 @@
1
- /* ─── Token 定义 ───────────────────────────────────────────────────── */
2
- /* 浅色主题:参考素描本米白纸张与水彩颜料色相。
1
+ /* ─── 调色板原始值 ─────────────────────────────────────────────────
2
+ 浅色与暗色两套色值在此各定义一次,下方的「语义 Token」只做 var() 映射。
3
+ 宿主切换主题时不会出现色值副本,改一处即两套主题同步生效。
4
+
5
+ 浅色主题:参考素描本米白纸张与水彩颜料色相。
3
6
  长时间阅读偏好:暖色偏移降低蓝光眩光、文字采用深沉柏木色而非纯黑、
4
- 重点色保持低饱和的"褪色颜料"质感、纸面与卡面亮度差拉开以便内容浮起。 */
7
+ 重点色保持低饱和的"褪色颜料"质感、纸面与卡面亮度差拉开以便内容浮起。
8
+
9
+ 暗色主题:"夜读台灯下的旧纸册":
10
+ 纸面为接近黑的暖褐底,墨色反相为米白;颜料色以"粉笔/水彩"的提亮版本出现,
11
+ 保持与浅色主题一致的色相与语义。
12
+
13
+ 注:blockquote 系列是从其他 Token 派生的 color-mix 结果,两套主题的配比不同,
14
+ 故同样分别定义;它们在被引用的那个映射块里求值,取到的必然是同主题的基准色。 */
5
15
  :root {
6
16
  /* 暖米纸:略冷于旧版的牛皮黄,减轻长时间阅读的"陈旧报纸"感。 */
7
- --scribdown-color-bg: #ebe1c8;
17
+ --scribdown-palette-light-bg: #ebe1c8;
8
18
  /* 内容纸面:进一步提亮但保持暖调,与底色形成清晰层次。 */
9
- --scribdown-color-surface: #f8f0db;
19
+ --scribdown-palette-light-surface: #f8f0db;
10
20
  /* 主文字:深胡桃色沉淀墨,对比 surface ≈12:1,足够锐利又不刺眼。 */
11
- --scribdown-color-text-primary: #2f2620;
21
+ --scribdown-palette-light-text-primary: #2f2620;
12
22
  /* 次文字:泛黄旧墨色。 */
13
- --scribdown-color-text-secondary: #786758;
23
+ --scribdown-palette-light-text-secondary: #786758;
14
24
  /* 主题色:松林青苔——明度居中、与文字蓝相区分。 */
15
- --scribdown-color-accent: #436b5b;
25
+ --scribdown-palette-light-accent: #436b5b;
16
26
  /* 链接色:靛青水墨蓝,去掉过往略带紫感的偏色。 */
17
- --scribdown-color-link: #355a7d;
27
+ --scribdown-palette-light-link: #355a7d;
18
28
  /* 已访问链接:晾干后的紫罗兰,色相比未访问偏暖。 */
19
- --scribdown-color-link-visited: #6a527b;
29
+ --scribdown-palette-light-link-visited: #6a527b;
20
30
  /* 高亮笔色:姜黄荧光,保留涂抹的颜料质地。 */
21
- --scribdown-color-mark: #d7ab48;
31
+ --scribdown-palette-light-mark: #d7ab48;
22
32
  /* 边线:铅笔石墨与纸张混合后的暖灰。 */
23
- --scribdown-color-border: #c5ad8a;
33
+ --scribdown-palette-light-border: #c5ad8a;
24
34
  /* 危险色:陶土红,去除生硬的猩红,落在书法朱砂。 */
25
- --scribdown-color-danger: #a8504a;
35
+ --scribdown-palette-light-danger: #a8504a;
26
36
  /* 警告色:烧赭石。 */
27
- --scribdown-color-warning: #8d6432;
37
+ --scribdown-palette-light-warning: #8d6432;
28
38
  /* 代码块墨色:板岩紫,与正文棕色明显区分但不抢眼。 */
29
- --scribdown-color-code-ink: #5e5483;
30
- --scribdown-color-blockquote-bg: color-mix(
39
+ --scribdown-palette-light-code-ink: #5e5483;
40
+ --scribdown-palette-light-blockquote-bg: color-mix(
31
41
  in srgb,
32
42
  var(--scribdown-color-border) 18%,
33
43
  var(--scribdown-color-surface)
34
44
  );
35
- --scribdown-color-blockquote-text: color-mix(
45
+ --scribdown-palette-light-blockquote-text: color-mix(
36
46
  in srgb,
37
47
  var(--scribdown-color-text-secondary) 88%,
38
48
  var(--scribdown-color-surface)
39
49
  );
40
- --scribdown-color-blockquote-link: color-mix(
50
+ --scribdown-palette-light-blockquote-link: color-mix(
41
51
  in srgb,
42
52
  var(--scribdown-color-link) 86%,
43
53
  var(--scribdown-color-text-primary)
44
54
  );
45
- --scribdown-color-blockquote-link-visited: color-mix(
55
+ --scribdown-palette-light-blockquote-link-visited: color-mix(
46
56
  in srgb,
47
57
  var(--scribdown-color-link-visited) 86%,
48
58
  var(--scribdown-color-text-primary)
49
59
  );
50
60
  /* 纸面颗粒:低饱和的褐色噪点,呼应"米黄毛边纸"。 */
51
- --scribdown-paper-grain: rgba(132, 96, 44, 0.10);
61
+ --scribdown-palette-light-paper-grain: rgba(132, 96, 44, 0.10);
52
62
  /* 纸面纤维:浅青苔色丝纹,与 accent 同源。 */
53
- --scribdown-paper-fiber: rgba(67, 107, 91, 0.06);
63
+ --scribdown-palette-light-paper-fiber: rgba(67, 107, 91, 0.06);
54
64
  /* 偏移阴影:保留手绘的"墨晕"感,避免过黑。 */
55
- --scribdown-shadow-sm: 2px 3px 0 rgba(47, 38, 32, 0.13);
56
- --scribdown-shadow-md: 4px 6px 0 rgba(47, 38, 32, 0.18);
65
+ --scribdown-palette-light-shadow-sm: 2px 3px 0 rgba(47, 38, 32, 0.13);
66
+ --scribdown-palette-light-shadow-md: 4px 6px 0 rgba(47, 38, 32, 0.18);
57
67
 
68
+ /* 夜间纸面底:暖褐近黑,避免冷调灰带来的"屏幕感"。 */
69
+ --scribdown-palette-dark-bg: #1e1915;
70
+ /* 卡面:底色之上 +6% 明度,让代码块/引用清晰浮起。 */
71
+ --scribdown-palette-dark-surface: #2a241f;
72
+ /* 主文字:温润米白粉笔。 */
73
+ --scribdown-palette-dark-text-primary: #ebdfcc;
74
+ /* 次文字:旧字迹褪色。 */
75
+ --scribdown-palette-dark-text-secondary: #ae9b85;
76
+ /* 主题色:粉笔薄荷青,亮度提到暗底易读区间。 */
77
+ --scribdown-palette-dark-accent: #7ebbab;
78
+ /* 链接色:粉笔水蓝。 */
79
+ --scribdown-palette-dark-link: #94b8de;
80
+ /* 已访问链接:粉笔薰衣草。 */
81
+ --scribdown-palette-dark-link-visited: #b39bcd;
82
+ /* 高亮色:暖琥珀粉笔。 */
83
+ --scribdown-palette-dark-mark: #d3aa57;
84
+ /* 边线:暗青铜,与底色同色相一脉。 */
85
+ --scribdown-palette-dark-border: #5a4a39;
86
+ /* 危险色:暗红粉笔。 */
87
+ --scribdown-palette-dark-danger: #db847a;
88
+ /* 警告色:黄铜粉笔。 */
89
+ --scribdown-palette-dark-warning: #d3a45f;
90
+ /* 代码块墨色:紫罗兰粉笔。 */
91
+ --scribdown-palette-dark-code-ink: #beacdc;
92
+ --scribdown-palette-dark-blockquote-bg: color-mix(
93
+ in srgb,
94
+ var(--scribdown-color-border) 28%,
95
+ var(--scribdown-color-surface)
96
+ );
97
+ --scribdown-palette-dark-blockquote-text: color-mix(
98
+ in srgb,
99
+ var(--scribdown-color-text-secondary) 90%,
100
+ var(--scribdown-color-bg)
101
+ );
102
+ --scribdown-palette-dark-blockquote-link: color-mix(
103
+ in srgb,
104
+ var(--scribdown-color-link) 88%,
105
+ var(--scribdown-color-text-primary)
106
+ );
107
+ --scribdown-palette-dark-blockquote-link-visited: color-mix(
108
+ in srgb,
109
+ var(--scribdown-color-link-visited) 88%,
110
+ var(--scribdown-color-text-primary)
111
+ );
112
+ /* 夜间纸面颗粒:暖琥珀微噪。 */
113
+ --scribdown-palette-dark-paper-grain: rgba(211, 170, 87, 0.10);
114
+ /* 夜间纸面纤维:薄荷青丝纹。 */
115
+ --scribdown-palette-dark-paper-fiber: rgba(126, 187, 171, 0.07);
116
+ /* 阴影更深以拉开层次。 */
117
+ --scribdown-palette-dark-shadow-sm: 2px 3px 0 rgba(0, 0, 0, 0.36);
118
+ --scribdown-palette-dark-shadow-md: 4px 6px 0 rgba(0, 0, 0, 0.48);
119
+ }
120
+
121
+ /* ─── 与主题无关的 Token ──────────────────────────────────────────── */
122
+ :root {
58
123
  --scribdown-font-body: "Source Serif 4", "Noto Serif SC", serif;
59
124
  --scribdown-font-heading: "Caveat", "LXGW WenKai", "Noto Serif SC", serif;
60
125
  --scribdown-font-code: "JetBrains Mono", "Fira Code", monospace;
@@ -80,61 +145,82 @@
80
145
  --scribdown-toc-toggle-icon: url("../assets/toc-branch-toggle.svg");
81
146
  }
82
147
 
83
- /* 暗色主题:"夜读台灯下的旧纸册":
84
- 纸面为接近黑的暖褐底,墨色反相为米白;颜料色以"粉笔/水彩"的提亮版本出现,
85
- 保持与浅色主题一致的色相与语义。 */
148
+ /* ─── 语义 Token ← 浅色 ────────────────────────────────────────────
149
+ 默认主题。宿主给根元素显式加 .scribdown-theme-light 时,
150
+ 该选择器的更高优先级会盖过下方「跟随系统」的暗色映射,实现强制浅色。 */
151
+ :root,
152
+ :root.scribdown-theme-light {
153
+ --scribdown-color-bg: var(--scribdown-palette-light-bg);
154
+ --scribdown-color-surface: var(--scribdown-palette-light-surface);
155
+ --scribdown-color-text-primary: var(--scribdown-palette-light-text-primary);
156
+ --scribdown-color-text-secondary: var(--scribdown-palette-light-text-secondary);
157
+ --scribdown-color-accent: var(--scribdown-palette-light-accent);
158
+ --scribdown-color-link: var(--scribdown-palette-light-link);
159
+ --scribdown-color-link-visited: var(--scribdown-palette-light-link-visited);
160
+ --scribdown-color-mark: var(--scribdown-palette-light-mark);
161
+ --scribdown-color-border: var(--scribdown-palette-light-border);
162
+ --scribdown-color-danger: var(--scribdown-palette-light-danger);
163
+ --scribdown-color-warning: var(--scribdown-palette-light-warning);
164
+ --scribdown-color-code-ink: var(--scribdown-palette-light-code-ink);
165
+ --scribdown-color-blockquote-bg: var(--scribdown-palette-light-blockquote-bg);
166
+ --scribdown-color-blockquote-text: var(--scribdown-palette-light-blockquote-text);
167
+ --scribdown-color-blockquote-link: var(--scribdown-palette-light-blockquote-link);
168
+ --scribdown-color-blockquote-link-visited: var(--scribdown-palette-light-blockquote-link-visited);
169
+ --scribdown-paper-grain: var(--scribdown-palette-light-paper-grain);
170
+ --scribdown-paper-fiber: var(--scribdown-palette-light-paper-fiber);
171
+ --scribdown-shadow-sm: var(--scribdown-palette-light-shadow-sm);
172
+ --scribdown-shadow-md: var(--scribdown-palette-light-shadow-md);
173
+ }
174
+
175
+ /* ─── 语义 Token ← 暗色(跟随系统偏好)───────────────────────────── */
86
176
  @media (prefers-color-scheme: dark) {
87
177
  :root {
88
- /* 夜间纸面底:暖褐近黑,避免冷调灰带来的"屏幕感"。 */
89
- --scribdown-color-bg: #1e1915;
90
- /* 卡面:底色之上 +6% 明度,让代码块/引用清晰浮起。 */
91
- --scribdown-color-surface: #2a241f;
92
- /* 主文字:温润米白粉笔。 */
93
- --scribdown-color-text-primary: #ebdfcc;
94
- /* 次文字:旧字迹褪色。 */
95
- --scribdown-color-text-secondary: #ae9b85;
96
- /* 主题色:粉笔薄荷青,亮度提到暗底易读区间。 */
97
- --scribdown-color-accent: #7ebbab;
98
- /* 链接色:粉笔水蓝。 */
99
- --scribdown-color-link: #94b8de;
100
- /* 已访问链接:粉笔薰衣草。 */
101
- --scribdown-color-link-visited: #b39bcd;
102
- /* 高亮色:暖琥珀粉笔。 */
103
- --scribdown-color-mark: #d3aa57;
104
- /* 边线:暗青铜,与底色同色相一脉。 */
105
- --scribdown-color-border: #5a4a39;
106
- /* 危险色:暗红粉笔。 */
107
- --scribdown-color-danger: #db847a;
108
- /* 警告色:黄铜粉笔。 */
109
- --scribdown-color-warning: #d3a45f;
110
- /* 代码块墨色:紫罗兰粉笔。 */
111
- --scribdown-color-code-ink: #beacdc;
112
- --scribdown-color-blockquote-bg: color-mix(
113
- in srgb,
114
- var(--scribdown-color-border) 28%,
115
- var(--scribdown-color-surface)
116
- );
117
- --scribdown-color-blockquote-text: color-mix(
118
- in srgb,
119
- var(--scribdown-color-text-secondary) 90%,
120
- var(--scribdown-color-bg)
121
- );
122
- --scribdown-color-blockquote-link: color-mix(
123
- in srgb,
124
- var(--scribdown-color-link) 88%,
125
- var(--scribdown-color-text-primary)
126
- );
127
- --scribdown-color-blockquote-link-visited: color-mix(
128
- in srgb,
129
- var(--scribdown-color-link-visited) 88%,
130
- var(--scribdown-color-text-primary)
131
- );
132
- /* 夜间纸面颗粒:暖琥珀微噪。 */
133
- --scribdown-paper-grain: rgba(211, 170, 87, 0.10);
134
- /* 夜间纸面纤维:薄荷青丝纹。 */
135
- --scribdown-paper-fiber: rgba(126, 187, 171, 0.07);
136
- /* 阴影更深以拉开层次。 */
137
- --scribdown-shadow-sm: 2px 3px 0 rgba(0, 0, 0, 0.36);
138
- --scribdown-shadow-md: 4px 6px 0 rgba(0, 0, 0, 0.48);
178
+ --scribdown-color-bg: var(--scribdown-palette-dark-bg);
179
+ --scribdown-color-surface: var(--scribdown-palette-dark-surface);
180
+ --scribdown-color-text-primary: var(--scribdown-palette-dark-text-primary);
181
+ --scribdown-color-text-secondary: var(--scribdown-palette-dark-text-secondary);
182
+ --scribdown-color-accent: var(--scribdown-palette-dark-accent);
183
+ --scribdown-color-link: var(--scribdown-palette-dark-link);
184
+ --scribdown-color-link-visited: var(--scribdown-palette-dark-link-visited);
185
+ --scribdown-color-mark: var(--scribdown-palette-dark-mark);
186
+ --scribdown-color-border: var(--scribdown-palette-dark-border);
187
+ --scribdown-color-danger: var(--scribdown-palette-dark-danger);
188
+ --scribdown-color-warning: var(--scribdown-palette-dark-warning);
189
+ --scribdown-color-code-ink: var(--scribdown-palette-dark-code-ink);
190
+ --scribdown-color-blockquote-bg: var(--scribdown-palette-dark-blockquote-bg);
191
+ --scribdown-color-blockquote-text: var(--scribdown-palette-dark-blockquote-text);
192
+ --scribdown-color-blockquote-link: var(--scribdown-palette-dark-blockquote-link);
193
+ --scribdown-color-blockquote-link-visited: var(--scribdown-palette-dark-blockquote-link-visited);
194
+ --scribdown-paper-grain: var(--scribdown-palette-dark-paper-grain);
195
+ --scribdown-paper-fiber: var(--scribdown-palette-dark-paper-fiber);
196
+ --scribdown-shadow-sm: var(--scribdown-palette-dark-shadow-sm);
197
+ --scribdown-shadow-md: var(--scribdown-palette-dark-shadow-md);
139
198
  }
140
199
  }
200
+
201
+ /* ─── 语义 Token ← 暗色(宿主显式指定)─────────────────────────────
202
+ 宿主自带主题开关(如文档站的明暗切换、VS Code 主题)时,把 .scribdown-theme-dark
203
+ 加到根元素上即可强制暗色;优先级高于上面的系统偏好映射,不受 OS 设置影响。
204
+ 与「跟随系统」共用同一套调色板变量,色值仍只有一份。 */
205
+ :root.scribdown-theme-dark {
206
+ --scribdown-color-bg: var(--scribdown-palette-dark-bg);
207
+ --scribdown-color-surface: var(--scribdown-palette-dark-surface);
208
+ --scribdown-color-text-primary: var(--scribdown-palette-dark-text-primary);
209
+ --scribdown-color-text-secondary: var(--scribdown-palette-dark-text-secondary);
210
+ --scribdown-color-accent: var(--scribdown-palette-dark-accent);
211
+ --scribdown-color-link: var(--scribdown-palette-dark-link);
212
+ --scribdown-color-link-visited: var(--scribdown-palette-dark-link-visited);
213
+ --scribdown-color-mark: var(--scribdown-palette-dark-mark);
214
+ --scribdown-color-border: var(--scribdown-palette-dark-border);
215
+ --scribdown-color-danger: var(--scribdown-palette-dark-danger);
216
+ --scribdown-color-warning: var(--scribdown-palette-dark-warning);
217
+ --scribdown-color-code-ink: var(--scribdown-palette-dark-code-ink);
218
+ --scribdown-color-blockquote-bg: var(--scribdown-palette-dark-blockquote-bg);
219
+ --scribdown-color-blockquote-text: var(--scribdown-palette-dark-blockquote-text);
220
+ --scribdown-color-blockquote-link: var(--scribdown-palette-dark-blockquote-link);
221
+ --scribdown-color-blockquote-link-visited: var(--scribdown-palette-dark-blockquote-link-visited);
222
+ --scribdown-paper-grain: var(--scribdown-palette-dark-paper-grain);
223
+ --scribdown-paper-fiber: var(--scribdown-palette-dark-paper-fiber);
224
+ --scribdown-shadow-sm: var(--scribdown-palette-dark-shadow-sm);
225
+ --scribdown-shadow-md: var(--scribdown-palette-dark-shadow-md);
226
+ }
@@ -88,8 +88,7 @@
88
88
  align-self: stretch;
89
89
  margin-right: 2px;
90
90
  padding: 0 6px 0 4px;
91
- border-right: 1px solid
92
- color-mix(in srgb, var(--scribdown-color-border) 70%, transparent);
91
+ border-right: 1px solid color-mix(in srgb, var(--scribdown-color-border) 70%, transparent);
93
92
  /* 关键步骤:可点击跳转到当前章节标题。 */
94
93
  cursor: pointer;
95
94
  }
@@ -145,19 +144,35 @@
145
144
  opacity: 1;
146
145
  }
147
146
 
148
- /* 「更多」按钮展开态:保持轻量描边,避免被 hover 态覆盖。 */
149
- .scribdown-toolbar-btn--more[aria-expanded="true"] {
147
+ /* 工具栏按钮展开态(目录侧栏 / 更多菜单共用):底色加深 + 强调色,
148
+ hover 态区分开,让「当前已展开」在按钮上可见。 */
149
+ .scribdown-toolbar-btn[aria-expanded="true"] {
150
150
  background: color-mix(in srgb, var(--scribdown-color-bg) 90%, transparent);
151
151
  color: var(--scribdown-color-accent);
152
152
  }
153
153
 
154
+ /* 关键步骤:展开态下方一小段强调色下划线,作为颜色之外的第二重状态提示(色觉障碍友好)。 */
155
+ .scribdown-toolbar-btn[aria-expanded="true"]::before {
156
+ content: "";
157
+ position: absolute;
158
+ bottom: 2px;
159
+ left: 50%;
160
+ width: 12px;
161
+ height: 2px;
162
+ transform: translateX(-50%);
163
+ background: var(--scribdown-color-accent);
164
+ border-radius: 999px;
165
+ }
166
+
154
167
  /* ─── 更多下拉菜单 ──────────────────────────────────────────────── */
155
168
  /* 关键步骤:菜单挂在 .scribdown-toolbar 内部,绝对定位到工具栏右下方。 */
156
169
  .scribdown-toolbar-menu {
170
+ --scribdown-toolbar-menu-width: 260px;
157
171
  position: absolute;
158
172
  top: calc(100% + 6px);
159
173
  right: 0;
160
- min-width: 200px;
174
+ width: var(--scribdown-toolbar-menu-width);
175
+ box-sizing: border-box;
161
176
  padding: var(--scribdown-space-1);
162
177
  background: var(--scribdown-color-surface);
163
178
  border: 1.5px solid var(--scribdown-color-border);
@@ -221,11 +236,12 @@
221
236
  .scribdown-toolbar-menu-group {
222
237
  display: flex;
223
238
  flex-direction: column;
239
+ /* 语言与宽度列表的容器、间隙均保留可点击指针,避免层级间光标闪回默认样式。 */
240
+ cursor: pointer;
224
241
  /* 关键步骤:和上方菜单项之间用一条柔和分隔线划开层级。 */
225
242
  margin-top: 4px;
226
243
  padding-top: 4px;
227
- border-top: 1px solid
228
- color-mix(in srgb, var(--scribdown-color-border) 70%, transparent);
244
+ border-top: 1px solid color-mix(in srgb, var(--scribdown-color-border) 70%, transparent);
229
245
  }
230
246
 
231
247
  /* 触发行:复用 .scribdown-toolbar-menu-item 样式,右侧追加当前值 + chevron。 */
@@ -241,6 +257,7 @@
241
257
  font-family: var(--scribdown-font-code);
242
258
  font-size: 12px;
243
259
  color: var(--scribdown-color-text-secondary);
260
+ white-space: nowrap;
244
261
  }
245
262
 
246
263
  .scribdown-toolbar-menu-item--select:hover .scribdown-toolbar-menu-select-value {
@@ -263,6 +280,7 @@
263
280
  display: flex;
264
281
  flex-direction: column;
265
282
  gap: 2px;
283
+ cursor: pointer;
266
284
  /* 关键步骤:与触发行文字左对齐(icon 16 + gap 8 = 24,再多 4 给视觉缩进)。 */
267
285
  padding: 0 4px 0 28px;
268
286
  max-height: 0;
@@ -273,11 +291,54 @@
273
291
  }
274
292
 
275
293
  .scribdown-toolbar-menu-group.is-open .scribdown-toolbar-menu-group-choices {
276
- /* 关键步骤:固定档位最多 4 × 30px ≈ 160px,给点冗余兜底字体加大。 */
277
- max-height: 200px;
294
+ /* 关键步骤:语言选择器有 11 项,常规视口完整展示;小视口按剩余空间滚动,避免被裁切。 */
295
+ max-height: min(360px, calc(100vh - 190px));
296
+ overflow-y: auto;
278
297
  padding: 4px 4px 4px 28px;
279
298
  }
280
299
 
300
+ /* 关键步骤:语言列表始终固定在浮层位置;开合仅过渡可组合属性,避免定位与高度同时跳变。 */
301
+ .scribdown-toolbar-menu-group.scribdown-toolbar-menu-group--language
302
+ .scribdown-toolbar-menu-group-choices {
303
+ position: fixed;
304
+ top: 42px;
305
+ right: calc(var(--scribdown-toolbar-menu-width) + 6px);
306
+ width: 220px;
307
+ max-height: calc(100vh - 54px);
308
+ box-sizing: border-box;
309
+ padding: 4px;
310
+ overflow-y: auto;
311
+ background: var(--scribdown-color-surface);
312
+ border: 1.5px solid var(--scribdown-color-border);
313
+ border-radius: var(--scribdown-radius-md);
314
+ box-shadow: var(--scribdown-shadow-md);
315
+ opacity: 0;
316
+ visibility: hidden;
317
+ pointer-events: none;
318
+ transform: translateX(4px);
319
+ transition:
320
+ opacity var(--scribdown-duration-fast) var(--scribdown-easing-standard),
321
+ transform var(--scribdown-duration-fast) var(--scribdown-easing-standard),
322
+ visibility var(--scribdown-duration-fast) var(--scribdown-easing-standard);
323
+ }
324
+
325
+ .scribdown-toolbar-menu-group.scribdown-toolbar-menu-group--language.is-open
326
+ .scribdown-toolbar-menu-group-choices {
327
+ opacity: 1;
328
+ visibility: visible;
329
+ pointer-events: auto;
330
+ transform: translateX(0);
331
+ }
332
+
333
+ @media (max-width: 560px) {
334
+ .scribdown-toolbar-menu-group.scribdown-toolbar-menu-group--language
335
+ .scribdown-toolbar-menu-group-choices {
336
+ right: 6px;
337
+ left: 6px;
338
+ width: auto;
339
+ }
340
+ }
341
+
281
342
  /* 档位选项:垂直列表项,左侧勾选位预留固定宽度,避免选中切换时文本抖动。 */
282
343
  .scribdown-toolbar-menu-sub-item {
283
344
  display: flex;
@@ -299,6 +360,13 @@
299
360
  background var(--scribdown-duration-fast) var(--scribdown-easing-standard);
300
361
  }
301
362
 
363
+ /* 关键步骤:文字与勾选图标继承 button 的 pointer;列表空隙则由 choices 容器承接。 */
364
+ .scribdown-toolbar-menu-sub-item-label,
365
+ .scribdown-toolbar-menu-sub-item-mark,
366
+ .scribdown-toolbar-menu-sub-item-mark svg {
367
+ cursor: inherit;
368
+ }
369
+
302
370
  .scribdown-toolbar-menu-sub-item-mark {
303
371
  display: inline-flex;
304
372
  align-items: center;
@@ -338,7 +406,8 @@
338
406
  .scribdown-toc-host {
339
407
  display: flex;
340
408
  align-items: stretch;
341
- /* TOC 宽度提到容器层,供 TOC 自身定宽 / 折叠位移共用。 */
409
+ /* TOC 宽度提到容器层,供 TOC 自身定宽 / 折叠位移共用;
410
+ 用户拖拽调宽后由 toolbar.ts 以内联样式覆盖本默认值。 */
342
411
  --scribdown-toc-width: min(280px, 70vw);
343
412
  /* 关键步骤:定高铺满视口;overflow:hidden 让整页不滚动,
344
413
  折叠态 TOC(负 margin)也被裁切,滚动全部下沉到 content-scroll。 */
@@ -370,12 +439,18 @@
370
439
  overflow: auto;
371
440
  }
372
441
 
373
- /* 目录侧栏:flex item 贴最左,固定宽度;默认 margin-left 负值收进容器左外,is-open 归零滑入。 */
442
+ /* 拖拽调宽期间:屏蔽正文文本选中并全局统一光标,避免拖动时误选内容 / 光标闪烁。 */
443
+ .scribdown-toc-host.is-toc-resizing {
444
+ cursor: col-resize;
445
+ user-select: none;
446
+ }
447
+
448
+ /* 目录侧栏:flex item 贴最左,固定宽度;默认 margin-left 负值收进容器左外,is-open 归零滑入。
449
+ 宽度变量由 .scribdown-toc-host 提供(用户拖拽后为内联覆盖值),此处仅做 fallback 兜底。 */
374
450
  .scribdown-toolbar-toc-panel {
375
- --scribdown-toc-width: min(280px, 70vw);
376
451
  flex-shrink: 0;
377
452
  box-sizing: border-box;
378
- width: var(--scribdown-toc-width);
453
+ width: var(--scribdown-toc-width, min(280px, 70vw));
379
454
  /* 关键步骤:填满外层容器高度(flex stretch 对齐 + 显式 100% 兜底),
380
455
  内部支持横向 + 纵向滚动,超长 / 超宽目录条目在面板内自滚。 */
381
456
  height: 100%;
@@ -390,7 +465,7 @@
390
465
  padding: var(--scribdown-space-4);
391
466
  /* 关键步骤:margin-left 负值占据负向布局空间收起,正文 flex:1 自然占满全宽;
392
467
  切到 0 时正文让出 var(--scribdown-toc-width),整体平滑过渡。 */
393
- margin-left: calc(-1 * var(--scribdown-toc-width));
468
+ margin-left: calc(-1 * var(--scribdown-toc-width, min(280px, 70vw)));
394
469
  transition: margin-left var(--scribdown-duration-base) var(--scribdown-easing-standard);
395
470
  z-index: 9001;
396
471
  }
@@ -399,6 +474,51 @@
399
474
  margin-left: 0;
400
475
  }
401
476
 
477
+ /* ─── 目录调宽手柄 ─────────────────────────────────────────────
478
+ 夹在目录侧栏与正文之间的 flex item:收起态宽度为 0(随侧栏一起塌陷,正文不留空条),
479
+ 展开态占 6px 命中区,内部 ::after 画一条居中细线,hover / 拖拽时点亮为主题强调色。 */
480
+ .scribdown-toc-resizer {
481
+ position: relative;
482
+ flex: 0 0 auto;
483
+ width: 0;
484
+ /* 关键步骤:与侧栏 margin-left 同一时长的过渡,开合时手柄与侧栏同步进出。 */
485
+ transition: width var(--scribdown-duration-base) var(--scribdown-easing-standard);
486
+ overflow: hidden;
487
+ cursor: col-resize;
488
+ /* 收起态不可交互 / 不可聚焦命中,展开时再恢复。 */
489
+ pointer-events: none;
490
+ /* 关键步骤:拖拽为横向手势,禁用触摸端的默认横向平移,避免与页面滚动争抢。 */
491
+ touch-action: none;
492
+ z-index: 9001;
493
+ }
494
+
495
+ .scribdown-toc-resizer.is-open {
496
+ width: 6px;
497
+ pointer-events: auto;
498
+ }
499
+
500
+ .scribdown-toc-resizer::after {
501
+ content: "";
502
+ position: absolute;
503
+ top: 0;
504
+ bottom: 0;
505
+ left: 50%;
506
+ width: 2px;
507
+ transform: translateX(-50%);
508
+ background: transparent;
509
+ transition: background var(--scribdown-duration-fast) var(--scribdown-easing-standard);
510
+ }
511
+
512
+ .scribdown-toc-resizer:hover::after,
513
+ .scribdown-toc-resizer:focus-visible::after,
514
+ .scribdown-toc-resizer.is-dragging::after {
515
+ background: var(--scribdown-color-accent);
516
+ }
517
+
518
+ .scribdown-toc-resizer:focus-visible {
519
+ outline: none;
520
+ }
521
+
402
522
  /* ─── 通用细滚动条(主题色,opt-in)────────────────────────────────
403
523
  目录侧栏(.scribdown-toolbar-toc-panel)与正文滚动层(.scribdown-content-scroll)共用:
404
524
  挂载时显式给滚动容器加 .scribdown-scrollbar-thin 引入,不在此罗列各容器选择器。
@@ -0,0 +1,96 @@
1
+ /* 图片 / Mermaid 查看器共用的顶部按钮与缩放按钮组。 */
2
+ .scribdown-viewer-control-button {
3
+ display: inline-flex;
4
+ flex: none;
5
+ align-items: center;
6
+ justify-content: center;
7
+ width: var(--scribdown-viewer-control-size, 28px);
8
+ height: var(--scribdown-viewer-control-size, 28px);
9
+ margin: 0;
10
+ padding: 0;
11
+ border: 1px solid color-mix(in srgb, var(--scribdown-color-border) 58%, transparent);
12
+ border-radius: 7px 9px 8px 10px;
13
+ background: color-mix(in srgb, var(--scribdown-color-surface) 88%, transparent);
14
+ box-shadow: 0 1px 0 color-mix(in srgb, var(--scribdown-color-border) 32%, transparent);
15
+ color: var(--scribdown-color-text-primary);
16
+ cursor: pointer;
17
+ font-family: var(--scribdown-font-code);
18
+ font-size: var(--scribdown-viewer-control-font-size, 13px);
19
+ font-weight: 700;
20
+ line-height: 1;
21
+ }
22
+
23
+ .scribdown-viewer-control-button svg {
24
+ pointer-events: none;
25
+ }
26
+
27
+ .scribdown-viewer-control-button:hover {
28
+ background: color-mix(
29
+ in srgb,
30
+ var(--scribdown-color-surface) 76%,
31
+ var(--scribdown-color-mark) 24%
32
+ );
33
+ }
34
+
35
+ .scribdown-viewer-control-button:focus-visible {
36
+ outline: 2px solid var(--scribdown-color-accent);
37
+ outline-offset: 2px;
38
+ }
39
+
40
+ .scribdown-viewer-control-button:disabled {
41
+ box-shadow: none;
42
+ cursor: default;
43
+ opacity: 0.42;
44
+ }
45
+
46
+ .scribdown-viewer-zoom-group {
47
+ display: inline-flex;
48
+ flex: none;
49
+ align-items: center;
50
+ overflow: hidden;
51
+ border: 1px solid color-mix(in srgb, var(--scribdown-color-border) 64%, transparent);
52
+ border-radius: 8px 10px 9px 11px;
53
+ background: color-mix(in srgb, var(--scribdown-color-surface) 88%, transparent);
54
+ box-shadow: 0 1px 0 color-mix(in srgb, var(--scribdown-color-border) 32%, transparent);
55
+ }
56
+
57
+ .scribdown-viewer-zoom-group .scribdown-viewer-control-button {
58
+ border: 0;
59
+ border-radius: 0;
60
+ background: transparent;
61
+ box-shadow: none;
62
+ }
63
+
64
+ .scribdown-viewer-zoom-group .scribdown-viewer-control-button:hover {
65
+ background: color-mix(
66
+ in srgb,
67
+ var(--scribdown-color-surface) 76%,
68
+ var(--scribdown-color-mark) 24%
69
+ );
70
+ }
71
+
72
+ .scribdown-viewer-zoom-group .scribdown-viewer-control-button:focus-visible {
73
+ position: relative;
74
+ z-index: 1;
75
+ outline-offset: -2px;
76
+ }
77
+
78
+ .scribdown-viewer-zoom-value {
79
+ display: inline-flex;
80
+ flex: none;
81
+ align-items: center;
82
+ justify-content: center;
83
+ min-width: var(--scribdown-viewer-zoom-value-min-width, 42px);
84
+ height: var(--scribdown-viewer-control-size, 28px);
85
+ border-right: 1px solid color-mix(in srgb, var(--scribdown-color-border) 48%, transparent);
86
+ border-left: 1px solid color-mix(in srgb, var(--scribdown-color-border) 48%, transparent);
87
+ background: color-mix(
88
+ in srgb,
89
+ var(--scribdown-color-surface) 94%,
90
+ var(--scribdown-color-border) 6%
91
+ );
92
+ color: color-mix(in srgb, var(--scribdown-color-text-primary) 78%, transparent);
93
+ font-family: var(--scribdown-font-code);
94
+ font-size: var(--scribdown-viewer-zoom-value-font-size, 12px);
95
+ font-weight: 700;
96
+ }
package/src/styles.css CHANGED
@@ -37,6 +37,12 @@
37
37
  /* 8. 代码:inline code + 代码块 + 语言标签 + 复制按钮 */
38
38
  @import "./styles/code.css";
39
39
 
40
+ /* 8.0.1 Mermaid / 表格共用复制按钮 */
41
+ @import "./styles/copy-control.css";
42
+
43
+ /* 8.0.2 图片 / Mermaid 查看器共用顶部控件 */
44
+ @import "./styles/viewer-controls.css";
45
+
40
46
  /* 8.1 Mermaid 图表块 */
41
47
  @import "./styles/mermaid.css";
42
48