[teamai] Push 87 resource(s) from XingfenD
This commit is contained in:
@@ -0,0 +1 @@
|
||||
registry=https://registry.npmjs.org/
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Article, Hero, Lead, Raw } from "reacticle";
|
||||
import { SectionOpening } from "./sections/01-opening";
|
||||
|
||||
// Article.tsx is the ASSEMBLER, owned by the main agent. It imports and orders
|
||||
// Section components — it must NOT contain Section bodies inline.
|
||||
//
|
||||
// 铁律:每个 Section 是独立组件文件(article/sections/NN-*.tsx),坚决不允许把
|
||||
// 多个 Section 直接写进这里。这样多个 Agent 才能并行各写一个 section 文件,主 Agent
|
||||
// 在这里负责合并与稳定性。详见 references/section-build.md。
|
||||
//
|
||||
// width (narrow/regular/wide/full) + toc 在 Plan Checkpoint 确认,与主题解耦
|
||||
// (见 references/layout.md)。
|
||||
export function ArticleDoc() {
|
||||
return (
|
||||
<Article toc width="regular">
|
||||
<Hero
|
||||
title="文章标题"
|
||||
subtitle="副标题:一句话框定这篇要解决什么"
|
||||
meta={[{ label: "日期", value: "2026-06-08" }]}
|
||||
/>
|
||||
<Lead>导语:用一两句话框定主题与读者要带走的判断。</Lead>
|
||||
|
||||
<SectionOpening />
|
||||
{/* 在此按顺序加入更多 section 组件:<SectionContext /> <SectionMechanism /> … */}
|
||||
|
||||
{/*
|
||||
─── Colophon ───
|
||||
每篇 Beautiful Article 必须保留这一段,位置在 </Article> 之前、所有 Section /
|
||||
Conclusion 之后。它是文章的"印记",告诉读者文章是用什么工作流生成的。
|
||||
|
||||
约束:
|
||||
• 不要删除。不要移到 Hero 旁边或浮动到角落。
|
||||
• 文本格式固定:Made with beautiful-article(带链接到 github 仓库)· <主题> theme
|
||||
• 主题名(下方 __THEME__ 占位)由 scaffold 写入;切换主题时同步更新这里和
|
||||
main.tsx 的 <ThemeProvider theme="...">。
|
||||
• 样式只能用 --ra-* token,跟随主题自适应;保持低对比、小字、居中。
|
||||
*/}
|
||||
<Raw title="">
|
||||
<footer
|
||||
style={{
|
||||
marginTop: "var(--ra-space-7, 3rem)",
|
||||
paddingTop: "var(--ra-space-4, 1rem)",
|
||||
borderTop: "1px solid var(--ra-color-border, currentColor)",
|
||||
color: "var(--ra-color-muted, inherit)",
|
||||
fontSize: "var(--ra-text-xs, 0.78rem)",
|
||||
textAlign: "center",
|
||||
letterSpacing: "0.02em",
|
||||
opacity: 0.85,
|
||||
}}
|
||||
>
|
||||
Made with{" "}
|
||||
<a
|
||||
href="https://github.com/ConardLi/garden-skills"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
color: "inherit",
|
||||
textDecoration: "underline",
|
||||
textUnderlineOffset: "0.2em",
|
||||
}}
|
||||
>
|
||||
beautiful-article
|
||||
</a>{" "}
|
||||
· __THEME__ theme
|
||||
</footer>
|
||||
</Raw>
|
||||
</Article>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// Cover.tsx —— 文章封面(独立于 Article,位于 TOC + 正文 + colophon 之上)
|
||||
//
|
||||
// 这一文件是 article-specific 的(跟 Article.tsx / sections/*.tsx 同等地位)。
|
||||
// 主 Agent 在 Phase 4 First Spread 把下面的【封面内容区】替换成按 **主题 + 文章主旨**
|
||||
// 定制的设计。**外壳(3:4 比例、定位、PDF 分页)不要动**。
|
||||
//
|
||||
// 硬约束(详见 references/cover.md):
|
||||
// 1. **3:4 比例固定(屏幕 + PDF)**:不要改 aspectRatio;打印时 .ra-cover 会自动
|
||||
// 独占首页,保持屏幕版 3:4 构图以避免 Chromium print 裁切内部布局。
|
||||
// 让内部元素用百分比 / aspect-ratio / inset 自适应,不要写绝对 px 高度。
|
||||
// 2. **图文并茂**:必须有视觉元素 + 简短文字(标题 + 可选副题 / 小标签)。
|
||||
// **禁止纯文字封面**。视觉用什么技术由你选(见约束 5)。
|
||||
// 3. **主题忠实**:颜色 / 字号 / 字重 / 边框 / 律动**只能用 `--ra-*` token**。
|
||||
// 切主题时封面要跟随刷新;不要写死颜色 / 字体名 / 像素字号。
|
||||
// 4. **内容忠实**:封面的视觉主图与文字要呼应正文主旨(看一眼能猜出文章是讲什么的)。
|
||||
// 5. **技术自由**:内联 SVG / CSS 几何 / Canvas / 复杂 React 组件 / 字体艺术 / 多层
|
||||
// gradient / mask / clip-path / 任意组合 —— 任选,最终效果好就行。**唯一禁止**:
|
||||
// 远程图片(offline-first);base64 raster 仅当 Plan Checkpoint "配图模式" 是
|
||||
// user-assets / ai-generated 才允许。
|
||||
// 6. **封面不承担正文**:不要把 Lead 第一段、TOC、阅读时间塞进来 —— 封面只承担
|
||||
// "识别 + 风格信号 + 引起阅读欲望",正文从下面的 Article 开始。
|
||||
|
||||
export function Cover() {
|
||||
return (
|
||||
<section
|
||||
className="ra-cover"
|
||||
aria-label="文章封面"
|
||||
data-ra-cover=""
|
||||
style={{
|
||||
// ── 外壳(请不要动) ──
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
// 屏幕上像"一本立着的书":限宽 48rem(768px);同时**从视口高度反推宽度**
|
||||
// (100vh - 8rem) * 3/4,确保整个 3:4 封面**一屏看全、不用下拉**。8rem
|
||||
// (128px) 给顶栏 / 边距 / site nav 等留出充足呼吸(典型场景 site nav 60 +
|
||||
// 容器顶 padding 32 + 边框 1 ≈ 93px,仍有 35px 余量)。
|
||||
// 3:4 比例由 aspect-ratio 保证不破。
|
||||
maxWidth: "min(100%, 48rem, calc((100vh - 8rem) * 3 / 4))",
|
||||
margin: "0 auto var(--ra-space-7, 3rem) auto",
|
||||
aspectRatio: "3 / 4",
|
||||
overflow: "hidden",
|
||||
// 背景透明:让外层 .ra-root / .gx-reader 的 --ra-color-bg "纸面色" 直接透上来。
|
||||
// 整片视觉是一张连续的纸,封面不再"自带一块色"。封面的辨识度由内部插画 + 边框
|
||||
// + 内容排版承担。如果你的封面**确实需要**整体着色(如孟菲斯主题大色块覆盖),
|
||||
// 可以改成 surface / surface-2 / accent-soft 等任意主题 token。
|
||||
background: "transparent",
|
||||
color: "var(--ra-color-fg, inherit)",
|
||||
borderRadius: "var(--ra-radius-md, 0)",
|
||||
border: "1px solid var(--ra-color-border, currentColor)",
|
||||
// 让 ::before 之类的几何装饰可以铺满
|
||||
isolation: "isolate",
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
─── 封面内容区 · 在这里写 ───
|
||||
默认占位长这样:
|
||||
• 一层主题感的几何装饰(SVG 网格 + 一个 accent 圆 + 描边斜线)
|
||||
• 居中的占位标题、副题、小标签
|
||||
构建时**替换为按文章 + 主题定制的封面**。占位是为了
|
||||
"即使忘了替换,也不会渲染出一团乱",但**不能交付出去**。
|
||||
*/}
|
||||
<CoverPlaceholder />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────
|
||||
// 占位实现 —— 主 Agent 把 <CoverPlaceholder /> 替换成本文真正的封面。
|
||||
// 删掉这个 function 也行;保留它能让占位回退更友好。
|
||||
// ────────────────────────────────────────────────────────────────────
|
||||
function CoverPlaceholder() {
|
||||
return (
|
||||
<>
|
||||
{/* 默认占位用了 SVG 是图省事,**不代表"应该用 SVG"** —— 你完全可以删掉这个
|
||||
* <svg>,换成 CSS 渐变层、Canvas、复杂 React 组件、字体艺术拼贴等任何能产生
|
||||
* 漂亮视觉的方式。视觉技术由你选,效果好就行。 */}
|
||||
<svg
|
||||
viewBox="0 0 1200 1600"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
aria-hidden="true"
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
color: "var(--ra-color-border, currentColor)",
|
||||
opacity: 0.55,
|
||||
zIndex: 0,
|
||||
}}
|
||||
>
|
||||
<defs>
|
||||
<pattern id="ra-cover-grid" width="80" height="80" patternUnits="userSpaceOnUse">
|
||||
<path
|
||||
d="M 80 0 L 0 0 0 80"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="0.6"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1200" height="1600" fill="url(#ra-cover-grid)" />
|
||||
<circle
|
||||
cx="900"
|
||||
cy="1180"
|
||||
r="220"
|
||||
fill="var(--ra-color-accent, currentColor)"
|
||||
opacity="0.18"
|
||||
/>
|
||||
<line
|
||||
x1="80"
|
||||
y1="1400"
|
||||
x2="560"
|
||||
y2="1400"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
{/* 文字层 */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
zIndex: 1,
|
||||
display: "grid",
|
||||
alignContent: "center",
|
||||
justifyItems: "start",
|
||||
padding:
|
||||
"var(--ra-space-7, 3rem) var(--ra-space-8, 4rem) var(--ra-space-7, 3rem) var(--ra-space-8, 4rem)",
|
||||
gap: "var(--ra-space-3, 0.75rem)",
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "var(--ra-text-xs, 0.75rem)",
|
||||
letterSpacing: "0.22em",
|
||||
textTransform: "uppercase",
|
||||
color: "var(--ra-color-muted, inherit)",
|
||||
opacity: 0.85,
|
||||
}}
|
||||
>
|
||||
COVER · 3 : 4 · 占位
|
||||
</span>
|
||||
<h1
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: "clamp(1.6rem, 4.6vw, var(--ra-text-4xl, 3rem))",
|
||||
lineHeight: 1.05,
|
||||
fontWeight: "var(--ra-font-weight-bold, 700)",
|
||||
color: "var(--ra-color-fg, inherit)",
|
||||
maxWidth: "70%",
|
||||
}}
|
||||
>
|
||||
按文章主旨 + 主题,在此处设计封面
|
||||
</h1>
|
||||
<p
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: "var(--ra-text-sm, 0.95rem)",
|
||||
color: "var(--ra-color-muted, inherit)",
|
||||
maxWidth: "70%",
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
>
|
||||
先读 <code>references/cover.md</code> 与选定主题的 <code>theme-profiles/<id>.md</code>,
|
||||
再替换 <code>CoverPlaceholder</code> 为本文专属的图文构图。视觉用什么技术(SVG /
|
||||
CSS / Canvas / 复杂 React 组件 / 任意混搭)由你选,效果好就行;唯一禁止远程图片。
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { ThemeProvider } from "reacticle";
|
||||
import "reacticle/styles.css";
|
||||
// __COVER_IMPORT_BEGIN__ (scaffold.sh 在 --no-cover 时剥掉这一段,连同标记)
|
||||
import { Cover } from "./Cover";
|
||||
// __COVER_IMPORT_END__
|
||||
import { ArticleDoc } from "./Article";
|
||||
|
||||
// Entry for the self-contained single-file HTML build.
|
||||
// Theme is fixed here — change `theme` (must be a registered reacticle theme id:
|
||||
// "tufte" | "press" | …) to switch the whole look.
|
||||
//
|
||||
// 渲染顺序:Cover(封面,可选)→ ArticleDoc(含 TOC + 正文 + colophon)。
|
||||
// Cover 故意**不**塞进 <Article> 内部(那样会被挤到正文栏旁边),而是和 <ArticleDoc/>
|
||||
// 在 ThemeProvider 下做兄弟,DOM 顺序天然就是「封面 → TOC → 正文 → colophon」。
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<ThemeProvider theme="__THEME__">
|
||||
{/* __COVER_RENDER_BEGIN__ (scaffold.sh 在 --no-cover 时剥掉这一段,连同标记) */}
|
||||
<Cover />
|
||||
{/* __COVER_RENDER_END__ */}
|
||||
<ArticleDoc />
|
||||
</ThemeProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { Section, Aside, Raw } from "reacticle";
|
||||
|
||||
// One Section per file. In parallel builds a single subagent owns this file and
|
||||
// must not touch Article.tsx or other section files. See references/section-build.md.
|
||||
//
|
||||
// Rules of thumb (references/component-policy.md + raw-policy.md):
|
||||
// - Prose is the body. Write paragraphs as <Section> children.
|
||||
// - Semantic components (Aside / Quote / Table / RiskList ...) are accents.
|
||||
// - Raw is freely used but hand-authored for THIS section, token-driven.
|
||||
export function SectionOpening() {
|
||||
return (
|
||||
<Section index="01" title="第一节">
|
||||
<p>正文段落用 children —— 这应是文章主体,尽量多写正文,把背景、推理、结论讲清楚。</p>
|
||||
<p>再写一段,保持阅读节奏。语义组件只在内容确实"是"那个结构时才用。</p>
|
||||
|
||||
<Aside tone="principle" label="核心判断">一句话的核心判断,给本节点睛。</Aside>
|
||||
|
||||
<Raw title="为本段现写的内联 SVG(用主题 token 取色)">
|
||||
<svg viewBox="0 0 240 60" width="100%">
|
||||
<polyline
|
||||
points="0,50 40,42 80,46 120,20 160,28 200,8 240,14"
|
||||
fill="none"
|
||||
stroke="var(--ra-color-accent)"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
</Raw>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Beautiful Article</title>
|
||||
<!-- Theme fonts. tufte falls back to Georgia; press uses Newsreader. -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght@6..72,400;6..72,500&family=Source+Serif+4:opsz,wght@8..60,400&family=JetBrains+Mono:wght@400;500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/article/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "beautiful-article-workspace",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"html": "npm run build && node -e \"require('fs').mkdirSync('article',{recursive:true});require('fs').copyFileSync('dist/index.html','article/article.html');console.log('built article/article.html')\"",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"reacticle": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^5.4.11",
|
||||
"vite-plugin-singlefile": "^2.0.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["article"]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { resolve } from "node:path";
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { viteSingleFile } from "vite-plugin-singlefile";
|
||||
|
||||
// reacticle is consumed from the published npm package (see package.json).
|
||||
// Builds a self-contained single-page HTML (CSS + JS inlined, opens offline)
|
||||
// to dist/index.html. `npm run html` then copies it to article/article.html.
|
||||
export default defineConfig({
|
||||
plugins: [react(), viteSingleFile()],
|
||||
build: {
|
||||
outDir: "dist",
|
||||
emptyOutDir: true,
|
||||
rollupOptions: {
|
||||
input: resolve(__dirname, "index.html"),
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user