mirror of
https://github.com/jackwener/OpenCLI.git
synced 2026-09-14 18:25:42 +08:00
5553300597
* feat(linux-do): split topic content into a dedicated command Move the old main-post path out of linux-do topic so topic stays a summarized first-page reader while topic-content becomes the Markdown-focused entrypoint for full post bodies. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * feat(linux-do): update topic content handling to include YAML front matter * fix(linux-do): update default output format to plain for topic-content rendering * fix(linux-do): replace js-yaml with inline YAML serialization for topic-content Adapters must only import node builtins, relative modules, or opencli public APIs. Hand-roll the simple front matter serialization to remove the third-party js-yaml dependency. * fix(linux-do): refine YAML quoting to only escape colons followed by space Colons in URLs (e.g. https://) are valid unquoted YAML values. Only quote when a colon is followed by a space or appears at end of line. --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
63 lines
2.0 KiB
YAML
63 lines
2.0 KiB
YAML
site: linux-do
|
|
name: topic
|
|
description: linux.do 帖子首页摘要和回复(首屏)
|
|
domain: linux.do
|
|
strategy: cookie
|
|
browser: true
|
|
|
|
args:
|
|
id:
|
|
positional: true
|
|
type: int
|
|
required: true
|
|
description: Topic ID
|
|
limit:
|
|
type: int
|
|
default: 20
|
|
description: Number of posts
|
|
|
|
pipeline:
|
|
- navigate: https://linux.do
|
|
|
|
- evaluate: |
|
|
(async () => {
|
|
const toLocalTime = (utcStr) => {
|
|
if (!utcStr) return '';
|
|
const date = new Date(utcStr);
|
|
return Number.isNaN(date.getTime()) ? utcStr : date.toLocaleString();
|
|
};
|
|
const res = await fetch('/t/${{ args.id }}.json', { credentials: 'include' });
|
|
if (!res.ok) throw new Error('HTTP ' + res.status + ' - 请先登录 linux.do');
|
|
let data;
|
|
try { data = await res.json(); } catch { throw new Error('响应不是有效 JSON - 请先登录 linux.do'); }
|
|
const strip = (html) => (html || '')
|
|
.replace(/<br\s*\/?>/gi, ' ')
|
|
.replace(/<\/(p|div|li|blockquote|h[1-6])>/gi, ' ')
|
|
.replace(/<[^>]+>/g, '')
|
|
.replace(/ /g, ' ')
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/&#(?:(\d+)|x([0-9a-fA-F]+));/g, (_, dec, hex) => {
|
|
try { return String.fromCodePoint(dec !== undefined ? Number(dec) : parseInt(hex, 16)); } catch { return ''; }
|
|
})
|
|
.replace(/\s+/g, ' ')
|
|
.trim();
|
|
const posts = data?.post_stream?.posts || [];
|
|
return posts.slice(0, ${{ args.limit }}).map(p => ({
|
|
author: p.username,
|
|
content: strip(p.cooked).slice(0, 200),
|
|
likes: p.like_count,
|
|
created_at: toLocalTime(p.created_at),
|
|
}));
|
|
})()
|
|
|
|
- map:
|
|
author: ${{ item.author }}
|
|
content: ${{ item.content }}
|
|
likes: ${{ item.likes }}
|
|
created_at: ${{ item.created_at }}
|
|
|
|
columns: [author, content, likes, created_at]
|