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.
- package/README.md +48 -222
- package/README.zh-CN.md +50 -245
- package/nuxt.config.ts +18 -15
- package/package.json +17 -19
- package/{app → src}/app.config.ts +1 -1
- package/{app → src}/components/widget/BlogTech.vue +2 -0
- package/{app → src}/composables/useArticle.ts +2 -2
- package/{config → src/config}/app.ts +1 -1
- package/{config → src/config}/define.mjs +1 -1
- package/{config → src/config}/define.ts +1 -1
- package/{config → src/config}/feeds.empty.ts +1 -1
- package/{config → src/config}/index.ts +1 -1
- package/{config → src/config}/public.ts +1 -1
- package/{img → src/img}/index.ts +2 -2
- package/{modules → src/modules}/clarity-config/index.ts +12 -9
- package/src/modules/clarity-source-layout/index.ts +78 -0
- package/{server → src/server}/routes/subscriptions.opml.get.ts +1 -1
- package/{app → src}/types/article.ts +3 -3
- package/src/types/feed.ts +1 -0
- package/app/types/feed.ts +0 -1
- /package/{app → src}/app.vue +0 -0
- /package/{app → src}/assets/css/_variable.scss +0 -0
- /package/{app → src}/assets/css/animation.scss +0 -0
- /package/{app → src}/assets/css/article.scss +0 -0
- /package/{app → src}/assets/css/color.scss +0 -0
- /package/{app → src}/assets/css/font.scss +0 -0
- /package/{app → src}/assets/css/main.scss +0 -0
- /package/{app → src}/assets/css/reusable.scss +0 -0
- /package/{app → src}/assets/icons/solar-rewind-back-bold-duotone.svg +0 -0
- /package/{app → src}/assets/icons/solar-rewind-forward-bold-duotone.svg +0 -0
- /package/{app → src}/components/blog/BlogAside.vue +0 -0
- /package/{app → src}/components/blog/BlogFooter.vue +0 -0
- /package/{app → src}/components/blog/BlogHeader.global.vue +0 -0
- /package/{app → src}/components/blog/BlogPanel.vue +0 -0
- /package/{app → src}/components/blog/BlogSidebar.vue +0 -0
- /package/{app → src}/components/blog/BlogWidget.vue +0 -0
- /package/{app → src}/components/blog/Mask.vue +0 -0
- /package/{app → src}/components/blog/SkipToContent.vue +0 -0
- /package/{app → src}/components/blog/ThemeToggle.vue +0 -0
- /package/{app → src}/components/content/Alert.vue +0 -0
- /package/{app → src}/components/content/Badge.vue +0 -0
- /package/{app → src}/components/content/Blur.vue +0 -0
- /package/{app → src}/components/content/CardList.vue +0 -0
- /package/{app → src}/components/content/Chat.vue +0 -0
- /package/{app → src}/components/content/Copy.vue +0 -0
- /package/{app → src}/components/content/EmojiClock.vue +0 -0
- /package/{app → src}/components/content/FeedCard.vue +0 -0
- /package/{app → src}/components/content/FeedGroup.vue +0 -0
- /package/{app → src}/components/content/Folding.vue +0 -0
- /package/{app → src}/components/content/Key.vue +0 -0
- /package/{app → src}/components/content/LinkBanner.vue +0 -0
- /package/{app → src}/components/content/LinkCard.vue +0 -0
- /package/{app → src}/components/content/MdTitle.vue +0 -0
- /package/{app → src}/components/content/Mermaid.vue +0 -0
- /package/{app → src}/components/content/MusicScore.vue +0 -0
- /package/{app → src}/components/content/Pic.vue +0 -0
- /package/{app → src}/components/content/Poetry.vue +0 -0
- /package/{app → src}/components/content/ProseA.vue +0 -0
- /package/{app → src}/components/content/ProseCode.vue +0 -0
- /package/{app → src}/components/content/ProsePre.vue +0 -0
- /package/{app → src}/components/content/ProseTable.vue +0 -0
- /package/{app → src}/components/content/Quote.vue +0 -0
- /package/{app → src}/components/content/Tab.vue +0 -0
- /package/{app → src}/components/content/Timeline.vue +0 -0
- /package/{app → src}/components/content/Tip.vue +0 -0
- /package/{app → src}/components/content/VideoEmbed.vue +0 -0
- /package/{app → src}/components/partial/Button.vue +0 -0
- /package/{app → src}/components/partial/DlGroup.vue +0 -0
- /package/{app → src}/components/partial/Dropdown.vue +0 -0
- /package/{app → src}/components/partial/Error.vue +0 -0
- /package/{app → src}/components/partial/Expand.vue +0 -0
- /package/{app → src}/components/partial/IconNavList.vue +0 -0
- /package/{app → src}/components/partial/Pagination.vue +0 -0
- /package/{app → src}/components/partial/RadioGroup.vue +0 -0
- /package/{app → src}/components/partial/Secret.vue +0 -0
- /package/{app → src}/components/partial/Slider.vue +0 -0
- /package/{app → src}/components/partial/Toggle.vue +0 -0
- /package/{app → src}/components/popover/Lightbox.vue +0 -0
- /package/{app → src}/components/popover/Search.vue +0 -0
- /package/{app → src}/components/popover/SearchItem.vue +0 -0
- /package/{app → src}/components/post/Archive.vue +0 -0
- /package/{app → src}/components/post/Article.vue +0 -0
- /package/{app → src}/components/post/Comment.vue +0 -0
- /package/{app → src}/components/post/Excerpt.vue +0 -0
- /package/{app → src}/components/post/OrderToggle.vue +0 -0
- /package/{app → src}/components/post/PostFooter.vue +0 -0
- /package/{app → src}/components/post/PostHeader.vue +0 -0
- /package/{app → src}/components/post/PostSurround.vue +0 -0
- /package/{app → src}/components/post/Slide.vue +0 -0
- /package/{app → src}/components/util/Date.vue +0 -0
- /package/{app → src}/components/util/HydrateSafe.vue +0 -0
- /package/{app → src}/components/util/Img.vue +0 -0
- /package/{app → src}/components/util/Link.vue +0 -0
- /package/{app → src}/components/widget/BlogLog.vue +0 -0
- /package/{app → src}/components/widget/BlogStats.vue +0 -0
- /package/{app → src}/components/widget/Empty.vue +0 -0
- /package/{app → src}/components/widget/Toc.vue +0 -0
- /package/{app → src}/composables/useAvoid.ts +0 -0
- /package/{app → src}/composables/useCopy.ts +0 -0
- /package/{app → src}/composables/usePagination.ts +0 -0
- /package/{app → src}/composables/useShiki.ts +0 -0
- /package/{app → src}/composables/useToc.ts +0 -0
- /package/{app → src}/composables/useWidgets.ts +0 -0
- /package/{config → src/config}/content.d.mts +0 -0
- /package/{config → src/config}/content.mjs +0 -0
- /package/{config → src/config}/content.ts +0 -0
- /package/{config → src/config}/feed.ts +0 -0
- /package/{config → src/config}/index.d.mts +0 -0
- /package/{config → src/config}/index.mjs +0 -0
- /package/{config → src/config}/schema.d.mts +0 -0
- /package/{config → src/config}/schema.mjs +0 -0
- /package/{config → src/config}/schema.ts +0 -0
- /package/{config → src/config}/server.ts +0 -0
- /package/{app → src}/error.vue +0 -0
- /package/{img → src/img}/index.d.mts +0 -0
- /package/{img → src/img}/index.mjs +0 -0
- /package/{app → src}/layouts/default.vue +0 -0
- /package/{modules → src/modules}/clarity-config/anti-mirror-client.ts +0 -0
- /package/{app → src}/pages/[...slug].vue +0 -0
- /package/{app → src}/pages/archive.vue +0 -0
- /package/{app → src}/pages/index.vue +0 -0
- /package/{app → src}/pages/link.vue +0 -0
- /package/{app → src}/pages/preview.vue +0 -0
- /package/{app → src}/plugins/easter-egg.ts +0 -0
- /package/{app → src}/plugins/init.ts +0 -0
- /package/{app → src}/plugins/tippy.ts +0 -0
- /package/{public → src/public}/assets/atom.css +0 -0
- /package/{public → src/public}/assets/atom.xsl +0 -0
- /package/{public → src/public}/fonts/AlimamaFangYuanTi.woff2 +0 -0
- /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.d.mts +0 -0
- /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.mjs +0 -0
- /package/{remark-plugins → src/remark-plugins}/rehype-meta-slots.ts +0 -0
- /package/{remark-plugins → src/remark-plugins}/remark-code-component.d.mts +0 -0
- /package/{remark-plugins → src/remark-plugins}/remark-code-component.mjs +0 -0
- /package/{remark-plugins → src/remark-plugins}/remark-code-component.ts +0 -0
- /package/{server → src/server}/api/stats.get.ts +0 -0
- /package/{server → src/server}/routes/atom.xml.get.ts +0 -0
- /package/{server → src/server}/utils/clarity.ts +0 -0
- /package/{shared → src/shared}/types/content.ts +0 -0
- /package/{shared → src/shared}/utils/clarity.ts +0 -0
- /package/{shared → src/shared}/utils/icon.ts +0 -0
- /package/{shared → src/shared}/utils/link.ts +0 -0
- /package/{shared → src/shared}/utils/str.ts +0 -0
- /package/{shared → src/shared}/utils/time.ts +0 -0
- /package/{app → src}/shiki.config.ts +0 -0
- /package/{app → src}/stores/layout.ts +0 -0
- /package/{app → src}/stores/search.ts +0 -0
- /package/{app → src}/types/index.ts +0 -0
- /package/{app → src}/types/modal.ts +0 -0
- /package/{app → src}/types/nav.ts +0 -0
- /package/{app → src}/utils/anim.ts +0 -0
- /package/{app → src}/utils/img.ts +0 -0
package/README.zh-CN.md
CHANGED
|
@@ -1,51 +1,45 @@
|
|
|
1
1
|
# Clarity Theme
|
|
2
2
|
|
|
3
|
+
[](https://github.com/iicemeta/clarity-theme/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/clarity-theme)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
3
7
|
[English](./README.md) | **简体中文**
|
|
4
8
|
|
|
5
9
|
Clarity Theme 是一个从 [L33Z22L11/blog-v3](https://github.com/L33Z22L11/blog-v3) 抽取出来的可复用 **Nuxt 4 Layer 博客主题**。它提供通用的博客 UI、页面结构、Markdown/MDC 渲染、SEO 集成以及 feed/服务端输出;你的项目只需要提供全部站点数据与内容。
|
|
6
10
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
- 通过一条 `extends` 配置即可完成 Nuxt 4 Layer 安装
|
|
10
|
-
- 带默认值校验的站点配置,并严格拒绝未知字段
|
|
11
|
-
- 用于文章元数据与站点地图数据的 Nuxt Content 集合工厂
|
|
12
|
-
- Markdown、MDC 组件、Shiki 代码高亮、KaTeX、Mermaid、ABC 乐谱与富图片
|
|
13
|
-
- 文章列表、归档、分页、目录(TOC)、搜索、主题切换、小部件、预览与 404 路由
|
|
14
|
-
- Atom、OPML、统计、robots、sitemap 与 LLMs 输出
|
|
15
|
-
- 由使用方配置驱动的 Twikoo、head 脚本与反镜像集成
|
|
16
|
-
- UI 默认值、app config 覆盖、自定义 Shiki 主题与同路径组件覆盖
|
|
17
|
-
- 自动化的 workspace、tarball 消费者、SSR、浏览器、水合、纯度、契约、peer 与上游同步检查
|
|
18
|
-
|
|
19
|
-
## 环境要求
|
|
11
|
+
## 为什么选择 Clarity?
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
| --- | --- |
|
|
23
|
-
| Node.js | `^22.19 \|\| ^24.11 \|\| >=26` |
|
|
24
|
-
| pnpm | 12.4.1,或适用于你项目的兼容包管理器 |
|
|
25
|
-
| Nuxt peer | `^4.5.2` |
|
|
26
|
-
| Vue peer | `^3.5.42` |
|
|
13
|
+
Clarity 取代传统的 sync fork 工作流。你不需要把上游数千行代码合并进博客仓库,而是以 Layer 方式消费主题,只维护自己的文件:
|
|
27
14
|
|
|
28
|
-
|
|
15
|
+
- **一条 `extends` 配置**即可安装完整的博客应用骨架
|
|
16
|
+
- **Theme 与 Consumer 分离**:文章、友链、重定向、部署配置、密钥与依赖补丁永远不会进入主题包
|
|
17
|
+
- **配置带校验**:`clarity.config.ts` 由 schema 校验,提供默认值并严格拒绝未知字段
|
|
18
|
+
- **Content 工厂**:Nuxt Content 集合与文章 schema 由你的配置派生
|
|
19
|
+
- **富渲染**:Markdown、MDC 组件、Shiki 代码高亮、KaTeX、Mermaid、ABC 乐谱与富图片
|
|
20
|
+
- **完整输出**:文章列表、归档、分页、目录(TOC)、搜索、主题切换、小部件、Atom、OPML、统计、robots、sitemap 与 LLMs
|
|
21
|
+
- **集成仍归你所有**:Twikoo、head 脚本与反镜像均由消费方配置驱动
|
|
22
|
+
- **覆盖而无需 fork**:UI app config 覆盖、同路径组件覆盖、自定义 Shiki 主题与消费方 CSS
|
|
29
23
|
|
|
30
|
-
##
|
|
24
|
+
## 选择你的路径
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
| 起点 | 文档 |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| 新博客 | [创建项目](./docs/getting-started/new-project.zh-CN.md) |
|
|
29
|
+
| 现有 blog-v3 站点 | [从 blog-v3 迁移](./docs/getting-started/migration-from-blog-v3.zh-CN.md) · Agent Skill:`migrate-blog-v3-to-clarity` |
|
|
30
|
+
| 手动接入现有 Nuxt 应用 | [手动安装](./docs/getting-started/manual-installation.zh-CN.md) |
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
如需 Agent 协助迁移,直接让你的 Agent 使用 `migrate-blog-v3-to-clarity` Skill。完整 Skill 位于 [`skills/migrate-blog-v3-to-clarity`](./skills/migrate-blog-v3-to-clarity/SKILL.md)。
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
## 快速开始
|
|
39
35
|
|
|
40
36
|
```bash
|
|
41
|
-
pnpm
|
|
37
|
+
pnpm create clarity-theme@beta my-blog
|
|
38
|
+
cd my-blog
|
|
39
|
+
pnpm dev
|
|
42
40
|
```
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## 快速开始
|
|
47
|
-
|
|
48
|
-
### 1. 继承 Layer
|
|
42
|
+
创建包以独立的 `create-clarity-theme` npm 包分发;当前初始预发布位于 `@beta` dist-tag。完整参数见 [`create-clarity-theme/README.md`](./create-clarity-theme/README.md)。手动接入只需四个文件:
|
|
49
43
|
|
|
50
44
|
```ts
|
|
51
45
|
// nuxt.config.ts
|
|
@@ -54,8 +48,6 @@ export default defineNuxtConfig({
|
|
|
54
48
|
})
|
|
55
49
|
```
|
|
56
50
|
|
|
57
|
-
### 2. 定义站点配置
|
|
58
|
-
|
|
59
51
|
```ts
|
|
60
52
|
// clarity.config.ts
|
|
61
53
|
import { defineClarityConfig } from 'clarity-theme/config'
|
|
@@ -65,18 +57,11 @@ export default defineClarityConfig({
|
|
|
65
57
|
title: 'My Blog',
|
|
66
58
|
description: 'Notes about technology and life',
|
|
67
59
|
url: 'https://example.com/',
|
|
68
|
-
author: {
|
|
69
|
-
name: 'My Name',
|
|
70
|
-
avatar: '/avatar.webp',
|
|
71
|
-
},
|
|
60
|
+
author: { name: 'My Name', avatar: '/avatar.webp' },
|
|
72
61
|
},
|
|
73
62
|
})
|
|
74
63
|
```
|
|
75
64
|
|
|
76
|
-
`site.title`、`site.description`、`site.url` 与 `site.author.name` 为必填项。article、feed、stats、integration、feature 与 changelog 分组均为可选,并使用文档中记载的默认值。
|
|
77
|
-
|
|
78
|
-
### 3. 创建 Content schema
|
|
79
|
-
|
|
80
65
|
```ts
|
|
81
66
|
// content.config.ts
|
|
82
67
|
import { createClarityContentConfig } from 'clarity-theme/content'
|
|
@@ -85,227 +70,47 @@ import clarityConfig from './clarity.config'
|
|
|
85
70
|
export default createClarityContentConfig(clarityConfig)
|
|
86
71
|
```
|
|
87
72
|
|
|
88
|
-
文章放在 `content/posts/` 下,其他 Content 页面放在 `content/` 下。
|
|
89
|
-
|
|
90
|
-
### 4. 可选:提供友链数据
|
|
91
|
-
|
|
92
|
-
```ts
|
|
93
|
-
// feeds.ts
|
|
94
|
-
import type { FeedGroup } from 'clarity-theme/config'
|
|
95
|
-
|
|
96
|
-
const feeds: FeedGroup[] = []
|
|
97
|
-
|
|
98
|
-
export default feeds
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
如果没有这个文件,友链页面和 OPML 输出会使用空数据,并且构建时会记录一条警告。
|
|
102
|
-
|
|
103
|
-
### 5. 生成或开发
|
|
104
|
-
|
|
105
73
|
```bash
|
|
74
|
+
pnpm add clarity-theme
|
|
106
75
|
pnpm dev
|
|
107
|
-
pnpm generate
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
从现有 blog-v3 项目完整迁移的操作流程,见[迁移指南](./docs/MIGRATION.zh-CN.md)。主题数据与用户内容是被刻意分开的:这个包永远不会携带你的文章、友链、重定向、部署配置或包补丁。
|
|
111
|
-
|
|
112
|
-
## 从 blog-v3 迁移
|
|
113
|
-
|
|
114
|
-
完整的人工迁移指南见[迁移指南](./docs/MIGRATION.zh-CN.md)。如果你希望让当前 Agent 使用 `migrate-blog-v3-to-clarity` Skill 自动执行迁移,可以直接使用下面的提示词:
|
|
115
|
-
|
|
116
|
-
```markdown
|
|
117
|
-
请使用 `migrate-blog-v3-to-clarity` Skill,把当前这个 blog-v3 项目迁移到 Clarity Theme。
|
|
118
|
-
|
|
119
|
-
要求:
|
|
120
|
-
|
|
121
|
-
1. 先只读扫描项目,不立即修改。
|
|
122
|
-
2. 判断当前项目是否属于支持的 blog-v3 结构。
|
|
123
|
-
3. 检查 blog.config.ts、app/app.config.ts、content.config.ts、nuxt.config.ts、feeds.ts、redirects.json、patches、content、public、custom components、server、modules。
|
|
124
|
-
4. 生成迁移计划,并把所有风险项标出来。
|
|
125
|
-
5. 不修改文章正文和 frontmatter。
|
|
126
|
-
6. 不删除 content、public、redirects、patches 或未知自定义代码。
|
|
127
|
-
7. 能自动迁移的部分自动处理。
|
|
128
|
-
8. 需要人工判断的部分暂停修改并记录原因。
|
|
129
|
-
9. 迁移完成后执行 typecheck、generate 和兼容性验证。
|
|
130
|
-
10. 最后输出完整 migration report,包括修改文件、保留配置、人工处理项和测试结果。
|
|
131
|
-
|
|
132
|
-
整个过程只使用当前 Agent 串行执行,不启动并行 Agent。
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## 基础配置
|
|
136
|
-
|
|
137
|
-
| 文件 | 职责 |
|
|
138
|
-
| --- | --- |
|
|
139
|
-
| `clarity.config.ts` | 站点身份、文章语义、友链、统计、集成、功能开关、更新日志 |
|
|
140
|
-
| `app/app.config.ts` | 仅限可选的响应式 UI 覆盖 |
|
|
141
|
-
| `content.config.ts` | Nuxt Content 集合/schema |
|
|
142
|
-
| `feeds.ts` | 可选的友链数据 |
|
|
143
|
-
| 使用方 `runtimeConfig` | 环境相关配置,以及唯一合法的密钥存放位置 |
|
|
144
|
-
|
|
145
|
-
逐字段的默认值、可见性与示例见[配置说明](./docs/CONFIGURATION.zh-CN.md)。
|
|
146
|
-
|
|
147
|
-
可选分组示例:
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
export default defineClarityConfig({
|
|
151
|
-
site: {
|
|
152
|
-
title: 'My Blog',
|
|
153
|
-
description: 'A Nuxt blog',
|
|
154
|
-
url: 'https://example.com/',
|
|
155
|
-
author: { name: 'My Name' },
|
|
156
|
-
},
|
|
157
|
-
article: {
|
|
158
|
-
defaultCategory: 'Uncategorized',
|
|
159
|
-
categories: {
|
|
160
|
-
Tech: { icon: 'tabler:code', color: '#7777ff' },
|
|
161
|
-
},
|
|
162
|
-
types: { tech: {}, story: {} },
|
|
163
|
-
},
|
|
164
|
-
feed: { limit: 50, enableStyle: true },
|
|
165
|
-
features: {
|
|
166
|
-
atom: true,
|
|
167
|
-
opml: true,
|
|
168
|
-
stats: true,
|
|
169
|
-
antiMirror: false,
|
|
170
|
-
},
|
|
171
|
-
})
|
|
172
76
|
```
|
|
173
77
|
|
|
174
|
-
|
|
78
|
+
文章放在 `content/posts/` 下,其他 Content 页面放在 `content/` 下。可选的 `feeds.ts` 友链数据与部署说明见[手动安装](./docs/getting-started/manual-installation.zh-CN.md)。
|
|
175
79
|
|
|
176
|
-
##
|
|
80
|
+
## 环境要求
|
|
177
81
|
|
|
178
|
-
|
|
|
82
|
+
| 运行时 | 版本 |
|
|
179
83
|
| --- | --- |
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
184
|
-
| `clarity-theme/img` | 头像/favicon/图片 URL 辅助函数 |
|
|
185
|
-
|
|
186
|
-
Layer 还暴露了 `useClarityConfig()`、`useClaritySite()`、`useClarityArticle()` 与 `useClaritySiteFeedEntry()` 运行时自动导入,以及 `#clarity/feeds` 注入。它们是 Layer 契约,而不是独立的包子路径。
|
|
187
|
-
|
|
188
|
-
确切的导出/类型边界记录在 [API 文档](./docs/API.zh-CN.md) 中。
|
|
189
|
-
|
|
190
|
-
## 自定义
|
|
191
|
-
|
|
192
|
-
### UI 配置
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
// app/app.config.ts
|
|
196
|
-
export default defineAppConfig({
|
|
197
|
-
clarity: {
|
|
198
|
-
header: { emojiTail: ['📝'] },
|
|
199
|
-
pagination: { perPage: 10 },
|
|
200
|
-
nav: [
|
|
201
|
-
{
|
|
202
|
-
title: '',
|
|
203
|
-
items: [
|
|
204
|
-
{ icon: 'tabler:files', text: 'Articles', url: '/' },
|
|
205
|
-
{ icon: 'tabler:link', text: 'Friends', url: '/link' },
|
|
206
|
-
{ icon: 'tabler:archive', text: 'Archive', url: '/archive' },
|
|
207
|
-
],
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
})
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
对象会深度合并;数组会整体替换主题的值。
|
|
215
|
-
|
|
216
|
-
### 组件
|
|
217
|
-
|
|
218
|
-
在使用方项目中创建同路径的 Layer 相对组件即可替换,例如:
|
|
219
|
-
|
|
220
|
-
```text
|
|
221
|
-
app/components/content/Badge.vue
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
使用方组件优先于 Layer 组件。Nuxt 目前会针对这种有意的覆盖模式输出重名警告。
|
|
225
|
-
|
|
226
|
-
### Shiki 主题
|
|
227
|
-
|
|
228
|
-
在使用方项目中提供 `app/shiki.config.ts`。只有当该文件不存在时,才会使用主题的回退配置。
|
|
229
|
-
|
|
230
|
-
UI 分组、同路径组件覆盖、CSS 覆盖、服务端/路由自定义与 Shiki 归属详见[自定义说明](./docs/CUSTOMIZATION.zh-CN.md)。
|
|
231
|
-
|
|
232
|
-
## 兼容性与验证
|
|
233
|
-
|
|
234
|
-
验证套件覆盖:
|
|
235
|
-
|
|
236
|
-
- Playground 静态生成
|
|
237
|
-
- 独立的 `pnpm pack` 消费者安装
|
|
238
|
-
- Node 与 TypeScript 中的五个包导出
|
|
239
|
-
- 三种配置分支
|
|
240
|
-
- Markdown/MDC/代码/数学公式/Mermaid/乐谱/图片渲染
|
|
241
|
-
- 生产 SSR、真实浏览器渲染与开发水合
|
|
242
|
-
- 搜索、分页、归档、TOC、SEO、robots、sitemap、LLMs、Atom、OPML、统计、固定链接、404、Twikoo 分支、反镜像注入、UI 覆盖与组件覆盖
|
|
243
|
-
- 主题纯度、peer 依赖、同步工具与上游漂移
|
|
244
|
-
|
|
245
|
-
生成的发布矩阵见[兼容性说明](./docs/COMPATIBILITY.zh-CN.md)。当前的精确数量、已知限制、技术债与发布阻塞项见[项目状态](./docs/PROJECT-STATUS.zh-CN.md)与[路线图](./docs/ROADMAP.zh-CN.md)。发布前必须在确切的 commit 上重新按顺序运行整套验证;早先的结果不能替代。
|
|
84
|
+
| Node.js | `^22.19 \|\| ^24.11 \|\| >=26` |
|
|
85
|
+
| pnpm | 12.4.1,或适用于你项目的兼容包管理器 |
|
|
86
|
+
| Nuxt peer | `^4.5.2` |
|
|
87
|
+
| Vue peer | `^3.5.42` |
|
|
246
88
|
|
|
247
|
-
|
|
89
|
+
Clarity 属于应用运行时的一部分(Nuxt 构建与静态生成会直接加载 Layer),因此请将其安装为常规依赖,而不是开发依赖。
|
|
248
90
|
|
|
249
91
|
## 文档
|
|
250
92
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
| [自定义说明](./docs/CUSTOMIZATION.zh-CN.md) | UI、组件、Shiki、CSS、服务端与路由覆盖 |
|
|
260
|
-
| [兼容性说明](./docs/COMPATIBILITY.zh-CN.md) | 生成的发布兼容性矩阵 |
|
|
261
|
-
| [上游同步](./docs/UPSTREAM.zh-CN.md) | 基线、manifest、命令、冲突与工作流 |
|
|
262
|
-
| [补丁说明](./docs/PATCHES.zh-CN.md) | 使用方补丁归属与当前结论 |
|
|
263
|
-
| [发布审计](./docs/RELEASE-AUDIT.zh-CN.md) | 收尾前工程审计与剩余发布门槛 |
|
|
264
|
-
| [发布清单](./docs/RELEASE-CHECKLIST.zh-CN.md) | 确切的最终检查、剩余阻塞项与验证证据 |
|
|
265
|
-
| [发布指南](./docs/PUBLISHING.zh-CN.md) | 版本管理、tag、GitHub Release、OIDC 发布、provenance 与回滚策略 |
|
|
266
|
-
| [更新日志](./CHANGELOG.md) | 面向使用者的发布历史 |
|
|
267
|
-
| [抽取历史](./docs/history/2026-09-layer-extraction.zh-CN.md) | 历史阶段与一次性差分验证 |
|
|
93
|
+
所有文档都有对应的简体中文版本(同名 `*.zh-CN.md` 文件)。入口见[文档索引](./docs/README.zh-CN.md):
|
|
94
|
+
|
|
95
|
+
- **入门** — [创建新项目](./docs/getting-started/new-project.zh-CN.md)、[手动安装](./docs/getting-started/manual-installation.zh-CN.md)、[从 blog-v3 迁移](./docs/getting-started/migration-from-blog-v3.zh-CN.md)
|
|
96
|
+
- **指南** — [配置](./docs/guides/configuration.zh-CN.md)、[内容](./docs/guides/content.zh-CN.md)、[自定义](./docs/guides/customization.zh-CN.md)、[集成](./docs/guides/integrations.zh-CN.md)
|
|
97
|
+
- **参考** — [公共 API](./docs/reference/api.zh-CN.md)、[路由与输出](./docs/reference/routes-and-outputs.zh-CN.md)、[兼容性矩阵](./docs/reference/compatibility.zh-CN.md)
|
|
98
|
+
- **概念** — [架构](./docs/concepts/architecture.zh-CN.md)
|
|
99
|
+
- **维护者** — [开发](./docs/maintainers/development.zh-CN.md)、[测试](./docs/maintainers/testing.zh-CN.md)、[上游同步](./docs/maintainers/upstream-sync.zh-CN.md)、[补丁](./docs/maintainers/patches.zh-CN.md)、[发布](./docs/maintainers/publishing.zh-CN.md)、[发布清单](./docs/maintainers/release-checklist.zh-CN.md)、[项目状态](./docs/maintainers/project-status.zh-CN.md)、[路线图](./docs/maintainers/roadmap.zh-CN.md)、[文档规则](./docs/maintainers/documentation.zh-CN.md)
|
|
100
|
+
- **发布历史** — [CHANGELOG](./CHANGELOG.md);历史记录位于 [docs/history](./docs/history/)
|
|
268
101
|
|
|
269
102
|
## 开发
|
|
270
103
|
|
|
271
104
|
```bash
|
|
272
|
-
pnpm install
|
|
273
|
-
pnpm dev
|
|
274
|
-
pnpm generate
|
|
275
|
-
pnpm lint
|
|
105
|
+
pnpm install # Theme + playground workspace
|
|
106
|
+
pnpm dev # Playground dev server
|
|
107
|
+
pnpm generate # Playground static generation
|
|
108
|
+
pnpm lint # ESLint + Stylelint
|
|
276
109
|
pnpm typecheck
|
|
277
|
-
pnpm verify # 纯度/静态泄漏检查
|
|
278
|
-
pnpm peers check
|
|
279
|
-
pnpm test:sync
|
|
280
|
-
pnpm test:migration
|
|
281
|
-
pnpm test:contract
|
|
282
|
-
pnpm test:consumer
|
|
283
|
-
pnpm test:compatibility
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
CI 从包元数据推导 Node 与 pnpm 版本。它先在固定的 Node 矩阵上运行 lint/typecheck/verify/sync/migration/contract/peers,再在主 Node 版本上运行 playground 生成、真实消费者验收与渲染兼容性。另有一个每周工作流只检测并报告上游漂移。
|
|
287
|
-
|
|
288
|
-
确切的 CI 阶段与权限见[项目状态 → CI](./docs/PROJECT-STATUS.zh-CN.md#10-ci)。
|
|
289
|
-
|
|
290
|
-
## 上游同步
|
|
291
|
-
|
|
292
|
-
Clarity 从一个上游 Nuxt 博客抽取而来,并在 `sync-manifest.json` 中记录确切的已审查基线。同步工具区分可直接包含的路径、使用方持有的排除项、经过转换的主题契约与人工审查路径;未知的上游变更会阻止 apply。使用:
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
pnpm sync:check # 比较 manifest 基线与远端
|
|
296
|
-
pnpm sync:diff # 对上游变更分类
|
|
297
|
-
pnpm sync:apply # 事务式应用已审查的 include-only 变更
|
|
298
|
-
pnpm sync:verify # 重新运行主题纯度与基线检查
|
|
299
110
|
```
|
|
300
111
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
## 发布状态
|
|
304
|
-
|
|
305
|
-
Clarity Theme 是一个 **v0.1.1 门禁 npm 发布版本**。Layer/包边界、已校验配置、Content 工厂、渲染管线、服务端输出、playground、真实消费者验收、兼容性矩阵、三层 CI、上游同步基线、发布门禁与 OIDC 发布工作流均已实现。剩余的人工发布步骤见[发布检查清单](./docs/RELEASE-CHECKLIST.zh-CN.md)。
|
|
306
|
-
|
|
307
|
-
[路线图](./docs/ROADMAP.zh-CN.md)中的 v0.1.0 正确性门禁已解决:服务端/客户端配置已拆分、功能关闭路由在运行时返回 404、反镜像导航已在真实浏览器中验证、no-op 随机固定链接字段已移除,多模式统计已增加回归测试。其余推迟事项记录在路线图与发布说明中。
|
|
112
|
+
完整验证矩阵、上游同步与发布流程见[开发](./docs/maintainers/development.zh-CN.md)与[测试](./docs/maintainers/testing.zh-CN.md)。
|
|
308
113
|
|
|
309
114
|
## 许可证
|
|
310
115
|
|
|
311
|
-
|
|
116
|
+
主题代码为 MIT。上游博客的文章不包含在本包中。
|
package/nuxt.config.ts
CHANGED
|
@@ -12,13 +12,13 @@ const toThemePath = (path: string) => join(themeDir, path).replaceAll('\\', '/')
|
|
|
12
12
|
function pluginPath(path: string) {
|
|
13
13
|
// 插件必须是 .mjs:@nuxt/content 以 Node 原生方式加载,
|
|
14
14
|
// 不允许 node_modules 内的 TS 文件(TS 剥离限制)
|
|
15
|
-
return pathToFileURL(join(themeDir, 'remark-plugins', `${path}.mjs`)).href
|
|
15
|
+
return pathToFileURL(join(themeDir, 'src', 'remark-plugins', `${path}.mjs`)).href
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Clarity Theme Layer 配置
|
|
20
20
|
*
|
|
21
|
-
* 站点数据(SEO、favicon、scripts 等)由 modules/clarity-config
|
|
21
|
+
* 站点数据(SEO、favicon、scripts 等)由 src/modules/clarity-config
|
|
22
22
|
* 读取消费项目的 clarity.config.ts 后统一注入,此处仅包含 Theme 自身能力。
|
|
23
23
|
*/
|
|
24
24
|
export default defineNuxtConfig({
|
|
@@ -50,18 +50,18 @@ export default defineNuxtConfig({
|
|
|
50
50
|
compatibilityDate: '2024-08-03',
|
|
51
51
|
|
|
52
52
|
components: [
|
|
53
|
-
{ path: toThemePath('
|
|
54
|
-
toThemePath('
|
|
53
|
+
{ path: toThemePath('src/components/partial'), prefix: 'Z' },
|
|
54
|
+
toThemePath('src/components'),
|
|
55
55
|
],
|
|
56
56
|
|
|
57
57
|
// @keep-sorted
|
|
58
58
|
css: [
|
|
59
|
-
toThemePath('
|
|
60
|
-
toThemePath('
|
|
61
|
-
toThemePath('
|
|
62
|
-
toThemePath('
|
|
63
|
-
toThemePath('
|
|
64
|
-
toThemePath('
|
|
59
|
+
toThemePath('src/assets/css/animation.scss'),
|
|
60
|
+
toThemePath('src/assets/css/article.scss'),
|
|
61
|
+
toThemePath('src/assets/css/color.scss'),
|
|
62
|
+
toThemePath('src/assets/css/font.scss'),
|
|
63
|
+
toThemePath('src/assets/css/main.scss'),
|
|
64
|
+
toThemePath('src/assets/css/reusable.scss'),
|
|
65
65
|
],
|
|
66
66
|
|
|
67
67
|
// @keep-sorted
|
|
@@ -72,6 +72,9 @@ export default defineNuxtConfig({
|
|
|
72
72
|
|
|
73
73
|
// @keep-sorted
|
|
74
74
|
modules: [
|
|
75
|
+
// 必须最先运行:把 src/ 仅应用到 Clarity 自身 layer,避免静态
|
|
76
|
+
// srcDir / serverDir / dir.* 经 c12 合并泄漏到 consumer root 配置。
|
|
77
|
+
toThemePath('src/modules/clarity-source-layout'),
|
|
75
78
|
'@bikariya/image-viewer',
|
|
76
79
|
'@bikariya/modals',
|
|
77
80
|
'@bikariya/shiki',
|
|
@@ -84,7 +87,7 @@ export default defineNuxtConfig({
|
|
|
84
87
|
'@vueuse/nuxt',
|
|
85
88
|
// Layer 配置中的相对 module 路径会以消费项目为基准解析,必须使用绝对路径;
|
|
86
89
|
// 且 clarity-config 必须先于 nuxt-llms 运行:后者在 setup 时读取注入的 llms 站点配置
|
|
87
|
-
toThemePath('modules/clarity-config'),
|
|
90
|
+
toThemePath('src/modules/clarity-config'),
|
|
88
91
|
'nuxt-llms',
|
|
89
92
|
],
|
|
90
93
|
|
|
@@ -112,8 +115,8 @@ export default defineNuxtConfig({
|
|
|
112
115
|
nodeTsConfig: {
|
|
113
116
|
// @keep-sorted
|
|
114
117
|
include: [
|
|
115
|
-
'../config/**/*.ts',
|
|
116
|
-
'../remark-plugins/**/*.ts',
|
|
118
|
+
'../src/config/**/*.ts',
|
|
119
|
+
'../src/remark-plugins/**/*.ts',
|
|
117
120
|
],
|
|
118
121
|
},
|
|
119
122
|
},
|
|
@@ -122,7 +125,7 @@ export default defineNuxtConfig({
|
|
|
122
125
|
css: {
|
|
123
126
|
preprocessorOptions: {
|
|
124
127
|
scss: {
|
|
125
|
-
additionalData: `@use "${toThemePath('
|
|
128
|
+
additionalData: `@use "${toThemePath('src/assets/css/_variable.scss')}" as *;`,
|
|
126
129
|
},
|
|
127
130
|
},
|
|
128
131
|
},
|
|
@@ -189,7 +192,7 @@ ${homepage}
|
|
|
189
192
|
|
|
190
193
|
icon: {
|
|
191
194
|
customCollections: [
|
|
192
|
-
{ prefix: 'clarity', dir: toThemePath('
|
|
195
|
+
{ prefix: 'clarity', dir: toThemePath('src/assets/icons') },
|
|
193
196
|
],
|
|
194
197
|
clientBundle: {
|
|
195
198
|
scan: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clarity-theme",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"description": "Clarity Theme — 从 blog-v3 提取的可复用 Nuxt 4 Layer 博客主题",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
@@ -18,36 +18,29 @@
|
|
|
18
18
|
"exports": {
|
|
19
19
|
".": "./nuxt.config.ts",
|
|
20
20
|
"./config": {
|
|
21
|
-
"types": "./config/index.d.mts",
|
|
22
|
-
"default": "./config/index.mjs"
|
|
21
|
+
"types": "./src/config/index.d.mts",
|
|
22
|
+
"default": "./src/config/index.mjs"
|
|
23
23
|
},
|
|
24
24
|
"./content": {
|
|
25
|
-
"types": "./config/content.d.mts",
|
|
26
|
-
"default": "./config/content.mjs"
|
|
25
|
+
"types": "./src/config/content.d.mts",
|
|
26
|
+
"default": "./src/config/content.mjs"
|
|
27
27
|
},
|
|
28
28
|
"./img": {
|
|
29
|
-
"types": "./img/index.d.mts",
|
|
30
|
-
"default": "./img/index.mjs"
|
|
29
|
+
"types": "./src/img/index.d.mts",
|
|
30
|
+
"default": "./src/img/index.mjs"
|
|
31
31
|
},
|
|
32
32
|
"./schema": {
|
|
33
|
-
"types": "./config/schema.d.mts",
|
|
34
|
-
"default": "./config/schema.mjs"
|
|
33
|
+
"types": "./src/config/schema.d.mts",
|
|
34
|
+
"default": "./src/config/schema.mjs"
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"main": "./nuxt.config.ts",
|
|
38
38
|
"files": [
|
|
39
39
|
"LICENSE",
|
|
40
40
|
"README.md",
|
|
41
|
-
"app",
|
|
42
|
-
"config",
|
|
43
|
-
"img",
|
|
44
|
-
"modules",
|
|
45
41
|
"nuxt.config.ts",
|
|
46
42
|
"package.json",
|
|
47
|
-
"
|
|
48
|
-
"remark-plugins",
|
|
49
|
-
"server",
|
|
50
|
-
"shared"
|
|
43
|
+
"src"
|
|
51
44
|
],
|
|
52
45
|
"engines": {
|
|
53
46
|
"node": "^22.19 || ^24.11 || >=26"
|
|
@@ -112,6 +105,7 @@
|
|
|
112
105
|
"@nuxt/hints": "^1.1.4",
|
|
113
106
|
"@stylistic/stylelint-plugin": "^5.2.1",
|
|
114
107
|
"@types/hast": "^3.0.5",
|
|
108
|
+
"@types/mdast": "^4.0.4",
|
|
115
109
|
"@zinkawaii/stylelint-config": "^0.5.2",
|
|
116
110
|
"cspell": "^10.2.2",
|
|
117
111
|
"eslint": "^10.10.0",
|
|
@@ -132,9 +126,10 @@
|
|
|
132
126
|
"dev": "pnpm --dir playground dev",
|
|
133
127
|
"build": "pnpm --dir playground build",
|
|
134
128
|
"generate": "pnpm --dir playground generate",
|
|
135
|
-
"lint": "eslint && stylelint \"
|
|
136
|
-
"lint:fix": "eslint --fix && stylelint \"
|
|
129
|
+
"lint": "eslint && stylelint \"src/**/*.{vue,scss}\" \"playground/app/**/*.vue\"",
|
|
130
|
+
"lint:fix": "eslint --fix && stylelint \"src/**/*.{vue,scss}\" \"playground/app/**/*.vue\" --fix",
|
|
137
131
|
"typecheck": "pnpm --dir playground typecheck",
|
|
132
|
+
"docs:check": "node scripts/check-docs.mjs",
|
|
138
133
|
"verify": "node scripts/verify-theme.mjs",
|
|
139
134
|
"test:sync": "node --test tests/sync-upstream.test.mjs",
|
|
140
135
|
"test:migration": "node --test tests/migration-skill.test.mjs",
|
|
@@ -142,6 +137,9 @@
|
|
|
142
137
|
"test:release": "pnpm verify && pnpm test:consumer && pnpm test:compatibility",
|
|
143
138
|
"test:consumer": "node scripts/test-consumer.mjs",
|
|
144
139
|
"test:compatibility": "node scripts/test-compatibility.mjs",
|
|
140
|
+
"test:create": "pnpm --dir create-clarity-theme test",
|
|
141
|
+
"test:create:e2e": "pnpm --dir create-clarity-theme test:e2e",
|
|
142
|
+
"test:create:tarball": "pnpm --dir create-clarity-theme test:tarball",
|
|
145
143
|
"test:registry-consumer": "node scripts/test-registry-consumer.mjs",
|
|
146
144
|
"release:check": "node scripts/release-check.mjs",
|
|
147
145
|
"sync:check": "node scripts/sync-upstream.mjs check",
|
|
@@ -27,6 +27,8 @@ const ciPlatform = computed(() => {
|
|
|
27
27
|
|
|
28
28
|
const service = computed(() => ([
|
|
29
29
|
...ci ? [{ label: '构建平台', value: ciPlatform }] : [],
|
|
30
|
+
{ label: '图片存储', value: () => [h(Icon, { name: 'devicon:cloudflare' }), ' R2'] },
|
|
31
|
+
{ label: '软件协议', value: 'MIT' },
|
|
30
32
|
{ label: '文章许可', value: clarity.site.copyright?.abbr || '未配置' },
|
|
31
33
|
{ label: '规范域名', value: getDomain(clarity.site.url) },
|
|
32
34
|
]))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MetaSlotsTree } from '
|
|
2
|
-
import type { ClarityContentRow } from '
|
|
1
|
+
import type { MetaSlotsTree } from '../remark-plugins/rehype-meta-slots'
|
|
2
|
+
import type { ClarityContentRow } from '../shared/types/content'
|
|
3
3
|
import type { ArticleOrderType, ArticleProps } from '../types/article'
|
|
4
4
|
import { orderBy } from 'es-toolkit/array'
|
|
5
5
|
|
|
@@ -13,7 +13,7 @@ export function defineClarityConfig(config) {
|
|
|
13
13
|
.join('\n')
|
|
14
14
|
throw new Error(
|
|
15
15
|
`clarity.config.ts 校验失败:\n${issues}\n`
|
|
16
|
-
+ '未知字段会被拒绝:请检查拼写,或参考 docs/
|
|
16
|
+
+ '未知字段会被拒绝:请检查拼写,或参考 docs/guides/configuration.md 的字段契约。',
|
|
17
17
|
{ cause: result.error },
|
|
18
18
|
)
|
|
19
19
|
}
|
|
@@ -15,7 +15,7 @@ export function defineClarityConfig(config: ClarityConfigInput): ClarityConfig {
|
|
|
15
15
|
.join('\n')
|
|
16
16
|
throw new Error(
|
|
17
17
|
`clarity.config.ts 校验失败:\n${issues}\n`
|
|
18
|
-
+ '未知字段会被拒绝:请检查拼写,或参考 docs/
|
|
18
|
+
+ '未知字段会被拒绝:请检查拼写,或参考 docs/guides/configuration.md 的字段契约。',
|
|
19
19
|
{ cause: result.error },
|
|
20
20
|
)
|
|
21
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Nav, NavItem } from '../
|
|
1
|
+
export type { Nav, NavItem } from '../types/nav'
|
|
2
2
|
export type { ClarityAppConfig, ClarityUiConfig, ClarityUiConfigInput, NavGroup } from './app'
|
|
3
3
|
export { defineClarityConfig } from './define'
|
|
4
4
|
export type { Arch, FeedEntry, FeedGroup } from './feed'
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
/**
|
|
11
11
|
* 由 clarity.config.ts 注入 appConfig 的客户端可见配置。
|
|
12
12
|
*
|
|
13
|
-
* 可见性约定(详见 docs/
|
|
13
|
+
* 可见性约定(详见 docs/guides/configuration.md):
|
|
14
14
|
* - 只有客户端渲染确实需要的字段进入 appConfig;
|
|
15
15
|
* - feed、完整 stats、features 与 site.author.email 等服务端/构建期字段
|
|
16
16
|
* 改由 Nitro 私有 runtimeConfig 提供(config/server.ts),不进入客户端 bundle;
|
package/{img → src/img}/index.ts
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `clarity-theme/img` 类型真源。
|
|
3
3
|
*
|
|
4
|
-
* 类型实现复用 `
|
|
4
|
+
* 类型实现复用 `src/utils/img.ts`(Layer 内部与包导出共享同一份签名),
|
|
5
5
|
* 运行时实现在同目录 index.mjs:Node 原生 TS 剥离不允许
|
|
6
6
|
* node_modules 内的 TS 文件,因此包入口运行时必须是 .mjs。
|
|
7
7
|
*/
|
|
8
|
-
export * from '../
|
|
8
|
+
export * from '../utils/img'
|