@tnotesjs/core 0.1.27 → 0.2.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.
Files changed (71) hide show
  1. package/README.md +2 -1
  2. package/package.json +3 -1
  3. package/templates/sub-repo/.gitattributes +30 -0
  4. package/templates/sub-repo/.github/workflows/deploy.yml +87 -0
  5. package/templates/sub-repo/.vitepress/config.mts +12 -0
  6. package/templates/sub-repo/.vitepress/env.d.ts +10 -0
  7. package/templates/sub-repo/.vitepress/theme/index.ts +12 -0
  8. package/templates/sub-repo/.vscode/settings.json +330 -0
  9. package/templates/sub-repo/.vscode/tnotes.code-snippets +110 -0
  10. package/templates/sub-repo/public/favicon.ico +0 -0
  11. package/templates/sub-repo/public/logo.png +0 -0
  12. package/templates/sub-repo/tsconfig.json +45 -0
  13. package/vitepress/assets/icons/icon__setting_dark.svg +4 -0
  14. package/vitepress/assets/icons/icon__setting_light.svg +4 -0
  15. package/vitepress/assets/icons/index.ts +2 -2
  16. package/vitepress/client/localSearchIndexBridge.ts +24 -0
  17. package/vitepress/components/Discussions/Discussions.vue +1 -1
  18. package/vitepress/components/Footprints/Footprints.vue +90 -25
  19. package/vitepress/components/Layout/CustomSidebar.vue +489 -117
  20. package/vitepress/components/Layout/Layout.vue +5 -0
  21. package/vitepress/components/Layout/NavBarSettingsTrigger.vue +10 -2
  22. package/vitepress/components/Layout/SidebarItems.vue +517 -342
  23. package/vitepress/components/Layout/SidebarNavBefore.vue +1 -50
  24. package/vitepress/components/Layout/SidebarResizeHandle.vue +6 -23
  25. package/vitepress/components/Layout/composables/docLayoutLogic.ts +59 -0
  26. package/vitepress/components/Layout/composables/useDocLayout.test.ts +69 -0
  27. package/vitepress/components/Layout/composables/useDocLayout.ts +128 -0
  28. package/vitepress/components/Layout/composables/useSidebarDrag.ts +514 -0
  29. package/vitepress/components/Layout/composables/useSidebarLayout.ts +25 -8
  30. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +8 -3
  31. package/vitepress/components/Layout/sidebarCollapsedState.test.ts +183 -0
  32. package/vitepress/components/Layout/sidebarCollapsedState.ts +241 -0
  33. package/vitepress/components/Layout/sidebarDragLogic.test.ts +1146 -0
  34. package/vitepress/components/Layout/sidebarDragLogic.ts +1307 -0
  35. package/vitepress/components/Layout/sidebarHitTest.test.ts +572 -0
  36. package/vitepress/components/Layout/sidebarHitTest.ts +801 -0
  37. package/vitepress/components/Layout/sidebarItemRenderLogic.test.ts +53 -0
  38. package/vitepress/components/Layout/sidebarItemRenderLogic.ts +50 -0
  39. package/vitepress/components/MarkMap/MarkMap.vue +67 -10
  40. package/vitepress/components/Settings/Settings.vue +78 -74
  41. package/vitepress/components/SidebarCard/FolderTreeItems.vue +268 -0
  42. package/vitepress/components/SidebarCard/SidebarCard.vue +125 -274
  43. package/vitepress/components/constants.ts +18 -6
  44. package/vitepress/components/sidebar.data.ts +13 -11
  45. package/vitepress/components/sidebarTreeHelpers.test.ts +142 -0
  46. package/vitepress/components/sidebarTreeHelpers.ts +168 -0
  47. package/vitepress/components/utils/vscodePaths.test.ts +41 -0
  48. package/vitepress/components/utils/vscodePaths.ts +52 -0
  49. package/vitepress/config/index.ts +2 -0
  50. package/vitepress/plugins/localSearchIndexBuilder.ts +209 -0
  51. package/vitepress/plugins/localSearchReindex.test.ts +46 -0
  52. package/vitepress/plugins/localSearchReindexLogic.ts +50 -0
  53. package/vitepress/plugins/localSearchReindexPatch.test.ts +30 -0
  54. package/vitepress/plugins/localSearchReindexPatch.ts +37 -0
  55. package/vitepress/plugins/localSearchReindexPlugin.ts +318 -0
  56. package/vitepress/plugins/sidebarStructurePlugin.ts +209 -63
  57. package/vitepress/theme/index.ts +8 -0
  58. package/vitepress/theme/styles/base.scss +0 -8
  59. package/vitepress/theme/styles/components/markmap.scss +23 -2
  60. package/vitepress/theme/styles/components/swiper.scss +1 -1
  61. package/vitepress/theme/styles/doc-layout.scss +212 -0
  62. package/vitepress/theme/styles/index.scss +3 -0
  63. package/vitepress/theme/styles/layout.scss +60 -10
  64. package/dist/chunk-4KG6RXFS.js +0 -4637
  65. package/dist/chunk-AGSL3VZE.js +0 -193
  66. package/dist/cli/index.js +0 -683
  67. package/dist/index.js +0 -8
  68. package/dist/vitepress/config/index.js +0 -1178
  69. package/vitepress/assets/icons/icon__mindmap.svg +0 -1
  70. package/vitepress/assets/icons/icon__setting.svg +0 -1
  71. package/vitepress/components/SidebarCard/MindMapView.vue +0 -488
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ getSidebarItemRenderMode,
5
+ type SidebarRenderItem,
6
+ } from './sidebarItemRenderLogic'
7
+
8
+ /** introduction:TNotes 笔记书写规范 → 0027 → Giscus folder */
9
+ const giscusFolderAtDepth2: SidebarRenderItem = {
10
+ text: '评论功能的技术实现(Giscus)',
11
+ items: [
12
+ {
13
+ text: '⏰ 评论功能的技术实现(Giscus)',
14
+ link: '/notes/0003. 评论功能的技术实现(Giscus)/README',
15
+ },
16
+ ],
17
+ }
18
+
19
+ describe('sidebarItemRenderLogic', () => {
20
+ it('renders pure folder at depth 2 when maxDepth is 3 (0027 child)', () => {
21
+ expect(getSidebarItemRenderMode(giscusFolderAtDepth2, 2, 3)).toBe(
22
+ 'pure-folder',
23
+ )
24
+ })
25
+
26
+ it('legacy cutoff depth < maxDepth - 1 would hide depth-2 folders', () => {
27
+ const legacyAllowsGroup = 2 < 3 - 1
28
+ expect(legacyAllowsGroup).toBe(false)
29
+ })
30
+
31
+ it('parent note at depth 1 still renders as group', () => {
32
+ const emojiNote: SidebarRenderItem = {
33
+ text: '✅ emoji 规范',
34
+ link: '/notes/0027. emoji 规范/README',
35
+ items: [giscusFolderAtDepth2],
36
+ }
37
+ expect(getSidebarItemRenderMode(emojiNote, 1, 3)).toBe('parent-note')
38
+ })
39
+
40
+ it('leaf note at depth 3 renders when maxDepth is 3', () => {
41
+ const leaf: SidebarRenderItem = {
42
+ text: '⏰ 0003',
43
+ link: '/notes/0003. x/README',
44
+ }
45
+ expect(getSidebarItemRenderMode(leaf, 3, 3)).toBe('leaf')
46
+ })
47
+
48
+ it('renders depth-2 pure folder when maxDepth is 0 (unlimited)', () => {
49
+ expect(getSidebarItemRenderMode(giscusFolderAtDepth2, 2, 0)).toBe(
50
+ 'pure-folder',
51
+ )
52
+ })
53
+ })
@@ -0,0 +1,50 @@
1
+ /**
2
+ * vitepress/components/Layout/sidebarItemRenderLogic.ts
3
+ *
4
+ * 侧边栏项渲染模式:决定 folder / parent-note / leaf / hidden
5
+ */
6
+
7
+ export interface SidebarRenderItem {
8
+ text: string
9
+ link?: string
10
+ items?: SidebarRenderItem[]
11
+ }
12
+
13
+ export type SidebarItemRenderMode =
14
+ | 'pure-folder'
15
+ | 'parent-note'
16
+ | 'leaf'
17
+ | 'hidden'
18
+
19
+ export function hasSidebarChildren(item: SidebarRenderItem): boolean {
20
+ return !!(item.items && item.items.length > 0)
21
+ }
22
+
23
+ export function isPureSidebarFolder(item: SidebarRenderItem): boolean {
24
+ return hasSidebarChildren(item) && !item.link
25
+ }
26
+
27
+ /**
28
+ * @param maxDepth 最大可见层级(0 或负数表示不限制)
29
+ */
30
+ export function getSidebarItemRenderMode(
31
+ item: SidebarRenderItem,
32
+ depth: number,
33
+ maxDepth: number,
34
+ ): SidebarItemRenderMode {
35
+ const hasDepthLimit = maxDepth > 0 && Number.isFinite(maxDepth)
36
+
37
+ if (isPureSidebarFolder(item) && (!hasDepthLimit || depth < maxDepth)) {
38
+ return 'pure-folder'
39
+ }
40
+
41
+ if (hasSidebarChildren(item) && (!hasDepthLimit || depth < maxDepth)) {
42
+ return 'parent-note'
43
+ }
44
+
45
+ if (!hasSidebarChildren(item) && item.link) {
46
+ return 'leaf'
47
+ }
48
+
49
+ return 'hidden'
50
+ }
@@ -8,6 +8,7 @@ import { Transformer } from 'markmap-lib'
8
8
  import { Toolbar } from 'markmap-toolbar'
9
9
  import 'markmap-toolbar/dist/style.css'
10
10
  import { Markmap, IMarkmapOptions } from 'markmap-view'
11
+ import { onContentUpdated } from 'vitepress'
11
12
  import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
12
13
 
13
14
  import { icon__fullscreen, icon__fullscreen_exit, icon__confirm } from '../../assets/icons'
@@ -30,6 +31,10 @@ const containerRef = ref<HTMLDivElement | null>(null)
30
31
  let markmapInstance: Markmap | null = null
31
32
  let observer: MutationObserver | null = null
32
33
  let toolbarEl: HTMLElement | null = null
34
+ let toolbarReinitTimer: ReturnType<typeof setTimeout> | null = null
35
+ let darkClassObserver: MutationObserver | null = null
36
+
37
+ const isMarkmapDark = ref(false)
33
38
 
34
39
  // 从 localStorage 读取配置,如果没有则使用 props 或默认值
35
40
  const getInitialExpandLevel = () => {
@@ -42,6 +47,9 @@ const getInitialExpandLevel = () => {
42
47
 
43
48
  const getThemeColorFn = () => {
44
49
  if (typeof window !== 'undefined') {
50
+ if (document.documentElement.classList.contains('markmap-dark')) {
51
+ return scaleOrdinal(schemeSet3)
52
+ }
45
53
  const theme = localStorage.getItem(MARKMAP_THEME_KEY) || 'default'
46
54
  switch (theme) {
47
55
  case 'colorful':
@@ -131,6 +139,7 @@ function initToolbar() {
131
139
  toolbarEl.style.position = 'absolute'
132
140
  toolbarEl.style.top = '1rem'
133
141
  toolbarEl.style.right = '.5rem'
142
+ toolbarEl.style.zIndex = '10'
134
143
  toolbarEl.style.scale = '.8'
135
144
  const brand = toolbarEl.querySelector('.mm-toolbar-brand')
136
145
  if (brand) toolbarEl.removeChild(brand)
@@ -367,7 +376,43 @@ function onUpdateClick() {
367
376
  renderMarkmap(decodeURIComponent(props.content || ''), expandLevel.value)
368
377
  }
369
378
 
379
+ function syncMarkmapDarkState(reRender = false) {
380
+ const dark = document.documentElement.classList.contains('markmap-dark')
381
+ const changed = isMarkmapDark.value !== dark
382
+ isMarkmapDark.value = dark
383
+ if (typeof window !== 'undefined') {
384
+ localStorage.setItem(MARKMAP_THEME_KEY, dark ? 'dark' : 'default')
385
+ }
386
+ if (reRender && changed && markmapInstance && props.content) {
387
+ renderMarkmap(decodeURIComponent(props.content || ''), expandLevel.value)
388
+ }
389
+ }
390
+
391
+ function ensureToolbarAfterContentUpdate() {
392
+ if (toolbarReinitTimer) clearTimeout(toolbarReinitTimer)
393
+ // ContentCollapse.onContentUpdated 会在 ~150ms 后重组 DOM,稍晚再补挂工具栏
394
+ toolbarReinitTimer = setTimeout(() => {
395
+ toolbarReinitTimer = null
396
+ if (!containerRef.value || !markmapInstance) return
397
+ if (!containerRef.value.querySelector('.mm-toolbar')) {
398
+ initToolbar()
399
+ }
400
+ }, 350)
401
+ }
402
+
370
403
  onMounted(() => {
404
+ if (typeof window !== 'undefined') {
405
+ if (localStorage.getItem(MARKMAP_THEME_KEY) === 'dark') {
406
+ document.documentElement.classList.add('markmap-dark')
407
+ }
408
+ syncMarkmapDarkState(false)
409
+ darkClassObserver = new MutationObserver(() => syncMarkmapDarkState(true))
410
+ darkClassObserver.observe(document.documentElement, {
411
+ attributes: true,
412
+ attributeFilter: ['class'],
413
+ })
414
+ }
415
+
371
416
  renderMarkmap(decodeURIComponent(props.content || ''))
372
417
 
373
418
  // 添加全屏事件监听
@@ -376,7 +421,24 @@ onMounted(() => {
376
421
  document.addEventListener('MSFullscreenChange', handleFullscreenChange)
377
422
  })
378
423
 
424
+ onContentUpdated(() => {
425
+ ensureToolbarAfterContentUpdate()
426
+ })
427
+
379
428
  onBeforeUnmount(() => {
429
+ if (darkClassObserver) {
430
+ darkClassObserver.disconnect()
431
+ darkClassObserver = null
432
+ }
433
+ if (toolbarReinitTimer) {
434
+ clearTimeout(toolbarReinitTimer)
435
+ toolbarReinitTimer = null
436
+ }
437
+ if (toolbarEl) {
438
+ toolbarEl.remove()
439
+ toolbarEl = null
440
+ toolbarLevelInput = null
441
+ }
380
442
  if (markmapInstance) {
381
443
  try {
382
444
  markmapInstance.destroy()
@@ -398,6 +460,7 @@ onBeforeUnmount(() => {
398
460
  <template>
399
461
  <div
400
462
  class="markmapContainer"
463
+ :class="{ 'is-markmap-dark': isMarkmapDark }"
401
464
  ref="containerRef"
402
465
  style="position: relative"
403
466
  >
@@ -434,16 +497,10 @@ onBeforeUnmount(() => {
434
497
  animation: pulse 1.5s ease-in-out infinite;
435
498
  }
436
499
  }
437
-
438
- /* 鼠标悬停显示 toolbar */
439
- &:hover :global(.mm-toolbar) {
440
- opacity: 1;
441
- pointer-events: auto;
442
- }
443
500
  }
444
501
 
445
502
  /* dark background */
446
- :global(.markmap-dark) .markmapContainer {
503
+ .markmapContainer.is-markmap-dark {
447
504
  background-color: #1d1d1d;
448
505
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
449
506
 
@@ -534,9 +591,9 @@ onBeforeUnmount(() => {
534
591
  box-shadow: none;
535
592
  }
536
593
 
537
- :global(.markmap-dark) .markmapContainer:fullscreen,
538
- :global(.markmap-dark) .markmapContainer:-ms-fullscreen,
539
- :global(.markmap-dark) .markmapContainer:-webkit-full-screen {
594
+ .markmapContainer.is-markmap-dark:fullscreen,
595
+ .markmapContainer.is-markmap-dark:-ms-fullscreen,
596
+ .markmapContainer.is-markmap-dark:-webkit-full-screen {
540
597
  background: #1d1d1d;
541
598
  }
542
599
 
@@ -47,7 +47,7 @@ vitepress/components/Settings/Settings.vue
47
47
  <span class="infoWrap">
48
48
  <span class="infoIcon">?</span>
49
49
  <span class="tooltip">
50
- 控制侧边栏笔记编号显示,以及目录行距密度。保存后会刷新页面以应用侧边栏配置。
50
+ 控制侧边栏笔记编号显示,以及已完成/未完成笔记前缀。保存后会刷新页面以应用侧边栏配置。
51
51
  </span>
52
52
  </span>
53
53
  </div>
@@ -64,28 +64,6 @@ vitepress/components/Settings/Settings.vue
64
64
  <span>显示笔记编号</span>
65
65
  </label>
66
66
 
67
- <div class="controlRow">
68
- <span class="controlLabel">目录风格</span>
69
- <div class="segmented">
70
- <label
71
- v-for="option in sidebarDensityOptions"
72
- :key="option.value"
73
- :class="[
74
- 'segment',
75
- { activeSegment: sidebarDensity === option.value },
76
- ]"
77
- >
78
- <input
79
- v-model="sidebarDensity"
80
- type="radio"
81
- name="sidebar-density"
82
- :value="option.value"
83
- />
84
- <span>{{ option.label }}</span>
85
- </label>
86
- </div>
87
- </div>
88
-
89
67
  <div class="prefixGrid">
90
68
  <label class="field">
91
69
  <span class="controlLabel">已完成笔记的前缀</span>
@@ -113,26 +91,58 @@ vitepress/components/Settings/Settings.vue
113
91
  <div class="settingItem">
114
92
  <div class="settingMeta">
115
93
  <div class="labelLine">
116
- <span class="itemName">MarkMap 思维导图</span>
94
+ <span class="itemName">正文区域</span>
117
95
  <span class="infoWrap">
118
96
  <span class="infoIcon">?</span>
119
97
  <span class="tooltip">
120
- 配置 MarkMap 的默认分支配色和初始展开层级。
98
+ 控制笔记正文在中间栏的显示宽度。保存后会刷新页面以应用页宽变更。
121
99
  </span>
122
100
  </span>
123
101
  </div>
102
+ <span class="statusText">{{
103
+ contentWidthMode === 'wide' ? '超宽显示' : '标准页宽'
104
+ }}</span>
124
105
  </div>
125
106
 
126
- <div class="inlineGrid">
127
- <label class="field">
128
- <span class="controlLabel">分支主题</span>
129
- <select v-model="markmapTheme" class="select">
130
- <option value="default">默认</option>
131
- <option value="colorful">多彩</option>
132
- <option value="dark">深色</option>
133
- </select>
134
- </label>
107
+ <div class="fieldStack">
108
+ <div class="controlRow">
109
+ <span class="controlLabel">页宽模式</span>
110
+ <div class="segmented segmented-two">
111
+ <label
112
+ v-for="option in contentWidthModeOptions"
113
+ :key="option.value"
114
+ :class="[
115
+ 'segment',
116
+ { activeSegment: contentWidthMode === option.value },
117
+ ]"
118
+ >
119
+ <input
120
+ v-model="contentWidthMode"
121
+ type="radio"
122
+ name="content-width-mode"
123
+ :value="option.value"
124
+ />
125
+ <span>{{ option.label }}</span>
126
+ </label>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
135
131
 
132
+ <div class="settingItem">
133
+ <div class="settingMeta">
134
+ <div class="labelLine">
135
+ <span class="itemName">笔记内 MarkMap</span>
136
+ <span class="infoWrap">
137
+ <span class="infoIcon">?</span>
138
+ <span class="tooltip">
139
+ 配置笔记中 markmap 代码块的初始展开层级。
140
+ </span>
141
+ </span>
142
+ </div>
143
+ </div>
144
+
145
+ <div class="inlineGrid">
136
146
  <label class="field">
137
147
  <span class="controlLabel">展开层级</span>
138
148
  <div class="inputWithUnit">
@@ -175,55 +185,53 @@ import { ref, computed, onMounted } from 'vue'
175
185
 
176
186
  import {
177
187
  NOTES_DIR_KEY,
178
- MARKMAP_THEME_KEY,
179
188
  MARKMAP_EXPAND_LEVEL_KEY,
180
189
  SIDEBAR_SHOW_NOTE_ID_KEY,
181
- SIDEBAR_DENSITY_KEY,
182
190
  SIDEBAR_DONE_PREFIX_KEY,
183
191
  SIDEBAR_UNDONE_PREFIX_KEY,
192
+ CONTENT_WIDTH_MODE_KEY,
184
193
  } from '../constants'
185
194
  // @ts-expect-error - VitePress Data Loader
186
195
  import { data as tnotesConfig } from '../tnotes-config.data'
187
196
 
188
- type SidebarDensity = 'compact' | 'default' | 'loose'
197
+ type ContentWidthMode = 'wide' | 'standard'
189
198
 
190
- const DEFAULT_SIDEBAR_DENSITY: SidebarDensity = 'default'
199
+ const DEFAULT_CONTENT_WIDTH_MODE: ContentWidthMode = 'wide'
191
200
  const DEFAULT_DONE_PREFIX = '✅'
192
201
  const DEFAULT_UNDONE_PREFIX = '⏰'
193
- const sidebarDensityOptions: Array<{
202
+
203
+ const contentWidthModeOptions: Array<{
194
204
  label: string
195
- value: SidebarDensity
205
+ value: ContentWidthMode
196
206
  }> = [
197
- { label: '紧凑', value: 'compact' },
198
- { label: '默认', value: 'default' },
199
- { label: '宽松', value: 'loose' },
207
+ { label: '超宽显示', value: 'wide' },
208
+ { label: '标准页宽', value: 'standard' },
200
209
  ]
201
210
 
202
211
  const path = ref('')
203
212
  const originalPath = ref('')
204
- const markmapTheme = ref('default')
205
- const originalMarkmapTheme = ref('default')
206
213
  const markmapExpandLevel = ref(5)
207
214
  const originalMarkmapExpandLevel = ref(5)
208
215
  const showNoteId = ref(false)
209
216
  const originalShowNoteId = ref(false)
210
- const sidebarDensity = ref<SidebarDensity>(DEFAULT_SIDEBAR_DENSITY)
211
- const originalSidebarDensity = ref<SidebarDensity>(DEFAULT_SIDEBAR_DENSITY)
212
217
  const donePrefix = ref(DEFAULT_DONE_PREFIX)
213
218
  const originalDonePrefix = ref(DEFAULT_DONE_PREFIX)
214
219
  const undonePrefix = ref(DEFAULT_UNDONE_PREFIX)
215
220
  const originalUndonePrefix = ref(DEFAULT_UNDONE_PREFIX)
221
+ const contentWidthMode = ref<ContentWidthMode>(DEFAULT_CONTENT_WIDTH_MODE)
222
+ const originalContentWidthMode = ref<ContentWidthMode>(
223
+ DEFAULT_CONTENT_WIDTH_MODE,
224
+ )
216
225
  const showSuccessToast = ref(false)
217
226
 
218
227
  const hasChanges = computed(
219
228
  () =>
220
229
  path.value !== originalPath.value ||
221
- markmapTheme.value !== originalMarkmapTheme.value ||
222
230
  markmapExpandLevel.value !== originalMarkmapExpandLevel.value ||
223
231
  showNoteId.value !== originalShowNoteId.value ||
224
- sidebarDensity.value !== originalSidebarDensity.value ||
225
232
  donePrefix.value !== originalDonePrefix.value ||
226
- undonePrefix.value !== originalUndonePrefix.value,
233
+ undonePrefix.value !== originalUndonePrefix.value ||
234
+ contentWidthMode.value !== originalContentWidthMode.value,
227
235
  )
228
236
 
229
237
  const saveText = computed(() => {
@@ -238,10 +246,6 @@ onMounted(() => {
238
246
  path.value = savedPath
239
247
  originalPath.value = savedPath
240
248
 
241
- const savedTheme = localStorage.getItem(MARKMAP_THEME_KEY) || 'default'
242
- markmapTheme.value = savedTheme
243
- originalMarkmapTheme.value = savedTheme
244
-
245
249
  const savedLevel = localStorage.getItem(MARKMAP_EXPAND_LEVEL_KEY) || '5'
246
250
  markmapExpandLevel.value = parseInt(savedLevel, 10)
247
251
  originalMarkmapExpandLevel.value = markmapExpandLevel.value
@@ -253,12 +257,6 @@ onMounted(() => {
253
257
  : tnotesConfig?.sidebarShowNoteId ?? false
254
258
  originalShowNoteId.value = showNoteId.value
255
259
 
256
- const savedSidebarDensity = normalizeSidebarDensity(
257
- localStorage.getItem(SIDEBAR_DENSITY_KEY),
258
- )
259
- sidebarDensity.value = savedSidebarDensity
260
- originalSidebarDensity.value = savedSidebarDensity
261
-
262
260
  const savedDonePrefix = localStorage.getItem(SIDEBAR_DONE_PREFIX_KEY)
263
261
  donePrefix.value =
264
262
  savedDonePrefix !== null ? savedDonePrefix : DEFAULT_DONE_PREFIX
@@ -268,14 +266,16 @@ onMounted(() => {
268
266
  undonePrefix.value =
269
267
  savedUndonePrefix !== null ? savedUndonePrefix : DEFAULT_UNDONE_PREFIX
270
268
  originalUndonePrefix.value = undonePrefix.value
271
- })
272
269
 
273
- function normalizeSidebarDensity(value: string | null): SidebarDensity {
274
- if (value === 'compact' || value === 'default' || value === 'loose') {
275
- return value
276
- }
270
+ const savedContentWidthMode = normalizeContentWidthMode(
271
+ localStorage.getItem(CONTENT_WIDTH_MODE_KEY),
272
+ )
273
+ contentWidthMode.value = savedContentWidthMode
274
+ originalContentWidthMode.value = savedContentWidthMode
275
+ })
277
276
 
278
- return DEFAULT_SIDEBAR_DENSITY
277
+ function normalizeContentWidthMode(value: string | null): ContentWidthMode {
278
+ return value === 'standard' ? 'standard' : 'wide'
279
279
  }
280
280
 
281
281
  function clearPath() {
@@ -288,28 +288,26 @@ function save() {
288
288
  try {
289
289
  const needReload =
290
290
  showNoteId.value !== originalShowNoteId.value ||
291
- sidebarDensity.value !== originalSidebarDensity.value ||
292
291
  donePrefix.value !== originalDonePrefix.value ||
293
- undonePrefix.value !== originalUndonePrefix.value
292
+ undonePrefix.value !== originalUndonePrefix.value ||
293
+ contentWidthMode.value !== originalContentWidthMode.value
294
294
 
295
295
  localStorage.setItem(NOTES_DIR_KEY, path.value)
296
- localStorage.setItem(MARKMAP_THEME_KEY, markmapTheme.value)
297
296
  localStorage.setItem(
298
297
  MARKMAP_EXPAND_LEVEL_KEY,
299
298
  markmapExpandLevel.value.toString(),
300
299
  )
301
300
  localStorage.setItem(SIDEBAR_SHOW_NOTE_ID_KEY, showNoteId.value.toString())
302
- localStorage.setItem(SIDEBAR_DENSITY_KEY, sidebarDensity.value)
303
301
  localStorage.setItem(SIDEBAR_DONE_PREFIX_KEY, donePrefix.value)
304
302
  localStorage.setItem(SIDEBAR_UNDONE_PREFIX_KEY, undonePrefix.value)
303
+ localStorage.setItem(CONTENT_WIDTH_MODE_KEY, contentWidthMode.value)
305
304
 
306
305
  originalPath.value = path.value
307
- originalMarkmapTheme.value = markmapTheme.value
308
306
  originalMarkmapExpandLevel.value = markmapExpandLevel.value
309
307
  originalShowNoteId.value = showNoteId.value
310
- originalSidebarDensity.value = sidebarDensity.value
311
308
  originalDonePrefix.value = donePrefix.value
312
309
  originalUndonePrefix.value = undonePrefix.value
310
+ originalContentWidthMode.value = contentWidthMode.value
313
311
 
314
312
  showSuccessToast.value = true
315
313
  setTimeout(() => {
@@ -329,12 +327,11 @@ function save() {
329
327
 
330
328
  function reset() {
331
329
  path.value = originalPath.value
332
- markmapTheme.value = originalMarkmapTheme.value
333
330
  markmapExpandLevel.value = originalMarkmapExpandLevel.value
334
331
  showNoteId.value = originalShowNoteId.value
335
- sidebarDensity.value = originalSidebarDensity.value
336
332
  donePrefix.value = originalDonePrefix.value
337
333
  undonePrefix.value = originalUndonePrefix.value
334
+ contentWidthMode.value = originalContentWidthMode.value
338
335
  }
339
336
  </script>
340
337
 
@@ -431,6 +428,8 @@ function reset() {
431
428
 
432
429
  .inputGroup {
433
430
  position: relative;
431
+ align-self: start;
432
+ width: 100%;
434
433
  }
435
434
 
436
435
  .input,
@@ -475,6 +474,7 @@ function reset() {
475
474
  width: 20px;
476
475
  height: 20px;
477
476
  padding: 0;
477
+ line-height: 1;
478
478
  color: var(--vp-c-text-3);
479
479
  background: transparent;
480
480
  border: none;
@@ -536,6 +536,10 @@ function reset() {
536
536
  border-radius: 6px;
537
537
  }
538
538
 
539
+ .segmented-two {
540
+ grid-template-columns: repeat(2, 1fr);
541
+ }
542
+
539
543
  .segment {
540
544
  display: inline-flex;
541
545
  align-items: center;