create-cocowiki 0.2.2
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/LICENSE +21 -0
- package/README.md +14 -0
- package/bin/create-cocowiki.mjs +41 -0
- package/package.json +36 -0
- package/template/_gitignore +3 -0
- package/template/cocowiki.config.ts +37 -0
- package/template/components/ItemAtlas.vue +81 -0
- package/template/components/pages/AtlasPage.vue +7 -0
- package/template/content/archive.md +6 -0
- package/template/content/atlas.page.json +8 -0
- package/template/content/atlas.page.vue +7 -0
- package/template/content/contributors.md +6 -0
- package/template/content/index.md +21 -0
- package/template/content/search.md +6 -0
- package/template/content/welcome.md +88 -0
- package/template/data/contributors.json +17 -0
- package/template/data/items.json +34 -0
- package/template/package.json +16 -0
- package/template/pnpm-workspace.yaml +2 -0
- package/template/public/cocowiki-logo.png +0 -0
- package/template/public/favicon.png +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mueo
|
|
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
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# create-cocowiki
|
|
2
|
+
|
|
3
|
+
创建一个带有完整示例内容的 CoCoWiki 静态 Wiki 项目。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pnpm create cocowiki my-wiki
|
|
7
|
+
cd my-wiki
|
|
8
|
+
pnpm install
|
|
9
|
+
pnpm dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
生成的站点名称、npm 包名和首页名称会自动使用目标目录名 `my-wiki`。
|
|
13
|
+
|
|
14
|
+
项目主页与完整说明位于 [CoCoWiki 源码仓库](https://github.com/coconi-dev/cocowiki)。
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cp, mkdir, readFile, readdir, rename, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { basename, resolve } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const targetArgument = process.argv.slice(2).find((argument) => !argument.startsWith('-')) || 'cocowiki-site'
|
|
7
|
+
const targetDirectory = resolve(process.cwd(), targetArgument)
|
|
8
|
+
const templateDirectory = fileURLToPath(new URL('../template', import.meta.url))
|
|
9
|
+
const siteName = basename(targetDirectory)
|
|
10
|
+
|
|
11
|
+
function fail(message) {
|
|
12
|
+
console.error(`\ncreate-cocowiki: ${message}\n`)
|
|
13
|
+
process.exit(1)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
await mkdir(targetDirectory, { recursive: true })
|
|
18
|
+
const existing = await readdir(targetDirectory)
|
|
19
|
+
if (existing.length) fail(`目标目录不为空:${targetDirectory}`)
|
|
20
|
+
|
|
21
|
+
await cp(templateDirectory, targetDirectory, { recursive: true })
|
|
22
|
+
await rename(resolve(targetDirectory, '_gitignore'), resolve(targetDirectory, '.gitignore'))
|
|
23
|
+
|
|
24
|
+
const packageFile = resolve(targetDirectory, 'package.json')
|
|
25
|
+
const packageJson = JSON.parse(await readFile(packageFile, 'utf8'))
|
|
26
|
+
packageJson.name = siteName.toLocaleLowerCase().replace(/[^a-z0-9._-]+/g, '-') || 'cocowiki-site'
|
|
27
|
+
await writeFile(packageFile, `${JSON.stringify(packageJson, null, 2)}\n`)
|
|
28
|
+
|
|
29
|
+
for (const relativeFile of ['cocowiki.config.ts', 'content/index.md']) {
|
|
30
|
+
const filename = resolve(targetDirectory, relativeFile)
|
|
31
|
+
const source = await readFile(filename, 'utf8')
|
|
32
|
+
await writeFile(filename, source.replaceAll('__COCOWIKI_SITE_NAME__', siteName))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(`\nCoCoWiki 已创建:${targetDirectory}\n`)
|
|
36
|
+
console.log(` cd ${targetArgument}`)
|
|
37
|
+
console.log(' pnpm install')
|
|
38
|
+
console.log(' pnpm dev\n')
|
|
39
|
+
} catch (error) {
|
|
40
|
+
fail(error instanceof Error ? error.message : String(error))
|
|
41
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-cocowiki",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Create a CoCoWiki site.",
|
|
6
|
+
"author": "Mueo",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/coconi-dev/cocowiki#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/coconi-dev/cocowiki.git",
|
|
12
|
+
"directory": "packages/create-cocowiki"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/coconi-dev/cocowiki/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"cocowiki",
|
|
19
|
+
"wiki",
|
|
20
|
+
"vitepress",
|
|
21
|
+
"scaffold"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"create-cocowiki": "./bin/create-cocowiki.mjs"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"bin",
|
|
28
|
+
"template"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { defineCocoWikiConfig } from 'cocowiki'
|
|
2
|
+
|
|
3
|
+
export default defineCocoWikiConfig({
|
|
4
|
+
title: '__COCOWIKI_SITE_NAME__',
|
|
5
|
+
description: '一个由 Markdown、Vue 和静态数据组成的轻量资料站示例。',
|
|
6
|
+
lang: 'zh-CN',
|
|
7
|
+
// 部署到子目录时可改为 '/my-wiki/',根目录部署保持 '/'。
|
|
8
|
+
base: '/',
|
|
9
|
+
logo: '/cocowiki-logo.png',
|
|
10
|
+
favicon: '/favicon.png',
|
|
11
|
+
navigation: [
|
|
12
|
+
{ text: '首页', link: '/' },
|
|
13
|
+
{ text: '欢迎使用 CoCoWiki', link: '/welcome' },
|
|
14
|
+
{
|
|
15
|
+
text: '探索',
|
|
16
|
+
link: '/atlas',
|
|
17
|
+
items: [
|
|
18
|
+
{ text: '组件图鉴', link: '/atlas' },
|
|
19
|
+
{ text: '归档索引', link: '/archive' },
|
|
20
|
+
{ text: '贡献者', link: '/contributors' }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
home: {
|
|
25
|
+
visual: {
|
|
26
|
+
image: '/cocowiki-logo.png',
|
|
27
|
+
labels: ['Markdown', 'Vue', 'Search', 'Static', 'Theme', 'Archive']
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
search: { enabled: true },
|
|
31
|
+
markdown: { spoiler: true, wikiLink: true },
|
|
32
|
+
content: {
|
|
33
|
+
outline: true,
|
|
34
|
+
showPrevNext: true,
|
|
35
|
+
showLastUpdated: true
|
|
36
|
+
}
|
|
37
|
+
})
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import items from '../data/items.json'
|
|
4
|
+
|
|
5
|
+
const query = ref('')
|
|
6
|
+
const rarity = ref('all')
|
|
7
|
+
const category = ref('all')
|
|
8
|
+
const sort = ref('rarity')
|
|
9
|
+
const rarityRank: Record<string, number> = { core: 3, stable: 2, extended: 1 }
|
|
10
|
+
const rarityLabel: Record<string, string> = { core: '核心', stable: '稳定', extended: '扩展' }
|
|
11
|
+
const categoryLabel: Record<string, string> = { data: '数据层', logic: '逻辑层', interface: '交互层' }
|
|
12
|
+
const rarities = ['core', 'stable', 'extended']
|
|
13
|
+
const categories = [...new Set(items.map((item) => item.category))]
|
|
14
|
+
const filtered = computed(() => items
|
|
15
|
+
.filter((item) => !query.value || `${item.name} ${item.description}`.toLocaleLowerCase().includes(query.value.toLocaleLowerCase()))
|
|
16
|
+
.filter((item) => rarity.value === 'all' || item.rarity === rarity.value)
|
|
17
|
+
.filter((item) => category.value === 'all' || item.category === category.value)
|
|
18
|
+
.sort((a, b) => sort.value === 'name' ? a.name.localeCompare(b.name, 'zh-CN') : rarityRank[b.rarity] - rarityRank[a.rarity]))
|
|
19
|
+
const allContributors = [...new Set(items.flatMap((item) => item.contributors))]
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div class="atlas">
|
|
24
|
+
<header class="atlas-header">
|
|
25
|
+
<div><p class="cw-kicker">VUE PAGE EXAMPLE</p><h1>组件图鉴</h1><p>这是一个由静态 JSON 驱动的纯 Vue 页面,用来验证搜索、筛选与排序。</p></div>
|
|
26
|
+
<strong>{{ filtered.length }} <small>项</small></strong>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
<section class="atlas-toolbar" aria-label="图鉴筛选">
|
|
30
|
+
<label class="atlas-search"><span>⌕</span><input v-model="query" type="search" placeholder="搜索组件"></label>
|
|
31
|
+
<label><span>状态</span><select v-model="rarity"><option value="all">全部</option><option v-for="name in rarities" :key="name" :value="name">{{ rarityLabel[name] }}</option></select></label>
|
|
32
|
+
<label><span>层级</span><select v-model="category"><option value="all">全部</option><option v-for="name in categories" :key="name" :value="name">{{ categoryLabel[name] }}</option></select></label>
|
|
33
|
+
<label><span>排序</span><select v-model="sort"><option value="rarity">状态</option><option value="name">名称</option></select></label>
|
|
34
|
+
</section>
|
|
35
|
+
|
|
36
|
+
<section class="atlas-grid">
|
|
37
|
+
<article v-for="(item, index) in filtered" :key="item.id" class="atlas-card">
|
|
38
|
+
<span class="atlas-card__index">{{ String(index + 1).padStart(2, '0') }}</span>
|
|
39
|
+
<div class="atlas-card__content">
|
|
40
|
+
<div class="atlas-card__meta"><span>{{ categoryLabel[item.category] }}</span><b>{{ rarityLabel[item.rarity] }}</b></div>
|
|
41
|
+
<h2>{{ item.name }}</h2>
|
|
42
|
+
<p>{{ item.description }}</p>
|
|
43
|
+
<footer><span>维护者</span><strong>{{ item.contributors.join(' · ') }}</strong></footer>
|
|
44
|
+
</div>
|
|
45
|
+
</article>
|
|
46
|
+
<div v-if="!filtered.length" class="cw-empty"><strong>没有符合条件的项目</strong><p>调整关键词或筛选条件再试一次。</p></div>
|
|
47
|
+
</section>
|
|
48
|
+
|
|
49
|
+
<footer class="atlas-footer"><div><h2>页面维护者</h2><p>数据、逻辑和界面由三位机器人分别维护。</p></div><ContributorList :names="allContributors" /></footer>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style scoped>
|
|
54
|
+
.atlas-header { display: flex; align-items: end; justify-content: space-between; gap: 30px; padding: 6px 0 24px; border-bottom: 1px solid var(--cw-border); }
|
|
55
|
+
.atlas-header h1 { margin: 5px 0 3px; font-family: Georgia, "Noto Serif SC", serif; font-size: clamp(2rem, 5vw, 3rem); line-height: 1.2; }
|
|
56
|
+
.atlas-header p:last-child { max-width: 620px; margin: 0; color: var(--cw-muted); font-size: .9rem; }
|
|
57
|
+
.atlas-header > strong { color: var(--cw-accent); font-family: Georgia, serif; font-size: 2.3rem; }
|
|
58
|
+
.atlas-header > strong small { color: var(--cw-muted); font: 500 .7rem Inter, sans-serif; }
|
|
59
|
+
.atlas-toolbar { position: sticky; top: 56px; z-index: 15; display: grid; grid-template-columns: 1fr repeat(3, 135px); margin-bottom: 18px; border: 1px solid var(--cw-border); border-top: 0; background: var(--cw-header); backdrop-filter: blur(8px); }
|
|
60
|
+
.atlas-toolbar label { display: flex; align-items: center; min-height: 48px; padding: 0 13px; border-left: 1px solid var(--cw-border); }
|
|
61
|
+
.atlas-toolbar label > span { margin-right: auto; color: var(--cw-muted); font-size: .68rem; font-weight: 700; }
|
|
62
|
+
.atlas-toolbar select { max-width: 76px; color: var(--cw-text); border: 0; outline: 0; background: transparent; font-size: .76rem; }
|
|
63
|
+
.atlas-toolbar .atlas-search { border-left: 0; }
|
|
64
|
+
.atlas-search > span { color: var(--cw-accent) !important; font-size: 1.1rem !important; }
|
|
65
|
+
.atlas-search input { min-width: 0; flex: 1; color: var(--cw-text); border: 0; outline: 0; background: transparent; }
|
|
66
|
+
.atlas-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
|
|
67
|
+
.atlas-card { display: grid; grid-template-columns: 44px 1fr; min-width: 0; padding: 16px; border: 1px solid var(--cw-border); border-radius: var(--cw-radius); background: var(--cw-surface); }
|
|
68
|
+
.atlas-card:hover { border-color: var(--cw-accent); }
|
|
69
|
+
.atlas-card__index { color: var(--cw-muted); font: .72rem Georgia, serif; }
|
|
70
|
+
.atlas-card__meta { display: flex; justify-content: space-between; color: var(--cw-muted); font-size: .66rem; }
|
|
71
|
+
.atlas-card__meta b { color: var(--cw-gold); }
|
|
72
|
+
.atlas-card h2 { margin: 5px 0 3px; font-family: Georgia, "Noto Serif SC", serif; font-size: 1.06rem; }
|
|
73
|
+
.atlas-card p { min-height: 2.8em; margin: 0; color: var(--cw-muted); font-size: .78rem; line-height: 1.5; }
|
|
74
|
+
.atlas-card footer { display: flex; justify-content: space-between; margin-top: 12px; padding-top: 9px; border-top: 1px solid var(--cw-border); font-size: .66rem; }
|
|
75
|
+
.atlas-card footer span { color: var(--cw-muted); }
|
|
76
|
+
.atlas-footer { display: flex; align-items: center; justify-content: space-between; gap: 25px; margin-top: 34px; padding: 22px 0; border-top: 1px solid var(--cw-border); }
|
|
77
|
+
.atlas-footer h2 { margin: 0; font-family: Georgia, "Noto Serif SC", serif; font-size: 1rem; }
|
|
78
|
+
.atlas-footer p { margin: 2px 0 0; color: var(--cw-muted); font-size: .75rem; }
|
|
79
|
+
@media (max-width: 760px) { .atlas-toolbar { position: static; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--cw-border); } .atlas-search { grid-column: 1 / -1; } .atlas-grid { grid-template-columns: 1fr; } }
|
|
80
|
+
@media (max-width: 560px) { .atlas-header { align-items: start; flex-direction: column; } .atlas-toolbar label { border-bottom: 1px solid var(--cw-border); } .atlas-footer { align-items: start; flex-direction: column; } }
|
|
81
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: home
|
|
3
|
+
title: __COCOWIKI_SITE_NAME__
|
|
4
|
+
description: 一个由 Markdown、Vue 和静态数据组成的轻量资料站示例
|
|
5
|
+
search: false
|
|
6
|
+
hero:
|
|
7
|
+
eyebrow: SEARCH-FIRST KNOWLEDGE BASE
|
|
8
|
+
name: __COCOWIKI_SITE_NAME__
|
|
9
|
+
text: 让知识自然生长。
|
|
10
|
+
tagline: 把散落的故事,慢慢收进这里。
|
|
11
|
+
search:
|
|
12
|
+
placeholder: 搜索人物、设定或任何关键词…
|
|
13
|
+
actions:
|
|
14
|
+
- theme: brand
|
|
15
|
+
text: 开始探索
|
|
16
|
+
link: /welcome
|
|
17
|
+
- theme: alt
|
|
18
|
+
text: 浏览归档
|
|
19
|
+
link: /archive
|
|
20
|
+
note: 为小型 Wiki、世界观设定集与资料归档而设计。
|
|
21
|
+
---
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 欢迎使用 CoCoWiki
|
|
3
|
+
description: 把散落的故事,慢慢收进这里。
|
|
4
|
+
type: guide
|
|
5
|
+
category: 使用指南
|
|
6
|
+
tags:
|
|
7
|
+
- CoCoWiki
|
|
8
|
+
- Markdown
|
|
9
|
+
- Vue
|
|
10
|
+
contributors:
|
|
11
|
+
- 皙折
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# 欢迎使用 CoCoWiki
|
|
15
|
+
|
|
16
|
+
**CoCoWiki 是一个基于 VitePress 深度封装的轻量静态 Wiki 框架。**
|
|
17
|
+
|
|
18
|
+
它面向小型 Wiki、世界观资料站、设定集和资料归档站。你主要负责写 Markdown、Vue 组件和静态数据,CoCoWiki 负责路由、主题、搜索、归档与静态构建。
|
|
19
|
+
|
|
20
|
+
CoCoWiki 不要求内容拥有完整目录或固定阅读顺序,因此尤其适合碎片内容较多、词条类型复杂的资料库。访问者不必沿着目录逐页阅读,而是通过全站搜索直接找到需要的内容。
|
|
21
|
+
|
|
22
|
+
## 三种页面形式
|
|
23
|
+
|
|
24
|
+
| 页面形式 | 适合内容 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| 普通 Markdown | 人物、地点、概念、说明文档 |
|
|
27
|
+
| Markdown + Vue | 在文章中嵌入图表、列表或交互组件 |
|
|
28
|
+
| 纯 Vue 页面 | 图鉴、时间线、关系图和复杂筛选页面 |
|
|
29
|
+
|
|
30
|
+
当前页面是普通 Markdown 页面;Markdown 中也可以直接使用 `components/` 中自动注册的 Vue 组件。[[组件图鉴]] 则是一张从 `.page.vue` 生成的纯 Vue 页面。
|
|
31
|
+
|
|
32
|
+
## 内容与 Frontmatter
|
|
33
|
+
|
|
34
|
+
页面元信息写在 Markdown 顶部的 Frontmatter 中。标题、描述、分类、标签、别名和贡献者会自动用于内容页、搜索、归档和贡献统计。
|
|
35
|
+
|
|
36
|
+
```md
|
|
37
|
+
---
|
|
38
|
+
title: 示例词条
|
|
39
|
+
description: 用一句话介绍当前内容
|
|
40
|
+
category: 世界观
|
|
41
|
+
tags: [设定, 示例]
|
|
42
|
+
aliases: [另一个名字]
|
|
43
|
+
contributors: [Mueo]
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# 示例词条
|
|
47
|
+
|
|
48
|
+
正文从这里开始。
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 搜索与归档
|
|
52
|
+
|
|
53
|
+
搜索索引在构建期从 Frontmatter 与正文生成,可以检索标题、描述、别名、标签、贡献者和正文,不需要服务器。归档页默认汇总全部内容页面,并按照分类展示。
|
|
54
|
+
|
|
55
|
+
## Markdown 扩展
|
|
56
|
+
|
|
57
|
+
标准 Markdown 可以照常使用,此外还提供少量适合 Wiki 的扩展:
|
|
58
|
+
|
|
59
|
+
- 使用双方括号创建站内链接,例如 `[[组件图鉴]]`。
|
|
60
|
+
- 使用双竖线隐藏剧透内容。
|
|
61
|
+
- 使用 `info`、`tip`、`warning`、`danger` 和 `details` 容器强调不同信息。
|
|
62
|
+
|
|
63
|
+
||这是一段可点击显示的剧透,用来验证桌面端与移动端交互。||
|
|
64
|
+
|
|
65
|
+
:::tip 搜索优先
|
|
66
|
+
面对无需按顺序阅读的碎片化资料,先搜索关键词通常比展开多级目录更直接。
|
|
67
|
+
:::
|
|
68
|
+
|
|
69
|
+
:::warning 构建期优先
|
|
70
|
+
能在构建期完成的索引、路由和页面生成,不会被放到运行时重复处理。
|
|
71
|
+
:::
|
|
72
|
+
|
|
73
|
+
## 主题与静态部署
|
|
74
|
+
|
|
75
|
+
默认主题支持 Light、Dark 和 System 三种模式,包含响应式导航、移动端布局、内容目录以及可配置的前后页导航。Markdown 页默认显示右侧目录,可以通过 `content.outline` 全局设置,也可以在单页 Frontmatter 中用 `outline: false` 关闭;纯 Vue 页面不会自动生成目录。
|
|
76
|
+
|
|
77
|
+
构建结果是纯 HTML、CSS、JavaScript 和静态资源,可部署到 GitHub Pages、Cloudflare Pages、Vercel、Netlify 或 Nginx。
|
|
78
|
+
|
|
79
|
+
## 开始使用
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pnpm create cocowiki my-wiki
|
|
83
|
+
cd my-wiki
|
|
84
|
+
pnpm install
|
|
85
|
+
pnpm dev
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
之后只需要在 `content/` 中写 Markdown、在 `components/` 中添加 Vue 组件,或在 `data/` 中维护 JSON / TypeScript 数据。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "content-index",
|
|
4
|
+
"name": "内容索引",
|
|
5
|
+
"rarity": "core",
|
|
6
|
+
"category": "data",
|
|
7
|
+
"description": "在构建期从 Markdown 与 Frontmatter 中整理出的搜索数据。",
|
|
8
|
+
"contributors": ["杰登"]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "page-state",
|
|
12
|
+
"name": "页面状态",
|
|
13
|
+
"rarity": "stable",
|
|
14
|
+
"category": "logic",
|
|
15
|
+
"description": "筛选、排序和主题模式使用的轻量客户端状态。",
|
|
16
|
+
"contributors": ["卡卡"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "search-panel",
|
|
20
|
+
"name": "搜索面板",
|
|
21
|
+
"rarity": "stable",
|
|
22
|
+
"category": "interface",
|
|
23
|
+
"description": "能够通过键盘或导航快速打开的全站检索入口。",
|
|
24
|
+
"contributors": ["皙折"]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "vue-page",
|
|
28
|
+
"name": "Vue 专属页",
|
|
29
|
+
"rarity": "extended",
|
|
30
|
+
"category": "interface",
|
|
31
|
+
"description": "以 .page.vue 约定创建的纯 Vue 功能页面。",
|
|
32
|
+
"contributors": ["皙折", "卡卡"]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cocowiki-site",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "cocowiki dev",
|
|
8
|
+
"build": "cocowiki build",
|
|
9
|
+
"preview": "cocowiki preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"cocowiki": "^0.2.2",
|
|
13
|
+
"vitepress": "^1.6.4",
|
|
14
|
+
"vue": "^3.5.42"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
Binary file
|
|
Binary file
|