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
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Zhilu
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Zhilu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -25,14 +25,24 @@ Clarity Theme is a reusable **Nuxt 4 Layer blog theme** extracted from [L33Z22L1
25
25
  | Nuxt peer | `^4.5.2` |
26
26
  | Vue peer | `^3.5.42` |
27
27
 
28
- The package is not currently available from the npm registry. Install it as a Git dependency pinned to a reviewed commit until the first package release is published. Clarity is part of your application runtime, so install it as a regular dependency rather than a development dependency.
28
+ Clarity is available from the npm registry as `clarity-theme`. It is part of your application runtime (the Nuxt build and static generation load the Layer directly), so install it as a regular dependency rather than a development dependency; a production install must still be able to resolve it.
29
29
 
30
30
  ## Installation
31
31
 
32
+ ```bash
33
+ pnpm add clarity-theme
34
+ ```
35
+
36
+ ### Git commit installation (development fallback)
37
+
38
+ For unreleased commits, local debugging, or reviewing a specific change before it is published, install directly from GitHub instead:
39
+
32
40
  ```bash
33
41
  pnpm add github:iicemeta/clarity-theme#<commit>
34
42
  ```
35
43
 
44
+ This path is intended for development only. Released sites should consume the published npm version so installs are reproducible and covered by the release verification matrix.
45
+
36
46
  ## Quick Start
37
47
 
38
48
  ### 1. Extend the Layer
@@ -83,7 +93,9 @@ Place articles under `content/posts/` and other Content pages under `content/`.
83
93
  // feeds.ts
84
94
  import type { FeedGroup } from 'clarity-theme/config'
85
95
 
86
- export default [] satisfies FeedGroup[]
96
+ const feeds: FeedGroup[] = []
97
+
98
+ export default feeds
87
99
  ```
88
100
 
89
101
  Without this file, the friend page and OPML output use empty data and the build logs a warning.
@@ -229,6 +241,8 @@ All documents are also available in 简体中文 as sibling `*.zh-CN.md` files.
229
241
  | [Patches](./docs/PATCHES.md) | Consumer patch ownership and current conclusions |
230
242
  | [Release audit](./docs/RELEASE-AUDIT.md) | Pre-closing engineering audit and remaining release gates |
231
243
  | [Release checklist](./docs/RELEASE-CHECKLIST.md) | Exact final checks, remaining blockers, and verification evidence |
244
+ | [Publishing](./docs/PUBLISHING.md) | Versioning, tags, GitHub Releases, OIDC publishing, provenance, and rollback policy |
245
+ | [Changelog](./CHANGELOG.md) | Consumer-facing release history |
232
246
  | [Extraction history](./docs/history/2026-09-layer-extraction.md) | Historical phases and one-time differential validation |
233
247
 
234
248
  ## Development
@@ -267,9 +281,9 @@ The weekly workflow only detects and reports drift. It never applies, commits, o
267
281
 
268
282
  ## Release Status
269
283
 
270
- Clarity Theme is a **v0.1.0 pre-publish Layer candidate**. The Layer/package boundary, validated configuration, Content factory, rendering pipeline, server outputs, playground, real-consumer acceptance, compatibility matrix, three-layer CI, and upstream-sync baseline are implemented.
284
+ Clarity Theme is a **v0.1.1 gated npm release**. The Layer/package boundary, validated configuration, Content factory, rendering pipeline, server outputs, playground, real-consumer acceptance, compatibility matrix, three-layer CI, upstream-sync baseline, release gate, and OIDC publish workflow are implemented. See the [release checklist](./docs/RELEASE-CHECKLIST.md) for the exact remaining manual publication steps.
271
285
 
272
- The first npm release is intentionally still blocked by the P0 correctness items in [Roadmap](./docs/ROADMAP.md)—especially the server/client configuration split, feature-off route semantics, anti-mirror navigation verification, and the no-op random-permalink contract—and by an exact-commit release run. Migration documentation and repeatability are being completed in this release-closing phase.
286
+ The v0.1.0 correctness gates from [Roadmap](./docs/ROADMAP.md) are resolved: server/client configuration is split, feature-off routes return 404 at runtime, anti-mirror navigation is verified in a real browser, the no-op random-permalink field is removed, and multi-pattern stats are covered by a regression test. Remaining deferred items are recorded in the roadmap and release notes.
273
287
 
274
288
  ## License
275
289
 
package/README.zh-CN.md CHANGED
@@ -25,14 +25,24 @@ Clarity Theme 是一个从 [L33Z22L11/blog-v3](https://github.com/L33Z22L11/blog
25
25
  | Nuxt peer | `^4.5.2` |
26
26
  | Vue peer | `^3.5.42` |
27
27
 
28
- 该包目前尚未发布到 npm 注册表。在第一个包版本发布之前,请以锁定到已审查 commit Git 依赖方式安装。Clarity 属于应用运行时的一部分,因此请将其安装为常规依赖(dependency),而不是开发依赖(devDependency)。
28
+ Clarity 已通过 npm 注册表以 `clarity-theme` 分发。它属于应用运行时的一部分(Nuxt 构建与静态生成会直接加载 Layer),因此请将其安装为常规依赖(dependency),而不是开发依赖(devDependency);生产环境安装也必须能解析到它。
29
29
 
30
30
  ## 安装
31
31
 
32
+ ```bash
33
+ pnpm add clarity-theme
34
+ ```
35
+
36
+ ### Git commit 安装(开发回退方式)
37
+
38
+ 如需使用未发布的 commit、本地调试,或在发布前审查某个具体变更,可以直接从 GitHub 安装:
39
+
32
40
  ```bash
33
41
  pnpm add github:iicemeta/clarity-theme#<commit>
34
42
  ```
35
43
 
44
+ 该方式仅用于开发场景。正式站点应使用已发布的 npm 版本,以保证安装可复现并被发布验证矩阵覆盖。
45
+
36
46
  ## 快速开始
37
47
 
38
48
  ### 1. 继承 Layer
@@ -83,7 +93,9 @@ export default createClarityContentConfig(clarityConfig)
83
93
  // feeds.ts
84
94
  import type { FeedGroup } from 'clarity-theme/config'
85
95
 
86
- export default [] satisfies FeedGroup[]
96
+ const feeds: FeedGroup[] = []
97
+
98
+ export default feeds
87
99
  ```
88
100
 
89
101
  如果没有这个文件,友链页面和 OPML 输出会使用空数据,并且构建时会记录一条警告。
@@ -250,6 +262,8 @@ UI 分组、同路径组件覆盖、CSS 覆盖、服务端/路由自定义与 Sh
250
262
  | [补丁说明](./docs/PATCHES.zh-CN.md) | 使用方补丁归属与当前结论 |
251
263
  | [发布审计](./docs/RELEASE-AUDIT.zh-CN.md) | 收尾前工程审计与剩余发布门槛 |
252
264
  | [发布清单](./docs/RELEASE-CHECKLIST.zh-CN.md) | 确切的最终检查、剩余阻塞项与验证证据 |
265
+ | [发布指南](./docs/PUBLISHING.zh-CN.md) | 版本管理、tag、GitHub Release、OIDC 发布、provenance 与回滚策略 |
266
+ | [更新日志](./CHANGELOG.md) | 面向使用者的发布历史 |
253
267
  | [抽取历史](./docs/history/2026-09-layer-extraction.zh-CN.md) | 历史阶段与一次性差分验证 |
254
268
 
255
269
  ## 开发
@@ -288,9 +302,9 @@ pnpm sync:verify # 重新运行主题纯度与基线检查
288
302
 
289
303
  ## 发布状态
290
304
 
291
- Clarity Theme 是一个 **v0.1.0 发布前 Layer 候选版本**。Layer/包边界、已校验配置、Content 工厂、渲染管线、服务端输出、playground、真实消费者验收、兼容性矩阵、三层 CI 与上游同步基线均已实现。
305
+ Clarity Theme 是一个 **v0.1.1 门禁 npm 发布版本**。Layer/包边界、已校验配置、Content 工厂、渲染管线、服务端输出、playground、真实消费者验收、兼容性矩阵、三层 CI、上游同步基线、发布门禁与 OIDC 发布工作流均已实现。剩余的人工发布步骤见[发布检查清单](./docs/RELEASE-CHECKLIST.zh-CN.md)。
292
306
 
293
- 首次 npm 发布仍被[路线图](./docs/ROADMAP.zh-CN.md)中的 P0 正确性事项刻意阻塞——尤其是服务端/客户端配置拆分、功能关闭时的路由语义、反镜像导航验证与 no-op 随机固定链接契约——同时还需要一次在确切 commit 上的发布运行。迁移文档与可复现性正在本次收尾阶段完成。
307
+ [路线图](./docs/ROADMAP.zh-CN.md)中的 v0.1.0 正确性门禁已解决:服务端/客户端配置已拆分、功能关闭路由在运行时返回 404、反镜像导航已在真实浏览器中验证、no-op 随机固定链接字段已移除,多模式统计已增加回归测试。其余推迟事项记录在路线图与发布说明中。
294
308
 
295
309
  ## 许可证
296
310
 
package/app/app.config.ts CHANGED
@@ -1,110 +1,110 @@
1
- /**
2
- * Clarity Theme UI 默认配置。
3
- *
4
- * 站点数据(标题、作者、文章分类等)来自根目录 clarity.config.ts,
5
- * 由 modules/clarity-config 注入到 appConfig.clarity 中。
6
- *
7
- * 消费项目可在自己的 app/app.config.ts 中按需覆盖任意键。
8
- */
9
- export default defineAppConfig({
10
- clarity: {
11
- // @keep-sorted
12
- component: {
13
- alert: {
14
- /** 默认使用卡片风格还是扁平风格 */
15
- defaultStyle: 'card' as 'card' | 'flat',
16
- },
17
-
18
- codeblock: {
19
- /** 代码块触发折叠的行数 */
20
- triggerRows: 32,
21
- /** 代码块折叠后的行数 */
22
- collapsedRows: 16,
23
- /** 启用代码块缩进导航会关闭空格渲染 */
24
- enableIndentGuide: true,
25
- /** 代码块缩进导航竖线匹配空格数 */
26
- indent: 4,
27
- /** tab 渲染宽度 */
28
- tabSize: 3,
29
- },
30
-
31
- /** 文章开头摘要 */
32
- excerpt: {
33
- animation: true,
34
- caret: '_',
35
- },
36
-
37
- /** 精选文章 Slide */
38
- slide: {
39
- /** 适合封面图无字时启用 */
40
- showTitle: true,
41
- },
42
-
43
- stats: {
44
- /** 归档页面每年标题对应的年龄,无需展示时可留空 */
45
- birthYear: undefined as number | undefined,
46
- },
47
- },
48
-
49
- // @keep-sorted
50
- footer: {
51
- /** 侧边栏底部图标导航 */
52
- iconNav: [] as { icon: string, text: string, url: string }[],
53
- /** 页脚站点地图 */
54
- nav: [] as {
55
- title: string
56
- items: { icon: string, text: string, url: string }[]
57
- }[],
58
- },
59
-
60
- /** 左侧栏顶部 Logo */
61
- header: {
62
- /** 展示标题文本,否则展示纯 Logo */
63
- showTitle: true,
64
- emojiTail: [] as string[],
65
- },
66
-
67
- /** 友链页面 */
68
- link: {
69
- /** 无订阅源展示静音图标 */
70
- remindNoFeed: true,
71
- /** 友链分组内随机排序 */
72
- randomInGroup: true,
73
- },
74
-
75
- /** 左侧栏导航 */
76
- nav: [
77
- {
78
- title: '',
79
- items: [
80
- { icon: 'tabler:files', text: '文章', url: '/' },
81
- { icon: 'tabler:link', text: '友链', url: '/link' },
82
- { icon: 'tabler:archive', text: '归档', url: '/archive' },
83
- ],
84
- },
85
- ],
86
-
87
- pagination: {
88
- perPage: 10,
89
- /** 默认排序方式,需要是 article.order 中的键名 */
90
- sortOrder: 'date',
91
- /** 允许(普通/预览/归档)文章列表正序,开启后排序方式左侧图标可切换顺序 */
92
- allowAscending: false,
93
- },
94
-
95
- themes: {
96
- light: {
97
- icon: 'tabler:sun',
98
- tip: '浅色模式',
99
- },
100
- system: {
101
- icon: 'tabler:device-desktop',
102
- tip: '跟随系统',
103
- },
104
- dark: {
105
- icon: 'tabler:moon',
106
- tip: '深色模式',
107
- },
108
- },
109
- },
110
- })
1
+ /**
2
+ * Clarity Theme UI 默认配置。
3
+ *
4
+ * 站点数据(标题、作者、文章分类等)来自根目录 clarity.config.ts,
5
+ * 由 modules/clarity-config 注入到 appConfig.clarity 中。
6
+ *
7
+ * 消费项目可在自己的 app/app.config.ts 中按需覆盖任意键。
8
+ */
9
+ export default defineAppConfig({
10
+ clarity: {
11
+ // @keep-sorted
12
+ component: {
13
+ alert: {
14
+ /** 默认使用卡片风格还是扁平风格 */
15
+ defaultStyle: 'card' as 'card' | 'flat',
16
+ },
17
+
18
+ codeblock: {
19
+ /** 代码块触发折叠的行数 */
20
+ triggerRows: 32,
21
+ /** 代码块折叠后的行数 */
22
+ collapsedRows: 16,
23
+ /** 启用代码块缩进导航会关闭空格渲染 */
24
+ enableIndentGuide: true,
25
+ /** 代码块缩进导航竖线匹配空格数 */
26
+ indent: 4,
27
+ /** tab 渲染宽度 */
28
+ tabSize: 3,
29
+ },
30
+
31
+ /** 文章开头摘要 */
32
+ excerpt: {
33
+ animation: true,
34
+ caret: '_',
35
+ },
36
+
37
+ /** 精选文章 Slide */
38
+ slide: {
39
+ /** 适合封面图无字时启用 */
40
+ showTitle: true,
41
+ },
42
+
43
+ stats: {
44
+ /** 归档页面每年标题对应的年龄,无需展示时可留空 */
45
+ birthYear: undefined as number | undefined,
46
+ },
47
+ },
48
+
49
+ // @keep-sorted
50
+ footer: {
51
+ /** 侧边栏底部图标导航 */
52
+ iconNav: [] as { icon: string, text: string, url: string }[],
53
+ /** 页脚站点地图 */
54
+ nav: [] as {
55
+ title: string
56
+ items: { icon: string, text: string, url: string }[]
57
+ }[],
58
+ },
59
+
60
+ /** 左侧栏顶部 Logo */
61
+ header: {
62
+ /** 展示标题文本,否则展示纯 Logo */
63
+ showTitle: true,
64
+ emojiTail: [] as string[],
65
+ },
66
+
67
+ /** 友链页面 */
68
+ link: {
69
+ /** 无订阅源展示静音图标 */
70
+ remindNoFeed: true,
71
+ /** 友链分组内随机排序 */
72
+ randomInGroup: true,
73
+ },
74
+
75
+ /** 左侧栏导航 */
76
+ nav: [
77
+ {
78
+ title: '',
79
+ items: [
80
+ { icon: 'tabler:files', text: '文章', url: '/' },
81
+ { icon: 'tabler:link', text: '友链', url: '/link' },
82
+ { icon: 'tabler:archive', text: '归档', url: '/archive' },
83
+ ],
84
+ },
85
+ ],
86
+
87
+ pagination: {
88
+ perPage: 10,
89
+ /** 默认排序方式,需要是 article.order 中的键名 */
90
+ sortOrder: 'date',
91
+ /** 允许(普通/预览/归档)文章列表正序,开启后排序方式左侧图标可切换顺序 */
92
+ allowAscending: false,
93
+ },
94
+
95
+ themes: {
96
+ light: {
97
+ icon: 'tabler:sun',
98
+ tip: '浅色模式',
99
+ },
100
+ system: {
101
+ icon: 'tabler:device-desktop',
102
+ tip: '跟随系统',
103
+ },
104
+ dark: {
105
+ icon: 'tabler:moon',
106
+ tip: '深色模式',
107
+ },
108
+ },
109
+ },
110
+ })
package/app/app.vue CHANGED
@@ -1,5 +1,5 @@
1
- <template>
2
- <NuxtLayout>
3
- <NuxtPage />
4
- </NuxtLayout>
5
- </template>
1
+ <template>
2
+ <NuxtLayout>
3
+ <NuxtPage />
4
+ </NuxtLayout>
5
+ </template>
@@ -1,27 +1,27 @@
1
- <script setup lang="ts">
2
- const layoutStore = useLayoutStore()
3
-
4
- // 页面完成异步 setup 后才注册具名插槽;水合前等待,避免重复插入 SSR 侧栏。
5
- const layoutSlots = inject<{ ready: Promise<void> }>(Symbol.for('dxup:layout-slots'))
6
- if (layoutSlots)
7
- await layoutSlots.ready
8
- </script>
9
-
10
- <template>
11
- <BlogMask
12
- :show="layoutStore.state === 'aside'"
13
- class="widescreen-only"
14
- @click="layoutStore.close()"
15
- />
16
-
17
- <!-- 不能用 Transition 实现弹出收起动画,因为宽屏状态始终显示 -->
18
- <!-- 如果为空数组则隐藏 -->
19
- <aside id="blog-aside" :class="{ show: layoutStore.state === 'aside' }">
20
- <slot />
21
- </aside>
22
- </template>
23
-
24
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ const layoutStore = useLayoutStore()
3
+
4
+ // 页面完成异步 setup 后才注册具名插槽;水合前等待,避免重复插入 SSR 侧栏。
5
+ const layoutSlots = inject<{ ready: Promise<void> }>(Symbol.for('dxup:layout-slots'))
6
+ if (layoutSlots)
7
+ await layoutSlots.ready
8
+ </script>
9
+
10
+ <template>
11
+ <BlogMask
12
+ :show="layoutStore.state === 'aside'"
13
+ class="widescreen-only"
14
+ @click="layoutStore.close()"
15
+ />
16
+
17
+ <!-- 不能用 Transition 实现弹出收起动画,因为宽屏状态始终显示 -->
18
+ <!-- 如果为空数组则隐藏 -->
19
+ <aside id="blog-aside" :class="{ show: layoutStore.state === 'aside' }">
20
+ <slot />
21
+ </aside>
22
+ </template>
23
+
24
+ <style lang="scss" scoped>
25
25
  #blog-aside {
26
26
  display: flex;
27
27
  flex-direction: column;
@@ -60,4 +60,4 @@ if (layoutSlots)
60
60
  display: none;
61
61
  }
62
62
  }
63
- </style>
63
+ </style>
@@ -1,27 +1,27 @@
1
- <script setup lang="ts">
2
- const clarity = useClarityConfig()
3
- </script>
4
-
5
- <template>
6
- <footer class="blog-footer">
7
- <nav class="footer-nav">
8
- <div v-for="(group, groupIndex) in clarity.footer.nav" :key="groupIndex">
9
- <hgroup class="text-creative" v-text="group.title" />
10
- <menu>
11
- <li v-for="(item, itemIndex) in group.items" :key="itemIndex">
12
- <UtilLink :to="item.url">
13
- <Icon :name="item.icon" />
14
- <span class="nav-text">{{ item.text }}</span>
15
- </UtilLink>
16
- </li>
17
- </menu>
18
- </div>
19
- </nav>
20
- <p v-html="clarity.footer.copyright" />
21
- </footer>
22
- </template>
23
-
24
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ const clarity = useClarityConfig()
3
+ </script>
4
+
5
+ <template>
6
+ <footer class="blog-footer">
7
+ <nav class="footer-nav">
8
+ <div v-for="(group, groupIndex) in clarity.footer.nav" :key="groupIndex">
9
+ <hgroup class="text-creative" v-text="group.title" />
10
+ <menu>
11
+ <li v-for="(item, itemIndex) in group.items" :key="itemIndex">
12
+ <UtilLink :to="item.url">
13
+ <Icon :name="item.icon" />
14
+ <span class="nav-text">{{ item.text }}</span>
15
+ </UtilLink>
16
+ </li>
17
+ </menu>
18
+ </div>
19
+ </nav>
20
+ <p v-html="clarity.footer.copyright" />
21
+ </footer>
22
+ </template>
23
+
24
+ <style lang="scss" scoped>
25
25
  .blog-footer {
26
26
  margin: 3rem 1rem;
27
27
  font-size: 0.9em;
@@ -58,4 +58,4 @@ const clarity = useClarityConfig()
58
58
  margin: 0.5em;
59
59
  }
60
60
  }
61
- </style>
61
+ </style>
@@ -1,50 +1,50 @@
1
- <script setup lang="ts">
2
- withDefaults(defineProps<{
3
- tag?: string
4
- }>(), {
5
- tag: 'div',
6
- })
7
- const clarity = useClarityConfig()
8
- </script>
9
-
10
- <template>
11
- <UtilLink class="blog-header">
12
- <div v-if="clarity.header.emojiTail" class="emoji-tail">
13
- <span
14
- v-for="(emoji, emojiIndex) in clarity.header.emojiTail"
15
- :key="emojiIndex"
16
- class="split-char"
17
- :style="getFixedDelay(emojiIndex * .6 - 3)"
18
- v-text="emoji"
19
- />
20
- </div>
21
-
22
- <NuxtImg
23
- :src="clarity.header.logo"
24
- class="blog-logo round-cobblestone"
25
- :class="{ circle: clarity.header.showTitle }"
26
- :alt="clarity.site.title"
27
- />
28
-
29
- <div v-if="clarity.header.showTitle" class="blog-text">
30
- <component :is="tag" class="header-title">
31
- <span
32
- v-for="(char, charIndex) in clarity.site.title"
33
- :key="charIndex"
34
- class="split-char"
35
- :style="getFixedDelay((charIndex + 1) * .1)"
36
- v-text="char"
37
- />
38
- </component>
39
-
40
- <div class="header-subtitle">
41
- {{ clarity.header.subtitle }}
42
- </div>
43
- </div>
44
- </UtilLink>
45
- </template>
46
-
47
- <style lang="scss" scoped>
1
+ <script setup lang="ts">
2
+ withDefaults(defineProps<{
3
+ tag?: string
4
+ }>(), {
5
+ tag: 'div',
6
+ })
7
+ const clarity = useClarityConfig()
8
+ </script>
9
+
10
+ <template>
11
+ <UtilLink class="blog-header">
12
+ <div v-if="clarity.header.emojiTail" class="emoji-tail">
13
+ <span
14
+ v-for="(emoji, emojiIndex) in clarity.header.emojiTail"
15
+ :key="emojiIndex"
16
+ class="split-char"
17
+ :style="getFixedDelay(emojiIndex * .6 - 3)"
18
+ v-text="emoji"
19
+ />
20
+ </div>
21
+
22
+ <NuxtImg
23
+ :src="clarity.header.logo"
24
+ class="blog-logo round-cobblestone"
25
+ :class="{ circle: clarity.header.showTitle }"
26
+ :alt="clarity.site.title"
27
+ />
28
+
29
+ <div v-if="clarity.header.showTitle" class="blog-text">
30
+ <component :is="tag" class="header-title">
31
+ <span
32
+ v-for="(char, charIndex) in clarity.site.title"
33
+ :key="charIndex"
34
+ class="split-char"
35
+ :style="getFixedDelay((charIndex + 1) * .1)"
36
+ v-text="char"
37
+ />
38
+ </component>
39
+
40
+ <div class="header-subtitle">
41
+ {{ clarity.header.subtitle }}
42
+ </div>
43
+ </div>
44
+ </UtilLink>
45
+ </template>
46
+
47
+ <style lang="scss" scoped>
48
48
  .blog-header {
49
49
  contain: layout;
50
50
  display: flex;
@@ -143,4 +143,4 @@ const clarity = useClarityConfig()
143
143
  filter: blur(1px);
144
144
  }
145
145
  }
146
- </style>
146
+ </style>