clarity-theme 0.1.1 → 0.1.3

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 (152) hide show
  1. package/README.md +48 -222
  2. package/README.zh-CN.md +50 -245
  3. package/nuxt.config.ts +18 -15
  4. package/package.json +17 -19
  5. package/{app → src}/app.config.ts +1 -1
  6. package/{app → src}/components/widget/BlogTech.vue +2 -0
  7. package/{app → src}/composables/useArticle.ts +2 -2
  8. package/{config → src/config}/app.ts +1 -1
  9. package/{config → src/config}/define.mjs +1 -1
  10. package/{config → src/config}/define.ts +1 -1
  11. package/{config → src/config}/feeds.empty.ts +1 -1
  12. package/{config → src/config}/index.ts +1 -1
  13. package/{config → src/config}/public.ts +1 -1
  14. package/{img → src/img}/index.ts +2 -2
  15. package/{modules → src/modules}/clarity-config/index.ts +12 -9
  16. package/src/modules/clarity-source-layout/index.ts +78 -0
  17. package/{server → src/server}/routes/subscriptions.opml.get.ts +1 -1
  18. package/{app → src}/types/article.ts +3 -3
  19. package/src/types/feed.ts +1 -0
  20. package/app/types/feed.ts +0 -1
  21. /package/{app → src}/app.vue +0 -0
  22. /package/{app → src}/assets/css/_variable.scss +0 -0
  23. /package/{app → src}/assets/css/animation.scss +0 -0
  24. /package/{app → src}/assets/css/article.scss +0 -0
  25. /package/{app → src}/assets/css/color.scss +0 -0
  26. /package/{app → src}/assets/css/font.scss +0 -0
  27. /package/{app → src}/assets/css/main.scss +0 -0
  28. /package/{app → src}/assets/css/reusable.scss +0 -0
  29. /package/{app → src}/assets/icons/solar-rewind-back-bold-duotone.svg +0 -0
  30. /package/{app → src}/assets/icons/solar-rewind-forward-bold-duotone.svg +0 -0
  31. /package/{app → src}/components/blog/BlogAside.vue +0 -0
  32. /package/{app → src}/components/blog/BlogFooter.vue +0 -0
  33. /package/{app → src}/components/blog/BlogHeader.global.vue +0 -0
  34. /package/{app → src}/components/blog/BlogPanel.vue +0 -0
  35. /package/{app → src}/components/blog/BlogSidebar.vue +0 -0
  36. /package/{app → src}/components/blog/BlogWidget.vue +0 -0
  37. /package/{app → src}/components/blog/Mask.vue +0 -0
  38. /package/{app → src}/components/blog/SkipToContent.vue +0 -0
  39. /package/{app → src}/components/blog/ThemeToggle.vue +0 -0
  40. /package/{app → src}/components/content/Alert.vue +0 -0
  41. /package/{app → src}/components/content/Badge.vue +0 -0
  42. /package/{app → src}/components/content/Blur.vue +0 -0
  43. /package/{app → src}/components/content/CardList.vue +0 -0
  44. /package/{app → src}/components/content/Chat.vue +0 -0
  45. /package/{app → src}/components/content/Copy.vue +0 -0
  46. /package/{app → src}/components/content/EmojiClock.vue +0 -0
  47. /package/{app → src}/components/content/FeedCard.vue +0 -0
  48. /package/{app → src}/components/content/FeedGroup.vue +0 -0
  49. /package/{app → src}/components/content/Folding.vue +0 -0
  50. /package/{app → src}/components/content/Key.vue +0 -0
  51. /package/{app → src}/components/content/LinkBanner.vue +0 -0
  52. /package/{app → src}/components/content/LinkCard.vue +0 -0
  53. /package/{app → src}/components/content/MdTitle.vue +0 -0
  54. /package/{app → src}/components/content/Mermaid.vue +0 -0
  55. /package/{app → src}/components/content/MusicScore.vue +0 -0
  56. /package/{app → src}/components/content/Pic.vue +0 -0
  57. /package/{app → src}/components/content/Poetry.vue +0 -0
  58. /package/{app → src}/components/content/ProseA.vue +0 -0
  59. /package/{app → src}/components/content/ProseCode.vue +0 -0
  60. /package/{app → src}/components/content/ProsePre.vue +0 -0
  61. /package/{app → src}/components/content/ProseTable.vue +0 -0
  62. /package/{app → src}/components/content/Quote.vue +0 -0
  63. /package/{app → src}/components/content/Tab.vue +0 -0
  64. /package/{app → src}/components/content/Timeline.vue +0 -0
  65. /package/{app → src}/components/content/Tip.vue +0 -0
  66. /package/{app → src}/components/content/VideoEmbed.vue +0 -0
  67. /package/{app → src}/components/partial/Button.vue +0 -0
  68. /package/{app → src}/components/partial/DlGroup.vue +0 -0
  69. /package/{app → src}/components/partial/Dropdown.vue +0 -0
  70. /package/{app → src}/components/partial/Error.vue +0 -0
  71. /package/{app → src}/components/partial/Expand.vue +0 -0
  72. /package/{app → src}/components/partial/IconNavList.vue +0 -0
  73. /package/{app → src}/components/partial/Pagination.vue +0 -0
  74. /package/{app → src}/components/partial/RadioGroup.vue +0 -0
  75. /package/{app → src}/components/partial/Secret.vue +0 -0
  76. /package/{app → src}/components/partial/Slider.vue +0 -0
  77. /package/{app → src}/components/partial/Toggle.vue +0 -0
  78. /package/{app → src}/components/popover/Lightbox.vue +0 -0
  79. /package/{app → src}/components/popover/Search.vue +0 -0
  80. /package/{app → src}/components/popover/SearchItem.vue +0 -0
  81. /package/{app → src}/components/post/Archive.vue +0 -0
  82. /package/{app → src}/components/post/Article.vue +0 -0
  83. /package/{app → src}/components/post/Comment.vue +0 -0
  84. /package/{app → src}/components/post/Excerpt.vue +0 -0
  85. /package/{app → src}/components/post/OrderToggle.vue +0 -0
  86. /package/{app → src}/components/post/PostFooter.vue +0 -0
  87. /package/{app → src}/components/post/PostHeader.vue +0 -0
  88. /package/{app → src}/components/post/PostSurround.vue +0 -0
  89. /package/{app → src}/components/post/Slide.vue +0 -0
  90. /package/{app → src}/components/util/Date.vue +0 -0
  91. /package/{app → src}/components/util/HydrateSafe.vue +0 -0
  92. /package/{app → src}/components/util/Img.vue +0 -0
  93. /package/{app → src}/components/util/Link.vue +0 -0
  94. /package/{app → src}/components/widget/BlogLog.vue +0 -0
  95. /package/{app → src}/components/widget/BlogStats.vue +0 -0
  96. /package/{app → src}/components/widget/Empty.vue +0 -0
  97. /package/{app → src}/components/widget/Toc.vue +0 -0
  98. /package/{app → src}/composables/useAvoid.ts +0 -0
  99. /package/{app → src}/composables/useCopy.ts +0 -0
  100. /package/{app → src}/composables/usePagination.ts +0 -0
  101. /package/{app → src}/composables/useShiki.ts +0 -0
  102. /package/{app → src}/composables/useToc.ts +0 -0
  103. /package/{app → src}/composables/useWidgets.ts +0 -0
  104. /package/{config → src/config}/content.d.mts +0 -0
  105. /package/{config → src/config}/content.mjs +0 -0
  106. /package/{config → src/config}/content.ts +0 -0
  107. /package/{config → src/config}/feed.ts +0 -0
  108. /package/{config → src/config}/index.d.mts +0 -0
  109. /package/{config → src/config}/index.mjs +0 -0
  110. /package/{config → src/config}/schema.d.mts +0 -0
  111. /package/{config → src/config}/schema.mjs +0 -0
  112. /package/{config → src/config}/schema.ts +0 -0
  113. /package/{config → src/config}/server.ts +0 -0
  114. /package/{app → src}/error.vue +0 -0
  115. /package/{img → src/img}/index.d.mts +0 -0
  116. /package/{img → src/img}/index.mjs +0 -0
  117. /package/{app → src}/layouts/default.vue +0 -0
  118. /package/{modules → src/modules}/clarity-config/anti-mirror-client.ts +0 -0
  119. /package/{app → src}/pages/[...slug].vue +0 -0
  120. /package/{app → src}/pages/archive.vue +0 -0
  121. /package/{app → src}/pages/index.vue +0 -0
  122. /package/{app → src}/pages/link.vue +0 -0
  123. /package/{app → src}/pages/preview.vue +0 -0
  124. /package/{app → src}/plugins/easter-egg.ts +0 -0
  125. /package/{app → src}/plugins/init.ts +0 -0
  126. /package/{app → src}/plugins/tippy.ts +0 -0
  127. /package/{public → src/public}/assets/atom.css +0 -0
  128. /package/{public → src/public}/assets/atom.xsl +0 -0
  129. /package/{public → src/public}/fonts/AlimamaFangYuanTi.woff2 +0 -0
  130. /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.d.mts +0 -0
  131. /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.mjs +0 -0
  132. /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.ts +0 -0
  133. /package/{remark-plugins → src/remark-plugins}/remark-code-component.d.mts +0 -0
  134. /package/{remark-plugins → src/remark-plugins}/remark-code-component.mjs +0 -0
  135. /package/{remark-plugins → src/remark-plugins}/remark-code-component.ts +0 -0
  136. /package/{server → src/server}/api/stats.get.ts +0 -0
  137. /package/{server → src/server}/routes/atom.xml.get.ts +0 -0
  138. /package/{server → src/server}/utils/clarity.ts +0 -0
  139. /package/{shared → src/shared}/types/content.ts +0 -0
  140. /package/{shared → src/shared}/utils/clarity.ts +0 -0
  141. /package/{shared → src/shared}/utils/icon.ts +0 -0
  142. /package/{shared → src/shared}/utils/link.ts +0 -0
  143. /package/{shared → src/shared}/utils/str.ts +0 -0
  144. /package/{shared → src/shared}/utils/time.ts +0 -0
  145. /package/{app → src}/shiki.config.ts +0 -0
  146. /package/{app → src}/stores/layout.ts +0 -0
  147. /package/{app → src}/stores/search.ts +0 -0
  148. /package/{app → src}/types/index.ts +0 -0
  149. /package/{app → src}/types/modal.ts +0 -0
  150. /package/{app → src}/types/nav.ts +0 -0
  151. /package/{app → src}/utils/anim.ts +0 -0
  152. /package/{app → src}/utils/img.ts +0 -0
@@ -21,7 +21,10 @@ import { toServerClarityConfig } from '../../config/server'
21
21
  import handleMirror from './anti-mirror-client'
22
22
 
23
23
  const moduleDir = dirname(fileURLToPath(import.meta.url))
24
- const themeDir = resolve(moduleDir, '../..')
24
+ /** Theme 运行时源码根(src/):模块位于 src/modules/clarity-config */
25
+ const themeSrcDir = resolve(moduleDir, '../..')
26
+ /** Theme npm 包根(nuxt.config.ts / package.json 所在层) */
27
+ const themePkgDir = resolve(moduleDir, '../../..')
25
28
 
26
29
  /** app/app.config.ts 的 clarity 键只允许 UI 覆盖(站点级字段属于 clarity.config.ts) */
27
30
  const uiConfigKeys = new Set(['component', 'footer', 'header', 'link', 'nav', 'pagination', 'themes'])
@@ -42,7 +45,7 @@ export default defineNuxtModule<ModuleOptions>({
42
45
  const rootDir = nuxt.options.rootDir
43
46
 
44
47
  const configPath = resolve(rootDir, options.configFile ?? findConfigFile(rootDir))
45
- const feedsPath = findFeedsFile(rootDir, themeDir)
48
+ const feedsPath = findFeedsFile(rootDir, themeSrcDir)
46
49
 
47
50
  // ---- 依赖注入层:Theme 内部不感知消费项目的文件布局 ----
48
51
  Object.assign(nuxt.options.alias, {
@@ -51,14 +54,14 @@ export default defineNuxtModule<ModuleOptions>({
51
54
  })
52
55
 
53
56
  // @pinia/nuxt 不会自动扫描 Layer 的 stores 目录,需显式注册
54
- addImportsDir(resolve(themeDir, 'app/stores'))
57
+ addImportsDir(resolve(themeSrcDir, 'stores'))
55
58
 
56
59
  // ---- AppConfig 类型化:消费者 defineAppConfig({ clarity: ... }) 获得完整类型提示 ----
57
60
  // 注意:类型文件生成于 buildDir/types/ 下,相对路径必须以其为基准计算,
58
61
  // 否则导入解析失败会因 skipLibCheck 静默退化为 any(审计发现 #9)。
59
62
  const appConfigTypeDir = resolve(nuxt.options.buildDir, 'types')
60
- const appConfigTypePath = relative(appConfigTypeDir, resolve(themeDir, 'config/app.ts')).replaceAll('\\', '/')
61
- const globalsTypePath = relative(appConfigTypeDir, resolve(themeDir, 'app/types/index.ts')).replaceAll('\\', '/')
63
+ const appConfigTypePath = relative(appConfigTypeDir, resolve(themeSrcDir, 'config/app.ts')).replaceAll('\\', '/')
64
+ const globalsTypePath = relative(appConfigTypeDir, resolve(themeSrcDir, 'types/index.ts')).replaceAll('\\', '/')
62
65
  addTypeTemplate({
63
66
  filename: 'types/clarity-app-config.d.ts',
64
67
  getContents: () => [
@@ -86,7 +89,7 @@ export default defineNuxtModule<ModuleOptions>({
86
89
  // 需置于 '~' 之前以保证 Vite 别名前缀优先匹配
87
90
  if (!existsSync(resolve(nuxt.options.srcDir, 'shiki.config.ts'))) {
88
91
  nuxt.options.alias = {
89
- '~/shiki.config': resolve(themeDir, 'app/shiki.config.ts'),
92
+ '~/shiki.config': resolve(themeSrcDir, 'shiki.config.ts'),
90
93
  ...nuxt.options.alias,
91
94
  }
92
95
  }
@@ -176,7 +179,7 @@ export default defineNuxtModule<ModuleOptions>({
176
179
 
177
180
  // ---- 构建信息(供 BlogTech 等 Widget 使用) ----
178
181
  const consumerPkg = await loadJson(resolve(rootDir, 'package.json'), jiti)
179
- const themePkg = await loadJson(resolve(themeDir, 'package.json'), jiti)
182
+ const themePkg = await loadJson(resolve(themePkgDir, 'package.json'), jiti)
180
183
  nuxt.options.runtimeConfig.public.clarity = {
181
184
  theme: 'Clarity',
182
185
  themeVersion: String(themePkg?.version ?? ''),
@@ -308,13 +311,13 @@ function findConfigFile(rootDir: string) {
308
311
  return 'clarity.config.ts'
309
312
  }
310
313
 
311
- function findFeedsFile(rootDir: string, themeDir: string) {
314
+ function findFeedsFile(rootDir: string, themeSrcDir: string) {
312
315
  for (const name of ['feeds.ts', 'feeds.mjs', 'feeds.js']) {
313
316
  if (existsSync(resolve(rootDir, name))) {
314
317
  return { found: true, resolved: resolve(rootDir, name) }
315
318
  }
316
319
  }
317
- return { found: false, resolved: resolve(themeDir, 'config/feeds.empty.ts') }
320
+ return { found: false, resolved: resolve(themeSrcDir, 'config/feeds.empty.ts') }
318
321
  }
319
322
 
320
323
  async function loadJson(path: string, jiti: ReturnType<typeof createJiti>) {
@@ -0,0 +1,78 @@
1
+ import type { Nuxt } from '@nuxt/schema'
2
+ import { dirname, relative, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'
5
+
6
+ const moduleDir = dirname(fileURLToPath(import.meta.url))
7
+ const themeSrcDir = resolve(moduleDir, '../..')
8
+ const themePkgDir = resolve(moduleDir, '../../..')
9
+
10
+ /**
11
+ * Clarity keeps all runtime source under `src/`. These values must only apply
12
+ * to the theme layer; declaring them statically in `nuxt.config.ts` would let
13
+ * c12 merge them into consumers which do not explicitly override them.
14
+ */
15
+ export default defineNuxtModule({
16
+ meta: {
17
+ name: 'clarity-source-layout',
18
+ },
19
+
20
+ setup(_options, nuxt) {
21
+ const layer = findThemeLayer(nuxt)
22
+ if (!layer) {
23
+ return
24
+ }
25
+
26
+ const sourceDir = withTrailingSlash(themeSrcDir)
27
+ const directories = {
28
+ layouts: withTrailingSlash(resolve(themeSrcDir, 'layouts')),
29
+ middleware: withTrailingSlash(resolve(themeSrcDir, 'middleware')),
30
+ modules: withTrailingSlash(resolve(themeSrcDir, 'modules')),
31
+ pages: withTrailingSlash(resolve(themeSrcDir, 'pages')),
32
+ plugins: withTrailingSlash(resolve(themeSrcDir, 'plugins')),
33
+ public: withTrailingSlash(resolve(themeSrcDir, 'public')),
34
+ server: withTrailingSlash(resolve(themeSrcDir, 'server')),
35
+ shared: withTrailingSlash(resolve(themeSrcDir, 'shared')),
36
+ }
37
+
38
+ layer.config.srcDir = sourceDir
39
+ layer.config.serverDir = directories.server
40
+ layer.config.dir = {
41
+ ...layer.config.dir,
42
+ app: sourceDir,
43
+ modules: directories.modules,
44
+ public: directories.public,
45
+ shared: directories.shared,
46
+ }
47
+
48
+ // `getLayerDirectories()` caches a plain metadata object per layer before
49
+ // modules are installed. Nuxt exposes no invalidation API, so update the
50
+ // cached paths in place as well as `layer.config`.
51
+ const cached = getLayerDirectories(nuxt).find(directory => isSamePath(directory.root, themePkgDir))
52
+ if (cached) {
53
+ Object.assign(cached, {
54
+ app: sourceDir,
55
+ appLayouts: directories.layouts,
56
+ appMiddleware: directories.middleware,
57
+ appPages: directories.pages,
58
+ appPlugins: directories.plugins,
59
+ modules: directories.modules,
60
+ public: directories.public,
61
+ server: directories.server,
62
+ shared: directories.shared,
63
+ })
64
+ }
65
+ },
66
+ })
67
+
68
+ function findThemeLayer(nuxt: Nuxt) {
69
+ return nuxt.options._layers.find(layer => isSamePath(layer.config.rootDir ?? layer.cwd, themePkgDir))
70
+ }
71
+
72
+ function isSamePath(left: string, right: string) {
73
+ return left === right || relative(resolve(left), resolve(right)) === ''
74
+ }
75
+
76
+ function withTrailingSlash(path: string) {
77
+ return `${path.replace(/[\\/]$/, '').replaceAll('\\', '/')}/`
78
+ }
@@ -1,4 +1,4 @@
1
- import type { FeedEntry, FeedGroup } from '../../app/types/feed'
1
+ import type { FeedEntry, FeedGroup } from '../../types/feed'
2
2
  import XmlBuilder from 'fast-xml-builder'
3
3
  import { toZonedTemporal } from '../../shared/utils/time'
4
4
 
@@ -1,6 +1,6 @@
1
- import type { ClarityAppConfig } from '../../config/app'
2
- import type { ArticleSchema } from '../../config/content'
3
- import type { MetaSlotsTree } from '../../remark-plugins/rehype-meta-slots'
1
+ import type { ClarityAppConfig } from '../config/app'
2
+ import type { ArticleSchema } from '../config/content'
3
+ import type { MetaSlotsTree } from '../remark-plugins/rehype-meta-slots'
4
4
 
5
5
  export type ArticleOrderType = keyof ClarityAppConfig['article']['order']
6
6
 
@@ -0,0 +1 @@
1
+ export type { FeedEntry, FeedGroup } from '../config/feed'
package/app/types/feed.ts DELETED
@@ -1 +0,0 @@
1
- export type { FeedEntry, FeedGroup } from '../../config/feed'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes