clarity-theme 0.1.0 → 0.1.1

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 (119) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +18 -4
  3. package/README.zh-CN.md +18 -4
  4. package/app/app.config.ts +110 -110
  5. package/app/app.vue +5 -5
  6. package/app/components/blog/BlogAside.vue +25 -25
  7. package/app/components/blog/BlogFooter.vue +25 -25
  8. package/app/components/blog/BlogHeader.global.vue +48 -48
  9. package/app/components/blog/BlogPanel.vue +43 -43
  10. package/app/components/blog/BlogSidebar.vue +53 -53
  11. package/app/components/blog/BlogWidget.vue +42 -42
  12. package/app/components/blog/Mask.vue +25 -25
  13. package/app/components/blog/SkipToContent.vue +9 -9
  14. package/app/components/blog/ThemeToggle.vue +22 -22
  15. package/app/components/content/Badge.vue +45 -45
  16. package/app/components/content/Blur.vue +14 -14
  17. package/app/components/content/CardList.vue +8 -8
  18. package/app/components/content/Chat.vue +41 -41
  19. package/app/components/content/Copy.vue +71 -71
  20. package/app/components/content/EmojiClock.vue +49 -49
  21. package/app/components/content/FeedCard.vue +96 -96
  22. package/app/components/content/FeedGroup.vue +61 -61
  23. package/app/components/content/Folding.vue +19 -19
  24. package/app/components/content/Key.vue +143 -143
  25. package/app/components/content/LinkBanner.vue +27 -27
  26. package/app/components/content/LinkCard.vue +28 -28
  27. package/app/components/content/MdTitle.vue +8 -8
  28. package/app/components/content/Mermaid.vue +99 -99
  29. package/app/components/content/MusicScore.vue +63 -63
  30. package/app/components/content/Pic.vue +49 -49
  31. package/app/components/content/Poetry.vue +27 -27
  32. package/app/components/content/ProseA.vue +24 -24
  33. package/app/components/content/ProseCode.vue +16 -16
  34. package/app/components/content/ProsePre.vue +117 -117
  35. package/app/components/content/ProseTable.vue +23 -23
  36. package/app/components/content/Quote.vue +21 -21
  37. package/app/components/content/Tab.vue +32 -32
  38. package/app/components/content/Timeline.vue +33 -33
  39. package/app/components/content/Tip.vue +40 -40
  40. package/app/components/content/VideoEmbed.vue +112 -112
  41. package/app/components/partial/Button.vue +36 -36
  42. package/app/components/partial/DlGroup.vue +31 -31
  43. package/app/components/partial/Dropdown.vue +21 -21
  44. package/app/components/partial/Error.vue +39 -39
  45. package/app/components/partial/Expand.vue +26 -26
  46. package/app/components/partial/IconNavList.vue +24 -24
  47. package/app/components/partial/Pagination.vue +62 -62
  48. package/app/components/partial/RadioGroup.vue +30 -30
  49. package/app/components/partial/Secret.vue +11 -11
  50. package/app/components/partial/Slider.vue +48 -48
  51. package/app/components/partial/Toggle.vue +17 -17
  52. package/app/components/popover/Lightbox.vue +44 -44
  53. package/app/components/popover/Search.vue +143 -143
  54. package/app/components/popover/SearchItem.vue +28 -28
  55. package/app/components/post/Archive.vue +40 -40
  56. package/app/components/post/Article.vue +49 -49
  57. package/app/components/post/Comment.vue +119 -119
  58. package/app/components/post/Excerpt.vue +40 -40
  59. package/app/components/post/OrderToggle.vue +70 -70
  60. package/app/components/post/PostFooter.vue +52 -52
  61. package/app/components/post/PostHeader.vue +66 -66
  62. package/app/components/post/PostSurround.vue +51 -51
  63. package/app/components/post/Slide.vue +85 -85
  64. package/app/components/util/Date.vue +62 -62
  65. package/app/components/util/HydrateSafe.vue +10 -10
  66. package/app/components/util/Img.vue +38 -38
  67. package/app/components/util/Link.vue +11 -11
  68. package/app/components/widget/BlogLog.vue +23 -23
  69. package/app/components/widget/BlogStats.vue +38 -38
  70. package/app/components/widget/BlogTech.vue +57 -57
  71. package/app/components/widget/Empty.vue +3 -3
  72. package/app/components/widget/Toc.vue +67 -67
  73. package/app/composables/useArticle.ts +113 -113
  74. package/app/composables/useAvoid.ts +87 -87
  75. package/app/composables/useCopy.ts +21 -21
  76. package/app/composables/usePagination.ts +70 -70
  77. package/app/composables/useShiki.ts +129 -129
  78. package/app/composables/useToc.ts +57 -57
  79. package/app/composables/useWidgets.ts +56 -56
  80. package/app/error.vue +31 -31
  81. package/app/layouts/default.vue +25 -25
  82. package/app/pages/[...slug].vue +59 -59
  83. package/app/pages/archive.vue +129 -129
  84. package/app/pages/index.vue +76 -76
  85. package/app/pages/link.vue +62 -62
  86. package/app/pages/preview.vue +46 -46
  87. package/app/plugins/easter-egg.ts +23 -23
  88. package/app/plugins/init.ts +6 -6
  89. package/app/plugins/tippy.ts +22 -22
  90. package/app/shiki.config.ts +8 -8
  91. package/app/stores/layout.ts +34 -34
  92. package/app/stores/search.ts +37 -37
  93. package/app/types/article.ts +16 -16
  94. package/app/types/index.ts +14 -14
  95. package/app/types/nav.ts +11 -11
  96. package/app/utils/anim.ts +37 -37
  97. package/app/utils/img.ts +83 -83
  98. package/config/app.ts +61 -61
  99. package/config/content.ts +75 -75
  100. package/config/define.ts +3 -3
  101. package/config/feeds.empty.ts +6 -4
  102. package/config/public.ts +1 -1
  103. package/config/schema.ts +89 -89
  104. package/config/server.ts +1 -1
  105. package/modules/clarity-config/index.ts +162 -159
  106. package/nuxt.config.ts +212 -212
  107. package/package.json +25 -21
  108. package/public/assets/atom.css +274 -274
  109. package/public/assets/atom.xsl +109 -109
  110. package/remark-plugins/rehype-meta-slots.ts +58 -58
  111. package/remark-plugins/remark-code-component.ts +41 -41
  112. package/server/api/stats.get.ts +84 -83
  113. package/server/routes/atom.xml.get.ts +85 -85
  114. package/server/routes/subscriptions.opml.get.ts +64 -64
  115. package/shared/utils/clarity.ts +24 -24
  116. package/shared/utils/icon.ts +218 -218
  117. package/shared/utils/link.ts +52 -52
  118. package/shared/utils/str.ts +88 -88
  119. package/shared/utils/time.ts +115 -115
@@ -1,21 +1,21 @@
1
- <script setup lang="ts">
2
- defineProps<{
3
- title?: string
4
- }>()
5
- </script>
6
-
7
- <template>
8
- <details>
9
- <summary>
10
- <slot name="title">
11
- {{ title }}
12
- </slot>
13
- </summary>
14
- <slot />
15
- </details>
16
- </template>
17
-
18
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ title?: string
4
+ }>()
5
+ </script>
6
+
7
+ <template>
8
+ <details>
9
+ <summary>
10
+ <slot name="title">
11
+ {{ title }}
12
+ </slot>
13
+ </summary>
14
+ <slot />
15
+ </details>
16
+ </template>
17
+
18
+ <style lang="scss" scoped>
19
19
  details {
20
20
  margin: 1em 0;
21
21
  padding: 0.5em 0.8em;
@@ -66,4 +66,4 @@ details {
66
66
  margin: 0 -0.8em -0.5em;
67
67
  }
68
68
  }
69
- </style>
69
+ </style>
@@ -1,145 +1,145 @@
1
- <script setup lang="ts">
2
- import { useEventListener } from '@vueuse/core'
3
- import { computed, ref } from 'vue'
4
-
5
- const props = withDefaults(defineProps<{
6
- text?: string
7
- /** https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/key */
8
- code?: string
9
- /** 仅 macOS 默认显示图标 */
10
- icon?: boolean
11
- ctrl?: boolean
12
- shift?: boolean
13
- alt?: boolean
14
- meta?: boolean
15
- win?: boolean
16
- /** 智能适配:Windows用Ctrl,macOS用Cmd */
17
- cmd?: boolean
18
- prevent?: boolean
19
- }>(), {
20
- icon: undefined,
21
- })
22
-
23
- const emit = defineEmits<{
24
- press: []
25
- }>()
26
-
27
- const mounted = useMounted()
28
- const isMac = computed(() => mounted.value && /mac ?os/i.test(navigator?.userAgent))
29
- const useSymbol = computed(() => isMac.value ? props.icon !== false : props.icon)
30
- const keyJoiner = computed(() => useSymbol.value ? '' : '+')
31
-
32
- // @keep-sorted
33
- const displayMap = {
34
- ' ': 'Space',
35
- 'ArrowDown': '↓',
36
- 'ArrowLeft': '←',
37
- 'ArrowRight': '→',
38
- 'ArrowUp': '↑',
39
- 'Control': 'Ctrl',
40
- 'Delete': 'Del',
41
- 'Escape': 'Esc',
42
- get 'Meta'() { return isMac.value ? 'Cmd' : 'Win' },
43
- }
44
-
45
- // @keep-sorted
46
- const symbolMap = {
47
- ' ': '␣',
48
- 'Alt': '⌥',
49
- 'Backspace': '⌫',
50
- 'Control': '⌃',
51
- 'Delete': '⌦',
52
- 'Enter': '↵',
53
- 'Escape': '⎋',
54
- get 'Meta'() { return isMac.value ? '⌘' : '⊞' },
55
- 'Shift': '⇧',
56
- 'Tab': '⇥',
57
- 'Win': '⊞',
58
- }
59
-
60
- function normalizeCodeDisplay(code?: string) {
61
- if (!code)
62
- return ''
63
- if (useSymbol.value && code in symbolMap)
64
- return symbolMap[code as keyof typeof symbolMap]
65
- if (code in displayMap)
66
- return displayMap[code as keyof typeof displayMap]
67
- return code
68
- }
69
-
70
- const codeDisplay = computed(() => {
71
- if (props.text)
72
- return props.text
73
-
74
- const keyConfigs = [
75
- { condition: props.cmd, code: isMac.value ? 'Meta' : 'Control' },
76
- { condition: props.ctrl && !props.cmd, code: 'Control' },
77
- { condition: props.shift, code: 'Shift' },
78
- { condition: props.alt, code: 'Alt' },
79
- { condition: props.meta && !props.cmd, code: 'Meta' },
80
- { condition: props.win && !props.meta, code: 'Win' },
81
- { condition: props.code, code: props.code },
82
- ]
83
-
84
- return keyConfigs
85
- .filter(config => config.condition)
86
- .map(config => normalizeCodeDisplay(config.code))
87
- .join(keyJoiner.value)
88
- })
89
-
90
- const active = ref(false)
91
-
92
- const ctrlState = useKeyModifier('Control')
93
- const shiftState = useKeyModifier('Shift')
94
- const altState = useKeyModifier('Alt')
95
- const metaState = useKeyModifier('Meta')
96
-
97
- /** 检查当前修饰键状态是否匹配 props */
98
- function modifiersMatch() {
99
- const cmdMatch = props.cmd
100
- ? (isMac.value ? metaState.value : ctrlState.value)
101
- : true
102
-
103
- return cmdMatch
104
- && (!props.ctrl || (!props.cmd && ctrlState.value))
105
- && (!props.shift || shiftState.value)
106
- && (!props.alt || altState.value)
107
- && (!props.meta || (!props.cmd && metaState.value))
108
- }
109
-
110
- function matchKeyEvent(e: KeyboardEvent, expectedCode?: string) {
111
- if (expectedCode && e.key?.toLowerCase() !== expectedCode.toLowerCase())
112
- return false
113
- return modifiersMatch()
114
- }
115
-
116
- useEventListener('keydown', (e) => {
117
- if (matchKeyEvent(e, props.code)) {
118
- emit('press')
119
- active.value = true
120
- props.prevent && e.preventDefault()
121
- }
122
- })
123
-
124
- useEventListener('keyup', (e) => {
125
- if (matchKeyEvent(e, props.code) || !modifiersMatch())
126
- active.value = false
127
- })
128
-
129
- useEventListener('blur', () => {
130
- active.value = false
131
- })
132
- </script>
133
-
134
- <template>
135
- <UtilHydrateSafe>
136
- <kbd :class="{ active }" @click.stop="emit('press')">
137
- <slot>{{ codeDisplay }}</slot>
138
- </kbd>
139
- </UtilHydrateSafe>
140
- </template>
141
-
142
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ import { useEventListener } from '@vueuse/core'
3
+ import { computed, ref } from 'vue'
4
+
5
+ const props = withDefaults(defineProps<{
6
+ text?: string
7
+ /** https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/key */
8
+ code?: string
9
+ /** 仅 macOS 默认显示图标 */
10
+ icon?: boolean
11
+ ctrl?: boolean
12
+ shift?: boolean
13
+ alt?: boolean
14
+ meta?: boolean
15
+ win?: boolean
16
+ /** 智能适配:Windows用Ctrl,macOS用Cmd */
17
+ cmd?: boolean
18
+ prevent?: boolean
19
+ }>(), {
20
+ icon: undefined,
21
+ })
22
+
23
+ const emit = defineEmits<{
24
+ press: []
25
+ }>()
26
+
27
+ const mounted = useMounted()
28
+ const isMac = computed(() => mounted.value && /mac ?os/i.test(navigator?.userAgent))
29
+ const useSymbol = computed(() => isMac.value ? props.icon !== false : props.icon)
30
+ const keyJoiner = computed(() => useSymbol.value ? '' : '+')
31
+
32
+ // @keep-sorted
33
+ const displayMap = {
34
+ ' ': 'Space',
35
+ 'ArrowDown': '↓',
36
+ 'ArrowLeft': '←',
37
+ 'ArrowRight': '→',
38
+ 'ArrowUp': '↑',
39
+ 'Control': 'Ctrl',
40
+ 'Delete': 'Del',
41
+ 'Escape': 'Esc',
42
+ get 'Meta'() { return isMac.value ? 'Cmd' : 'Win' },
43
+ }
44
+
45
+ // @keep-sorted
46
+ const symbolMap = {
47
+ ' ': '␣',
48
+ 'Alt': '⌥',
49
+ 'Backspace': '⌫',
50
+ 'Control': '⌃',
51
+ 'Delete': '⌦',
52
+ 'Enter': '↵',
53
+ 'Escape': '⎋',
54
+ get 'Meta'() { return isMac.value ? '⌘' : '⊞' },
55
+ 'Shift': '⇧',
56
+ 'Tab': '⇥',
57
+ 'Win': '⊞',
58
+ }
59
+
60
+ function normalizeCodeDisplay(code?: string) {
61
+ if (!code)
62
+ return ''
63
+ if (useSymbol.value && code in symbolMap)
64
+ return symbolMap[code as keyof typeof symbolMap]
65
+ if (code in displayMap)
66
+ return displayMap[code as keyof typeof displayMap]
67
+ return code
68
+ }
69
+
70
+ const codeDisplay = computed(() => {
71
+ if (props.text)
72
+ return props.text
73
+
74
+ const keyConfigs = [
75
+ { condition: props.cmd, code: isMac.value ? 'Meta' : 'Control' },
76
+ { condition: props.ctrl && !props.cmd, code: 'Control' },
77
+ { condition: props.shift, code: 'Shift' },
78
+ { condition: props.alt, code: 'Alt' },
79
+ { condition: props.meta && !props.cmd, code: 'Meta' },
80
+ { condition: props.win && !props.meta, code: 'Win' },
81
+ { condition: props.code, code: props.code },
82
+ ]
83
+
84
+ return keyConfigs
85
+ .filter(config => config.condition)
86
+ .map(config => normalizeCodeDisplay(config.code))
87
+ .join(keyJoiner.value)
88
+ })
89
+
90
+ const active = ref(false)
91
+
92
+ const ctrlState = useKeyModifier('Control')
93
+ const shiftState = useKeyModifier('Shift')
94
+ const altState = useKeyModifier('Alt')
95
+ const metaState = useKeyModifier('Meta')
96
+
97
+ /** 检查当前修饰键状态是否匹配 props */
98
+ function modifiersMatch() {
99
+ const cmdMatch = props.cmd
100
+ ? (isMac.value ? metaState.value : ctrlState.value)
101
+ : true
102
+
103
+ return cmdMatch
104
+ && (!props.ctrl || (!props.cmd && ctrlState.value))
105
+ && (!props.shift || shiftState.value)
106
+ && (!props.alt || altState.value)
107
+ && (!props.meta || (!props.cmd && metaState.value))
108
+ }
109
+
110
+ function matchKeyEvent(e: KeyboardEvent, expectedCode?: string) {
111
+ if (expectedCode && e.key?.toLowerCase() !== expectedCode.toLowerCase())
112
+ return false
113
+ return modifiersMatch()
114
+ }
115
+
116
+ useEventListener('keydown', (e) => {
117
+ if (matchKeyEvent(e, props.code)) {
118
+ emit('press')
119
+ active.value = true
120
+ props.prevent && e.preventDefault()
121
+ }
122
+ })
123
+
124
+ useEventListener('keyup', (e) => {
125
+ if (matchKeyEvent(e, props.code) || !modifiersMatch())
126
+ active.value = false
127
+ })
128
+
129
+ useEventListener('blur', () => {
130
+ active.value = false
131
+ })
132
+ </script>
133
+
134
+ <template>
135
+ <UtilHydrateSafe>
136
+ <kbd :class="{ active }" @click.stop="emit('press')">
137
+ <slot>{{ codeDisplay }}</slot>
138
+ </kbd>
139
+ </UtilHydrateSafe>
140
+ </template>
141
+
142
+ <style lang="scss" scoped>
143
143
  kbd {
144
144
  display: inline-block;
145
145
  margin: 0.1em;
@@ -161,4 +161,4 @@ kbd {
161
161
  transform: translateY(0.05em);
162
162
  }
163
163
  }
164
- </style>
164
+ </style>
@@ -1,29 +1,29 @@
1
- <script setup lang="ts">
2
- defineProps<{
3
- banner?: string
4
- mirror?: ImgService
5
- title: string
6
- description?: string
7
- link: string
8
- }>()
9
- </script>
10
-
11
- <template>
12
- <UtilLink :to="link" class="link-banner card" :title="joinWith([title, description, link])">
13
- <UtilImg v-if="banner" class="link-banner-bg" :src="banner" :mirror />
14
- <div class="link-banner-header" />
15
- <div class="link-banner-info">
16
- <div class="link-banner-title">
17
- {{ title }}
18
- </div>
19
- <div class="link-banner-desc">
20
- {{ description ?? getDomain(link) }}
21
- </div>
22
- </div>
23
- </UtilLink>
24
- </template>
25
-
26
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ banner?: string
4
+ mirror?: ImgService
5
+ title: string
6
+ description?: string
7
+ link: string
8
+ }>()
9
+ </script>
10
+
11
+ <template>
12
+ <UtilLink :to="link" class="link-banner card" :title="joinWith([title, description, link])">
13
+ <UtilImg v-if="banner" class="link-banner-bg" :src="banner" :mirror />
14
+ <div class="link-banner-header" />
15
+ <div class="link-banner-info">
16
+ <div class="link-banner-title">
17
+ {{ title }}
18
+ </div>
19
+ <div class="link-banner-desc">
20
+ {{ description ?? getDomain(link) }}
21
+ </div>
22
+ </div>
23
+ </UtilLink>
24
+ </template>
25
+
26
+ <style lang="scss" scoped>
27
27
  .link-banner {
28
28
  line-height: 1.4;
29
29
 
@@ -56,4 +56,4 @@ defineProps<{
56
56
  color: var(--c-text-2);
57
57
  }
58
58
  }
59
- </style>
59
+ </style>
@@ -1,30 +1,30 @@
1
- <script setup lang="ts">
2
- defineProps<{
3
- link: string
4
- title: string
5
- description?: string
6
- icon?: string
7
- mirror?: ImgService
8
- }>()
9
- </script>
10
-
11
- <template>
12
- <UtilLink :to="link" class="link-card card" :title="joinWith([title, description, link])">
13
- <div class="link-card-info">
14
- <div class="link-card-title">
15
- {{ title }}
16
- </div>
17
- <div class="link-card-description">
18
- {{ description ?? getDomain(link) }}
19
- </div>
20
- </div>
21
- <slot name="icon" class="link-card-icon-slot">
22
- <UtilImg v-if="icon" class="link-card-icon" :src="icon" :mirror />
23
- </slot>
24
- </UtilLink>
25
- </template>
26
-
27
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ link: string
4
+ title: string
5
+ description?: string
6
+ icon?: string
7
+ mirror?: ImgService
8
+ }>()
9
+ </script>
10
+
11
+ <template>
12
+ <UtilLink :to="link" class="link-card card" :title="joinWith([title, description, link])">
13
+ <div class="link-card-info">
14
+ <div class="link-card-title">
15
+ {{ title }}
16
+ </div>
17
+ <div class="link-card-description">
18
+ {{ description ?? getDomain(link) }}
19
+ </div>
20
+ </div>
21
+ <slot name="icon" class="link-card-icon-slot">
22
+ <UtilImg v-if="icon" class="link-card-icon" :src="icon" :mirror />
23
+ </slot>
24
+ </UtilLink>
25
+ </template>
26
+
27
+ <style lang="scss" scoped>
28
28
  .link-card {
29
29
  display: flex;
30
30
  align-items: center;
@@ -71,4 +71,4 @@ defineProps<{
71
71
  object-fit: cover;
72
72
  }
73
73
  }
74
- </style>
74
+ </style>
@@ -1,10 +1,10 @@
1
- <template>
2
- <div class="md-title">
3
- <slot />
4
- </div>
5
- </template>
6
-
7
- <style lang="scss" scoped>
1
+ <template>
2
+ <div class="md-title">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style lang="scss" scoped>
8
8
  .md-title {
9
9
  margin: 0.5em 0;
10
10
  font-size: 1.1em;
@@ -23,4 +23,4 @@
23
23
  opacity: 0.5;
24
24
  }
25
25
  }
26
- </style>
26
+ </style>