diff --git a/MANIFEST.json b/MANIFEST.json index 9a95e84..ee2c761 100644 --- a/MANIFEST.json +++ b/MANIFEST.json @@ -4,13 +4,13 @@ "summary": "技能目录站:把对外发布的技能生成一个静态站(能干什么 / 先装什么 / 要配什么 / 依赖谁 / 一条安装命令),生成物不手改页面。", "tier": 1, "status": "stable", - "version": "5da1a0f", + "version": "f7a6763", "source": { "path": "skills/skill-catalog", - "commit": "5da1a0f", - "describe": "5da1a0f", + "commit": "f7a6763", + "describe": "f7a6763", "dirty": false, - "packed_at": "2026-10-02T01:27:14.099Z" + "packed_at": "2026-10-02T01:30:47.222Z" }, "platforms": [ "darwin", @@ -174,17 +174,22 @@ { "path": "VERSION", "bytes": 6, - "sha256": "e9dd8507f4bf0c6f" + "sha256": "80447316529fc620" }, { "path": "assets/app.js", - "bytes": 3114, - "sha256": "bfb8b03ff9d4b971" + "bytes": 4601, + "sha256": "78a507c30e6c9cf9" + }, + { + "path": "assets/favicon.svg", + "bytes": 235, + "sha256": "dc255fa0fe62baca" }, { "path": "assets/style.css", - "bytes": 16162, - "sha256": "16217b36cb3db39d" + "bytes": 16997, + "sha256": "dfe35d419987cc81" }, { "path": "contract.lock.json", @@ -193,8 +198,8 @@ }, { "path": "interface.json", - "bytes": 2783, - "sha256": "d413b130d1140cfd" + "bytes": 2780, + "sha256": "1417b2ba9c473218" }, { "path": "scripts/setup-hosting.sh", @@ -203,8 +208,8 @@ }, { "path": "scripts/skill-catalog.mjs", - "bytes": 36074, - "sha256": "d97ba74c71008450" + "bytes": 37551, + "sha256": "7bdd12c1aeea89c5" } ], "leak_scan": { diff --git a/README.md b/README.md index 84a2e4a..79feb9b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## 安装 ```sh -pi install git:gitea.vhkd.top/geekinney/skill-catalog.git@v0.1.0 +pi install git:gitea.vhkd.top/pi-hub/skill-catalog.git@v0.1.1 ``` 装完 `pi-skill list` 能看到 `skill-catalog`,`pi-skill skill-catalog check` 会告诉还缺什么。 diff --git a/package.json b/package.json index c56aebf..79e812f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { "name": "skill-catalog", - "version": "0.1.0", + "version": "0.1.1", "description": "技能目录站:把对外发布的技能生成一个静态站(能干什么 / 先装什么 / 要配什么 / 依赖谁 / 一条安装命令),生成物不手改页面。" } diff --git a/skills/skill-catalog/VERSION b/skills/skill-catalog/VERSION index 6e8bf73..17e51c3 100644 --- a/skills/skill-catalog/VERSION +++ b/skills/skill-catalog/VERSION @@ -1 +1 @@ -0.1.0 +0.1.1 diff --git a/skills/skill-catalog/assets/app.js b/skills/skill-catalog/assets/app.js index 947e4c0..28e8be7 100644 --- a/skills/skill-catalog/assets/app.js +++ b/skills/skill-catalog/assets/app.js @@ -77,5 +77,46 @@ } }); + // 键盘:/ 聚焦搜索,Esc 清空并退出;筛选状态写进 URL(可分享/可回退)。 + document.addEventListener('keydown', event => { + const typing = /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement?.tagName ?? ''); + if (event.key === '/' && !typing) { + event.preventDefault(); + search?.focus(); + search?.select(); + } else if (event.key === 'Escape' && (typing || search?.value)) { + if (search) { + search.value = ''; + apply(); + if (typing) search.blur(); + } + } + }); + + const syncHash = () => { + const hash = activeLayers.size ? `#${[...activeLayers].sort().join(',')}` : ''; + if (location.hash !== hash) history.replaceState(null, '', `${location.pathname}${location.search}${hash}`); + }; + const readHash = () => { + const wanted = location.hash.replace(/^#/, '').split(',').map(s => s.trim()).filter(Boolean); + for (const chip of layerFilters) { + const layer = chip.dataset.layerFilter; + if (wanted.includes(layer)) { + activeLayers.add(layer); + chip.classList.add('active'); + chip.setAttribute('aria-pressed', 'true'); + } + } + }; + for (const chip of layerFilters) { + chip.addEventListener('click', () => { + chip.setAttribute('aria-pressed', String(activeLayers.has(chip.dataset.layerFilter))); + syncHash(); + }); + } + window.addEventListener('hashchange', () => location.reload()); + readHash(); + if (activeLayers.size) apply(); + apply(); })(); diff --git a/skills/skill-catalog/assets/favicon.svg b/skills/skill-catalog/assets/favicon.svg new file mode 100644 index 0000000..a36ea09 --- /dev/null +++ b/skills/skill-catalog/assets/favicon.svg @@ -0,0 +1,4 @@ + + + π + diff --git a/skills/skill-catalog/assets/style.css b/skills/skill-catalog/assets/style.css index 041c4e5..e607ec0 100644 --- a/skills/skill-catalog/assets/style.css +++ b/skills/skill-catalog/assets/style.css @@ -334,3 +334,25 @@ button.chip.active { color: var(--accent); border-color: currentColor; } @media (prefers-reduced-motion: reduce) { * { transition: none !important; } } + + +/* ── 产品细节:静态信息 vs 可点控件要有区分 ───────────── */ +.meta-chip { + font-family: var(--mono); font-size: 11px; letter-spacing: .04em; + color: var(--faint); white-space: nowrap; +} +.meta-chip-warn { color: var(--warn); } +.card-foot .meta-chip { margin-right: 2px; } + +.cta-label { + font-family: var(--mono); font-size: var(--t-xs); letter-spacing: .12em; + text-transform: uppercase; color: var(--faint); margin: 0 0 var(--s-2); +} +.cta-more { font-size: var(--t-sm); color: var(--muted); border-bottom: 1px solid var(--line-2); padding-bottom: 1px; } +.cta-more:hover { color: var(--accent); border-color: currentColor; } + +/* 移动端:只收起文字链接,主题开关必须留着 */ +@media (max-width: 720px) { + .nav-links { gap: 0; } + .nav-links a { display: none; } +} diff --git a/skills/skill-catalog/interface.json b/skills/skill-catalog/interface.json index 936f288..ed1c8d4 100644 --- a/skills/skill-catalog/interface.json +++ b/skills/skill-catalog/interface.json @@ -101,6 +101,6 @@ } ], "publish": { - "package_repo": "https://gitea.vhkd.top/geekinney/skill-catalog.git" + "package_repo": "https://gitea.vhkd.top/pi-hub/skill-catalog.git" } } diff --git a/skills/skill-catalog/scripts/skill-catalog.mjs b/skills/skill-catalog/scripts/skill-catalog.mjs index 4529573..4a369f2 100644 --- a/skills/skill-catalog/scripts/skill-catalog.mjs +++ b/skills/skill-catalog/scripts/skill-catalog.mjs @@ -206,7 +206,7 @@ function siteNav(depth = 0) { π${BRAND.name}${BRAND.scope} -

先从 ${escapeHtml(latest.name)} 试起

` + sample + ? `

安装示例

+
+ ${escapeHtml(sample.install.pi)} + + 看它怎么用 → +
` : '' }
- ${kinds} 个条目 + ${entries.length} 个条目 底座 工具 @@ -458,11 +467,11 @@ function indexPage(entries, siteUrl, fontsCss) {
- -
+ +
${layers .filter(layer => entries.some(entry => entry.layer === layer)) - .map(layer => ``) + .map(layer => ``) .join('')}
${entries.length} @@ -473,7 +482,7 @@ ${sections} `; return pageShell({ - title: 'Pi 能力目录', + title: BRAND.name, description: 'Pi 能力目录:技能与扩展,写清依赖与前置条件,一条命令装好就能用。', body, fontsCss, @@ -481,6 +490,7 @@ ${sections} }); } + /** 取(或首次下载)一套网络字体到 local 缓存;失败返回 { dir: null, error }。 */ export function ensureFont(repo, font) { // 字体缓存是机器级的(与构建哪个仓库无关),跟着 agent 目录走。 @@ -535,6 +545,17 @@ export function buildCatalog({ repo = repoRoot(), out, siteUrl = '' } = {}) { fs.mkdirSync(path.join(outDir, 'assets'), { recursive: true }); fs.cpSync(path.join(SKILL_DIR, 'assets', 'style.css'), path.join(outDir, 'assets', 'style.css')); fs.cpSync(path.join(SKILL_DIR, 'assets', 'app.js'), path.join(outDir, 'assets', 'app.js')); + fs.cpSync(path.join(SKILL_DIR, 'assets', 'favicon.svg'), path.join(outDir, 'assets', 'favicon.svg')); + const siteRoot = (siteUrl || '').replace(/\/$/, ''); + const urls = [`${siteRoot}/`, ...entries.map(entry => `${siteRoot}/skills/${entry.name}.html`)]; + fs.writeFileSync(path.join(outDir, 'robots.txt'), `User-agent: *\nAllow: /\n${siteRoot ? `Sitemap: ${siteRoot}/sitemap.xml\n` : ''}`); + fs.writeFileSync( + path.join(outDir, 'sitemap.xml'), + `\n\n${urls + .filter(url => url.startsWith('http')) + .map(url => ` ${url}`) + .join('\n')}\n\n`, + ); // 中文正文字体(霞鹜文楷 Screen):首次构建下载到 local 缓存,之后直接用; // 拿不到就退回系统字体并 warn(页面仍可用)。 const fontLinks = [];