hd-garden 0.3.13 → 0.4.0
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/app/a2/[slug]/page.tsx +61 -0
- package/app/a2/page.tsx +27 -0
- package/app/blog/[...path]/page.tsx +33 -22
- package/app/blog/page.tsx +6 -7
- package/app/columns/[column]/[...path]/page.tsx +33 -25
- package/app/columns/page.tsx +38 -52
- package/app/components/ArticleMeasure.tsx +95 -0
- package/app/components/ArticleTitle.tsx +20 -0
- package/app/components/BlogArchive.tsx +106 -102
- package/app/components/MarkdownArticle.tsx +145 -66
- package/app/components/MermaidDiagram.tsx +44 -71
- package/app/components/SiteFooter.tsx +3 -7
- package/app/components/SiteHeader.tsx +55 -41
- package/app/components/TableOfContents.tsx +3 -2
- package/app/components/TagIndex.tsx +97 -0
- package/app/components/garden/GardenBlock.tsx +45 -0
- package/app/components/garden/blocks.tsx +530 -0
- package/app/components/garden/chrome.tsx +350 -0
- package/app/components/garden/sandbox-message.ts +16 -0
- package/app/garden-modules.d.ts +2 -0
- package/app/globals.css +17 -12
- package/app/layout.tsx +9 -0
- package/app/lib/a2-meta.ts +22 -0
- package/app/lib/a2-preview.ts +50 -0
- package/app/lib/content.ts +48 -5
- package/app/lib/markdown-plugins.ts +2 -0
- package/app/lib/remark-a2.mjs +208 -0
- package/app/lib/remark-garden.mjs +88 -0
- package/app/page.tsx +122 -93
- package/app/styles/a2.css +1383 -0
- package/app/styles/shell.css +438 -0
- package/app/styles/tokens.css +111 -0
- package/app/tags/page.tsx +28 -0
- package/app/ui-parity/page.tsx +3 -2
- package/package.json +1 -1
- package/scripts/build-content.mjs +11 -1
- package/scripts/check-post.mjs +18 -4
- package/scripts/new-post.mjs +3 -0
- package/site.config.yaml +1 -1
- package/templates/garden-blocks.md +128 -0
- package/templates/garden-snippets.plist +121 -0
- package/ui/garden/catalog.mjs +196 -0
- package/ui/garden/check.mjs +103 -0
- package/ui/garden/enhance.mjs +89 -0
- package/ui/garden/parse.mjs +198 -0
- package/ui/garden/snippets.mjs +109 -0
- package/ui/garden/title.mjs +37 -0
- package/ui/garden/word-count.mjs +266 -0
- package/ui/host.mjs +45 -28
- package/ui/parity-fixtures.mjs +1 -1
- package/ui/preview/dist/garden-ui.css +81 -77
- package/ui/preview/dist/garden-ui.esm.js +124 -89
- package/ui/preview/dist/garden-ui.iife.js +124 -89
- package/ui/prompt/rules.md +17 -1
- package/ui/react/CatalogPage.tsx +12 -0
- package/ui/react/components/display.tsx +1 -1
- package/ui/react/components/media.tsx +2 -2
- package/ui/react/ui.css +81 -77
package/ui/prompt/rules.md
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 把作者的想法编译成 Garden 块
|
|
2
|
+
|
|
3
|
+
文章里只有一种写法:`garden` 围栏。名字只有 card、stat、compare、timeline、chart、figure、html、interactive。裸 `garden` 围栏是作者的想法,发布前编译掉。不要再写 `ui`、`widget`、`embed`、`intent` 或 `garden:名字`。
|
|
4
|
+
|
|
5
|
+
## 只用作者的原文
|
|
6
|
+
|
|
7
|
+
- 只用作者已经写过的句子。不改措辞,不补例子,不编数字。
|
|
8
|
+
- 不写测验,不写「作用」「适用」「特点」「说明」「要点」「互动版」「示例图」「点击」「点按」这类填充标签或过程旁白。
|
|
9
|
+
- 并排格子只放大约 60 字以内的短句。格子里放不下的,留在正文。
|
|
10
|
+
- 不要把连续段落拆成步骤。读者没有状态可以改时,不要做 interactive。
|
|
11
|
+
- 计算器只给复杂公式。一次乘法留在正文里。
|
|
12
|
+
- 保留作者自己的 mermaid。全局概览图保持一整张,不要拆开。
|
|
13
|
+
- 正文已经读得清楚时,不要再套一个组件。
|
|
14
|
+
|
|
15
|
+
interactive 的正文仍用下面的组件和属性。那是 interactive 的内部零件,不是文章里的名字。
|
|
16
|
+
|
|
17
|
+
# 把作者的意图写成 Garden 的 interactive 块
|
|
2
18
|
|
|
3
19
|
你在帮一位技术博客作者,把他用自然语言写下的"这里想让读者动手看看",写成 Garden 站点能直接绘制的 `ui` 块。读者在网页上拖滑杆、翻步骤、点格子,全部在本地计算,不会再调用模型。
|
|
4
20
|
|
package/ui/react/CatalogPage.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { marked } from "marked";
|
|
4
4
|
import { useMemo, useState, useSyncExternalStore } from "react";
|
|
5
5
|
import { COMPONENTS, GROUPS } from "../core/catalog.mjs";
|
|
6
|
+
import { CATALOG, GARDEN_NAMES, IDEA } from "../garden/catalog.mjs";
|
|
6
7
|
import { compileUiBlock } from "../core/compile.mjs";
|
|
7
8
|
import { DEMOS, demoFence } from "../core/demos.mjs";
|
|
8
9
|
import { scanFences } from "../core/fence.mjs";
|
|
@@ -149,6 +150,17 @@ export function CatalogPage({ recipes = [], onStart }: { recipes?: RecipeSource[
|
|
|
149
150
|
|
|
150
151
|
return (
|
|
151
152
|
<div className="garden-catalog">
|
|
153
|
+
<section className="garden-author-catalog">
|
|
154
|
+
<h2>写作块</h2>
|
|
155
|
+
<p>文章里只写 <code>garden</code> 围栏。下面是名字。再往下的清单是 interactive 的内部零件,不是文章里的名字。</p>
|
|
156
|
+
<ul>
|
|
157
|
+
<li><code>garden</code> · {IDEA.label}。{IDEA.when}</li>
|
|
158
|
+
{GARDEN_NAMES.map((name) => {
|
|
159
|
+
const spec = CATALOG[name as keyof typeof CATALOG];
|
|
160
|
+
return <li key={name}><code>garden {name}</code> · {spec.label}。{spec.when}</li>;
|
|
161
|
+
})}
|
|
162
|
+
</ul>
|
|
163
|
+
</section>
|
|
152
164
|
<nav className="garden-catalog-nav" aria-label="大类">
|
|
153
165
|
<input type="search" placeholder="搜索" value={query} onChange={(event) => setQuery(event.target.value)} aria-label="搜索组件" />
|
|
154
166
|
{categories.map((name) => (
|
|
@@ -282,7 +282,7 @@ function Cite({ node, env }: { node: UiNode; env: Env }) {
|
|
|
282
282
|
const icon = href ? faviconSrc(href) : null;
|
|
283
283
|
const body = (
|
|
284
284
|
<>
|
|
285
|
-
{icon ? <
|
|
285
|
+
{icon ? <span className="garden-ui-cite-icon" aria-hidden="true" style={{ backgroundImage: `url("${icon}")` }} /> : null}
|
|
286
286
|
{label}
|
|
287
287
|
</>
|
|
288
288
|
);
|
|
@@ -97,8 +97,8 @@ let mermaidQueue: Promise<unknown> = Promise.resolve();
|
|
|
97
97
|
|
|
98
98
|
const MERMAID_FONT = 'ui-sans-serif, -apple-system, system-ui, "Segoe UI", Helvetica, Arial, "PingFang SC", sans-serif';
|
|
99
99
|
const MERMAID_THEMES = {
|
|
100
|
-
light: { background: "#
|
|
101
|
-
dark: { background: "#
|
|
100
|
+
light: { background: "#F8F7F3", primaryColor: "#FFFFFF", primaryBorderColor: "#D6D2C9", primaryTextColor: "#1B1A18", lineColor: "#6E6B64", secondaryColor: "#F0EEE8", tertiaryColor: "#F0EEE8", fontSize: "14px" },
|
|
101
|
+
dark: { background: "#161513", primaryColor: "#1E1D1A", primaryBorderColor: "#45423C", primaryTextColor: "#EEECE7", lineColor: "#A09B91", secondaryColor: "#22211D", tertiaryColor: "#22211D", fontSize: "14px" },
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
function renderMermaid(source: string, id: string, dark: boolean) {
|
package/ui/react/ui.css
CHANGED
|
@@ -6,41 +6,41 @@
|
|
|
6
6
|
.garden-ui,
|
|
7
7
|
.garden-catalog,
|
|
8
8
|
.garden-ui-preview {
|
|
9
|
-
--gui-bg: #fff;
|
|
10
|
-
--gui-chart:
|
|
11
|
-
--gui-track: #
|
|
12
|
-
--gui-thumb: #fff;
|
|
13
|
-
--gui-slider-track: #
|
|
14
|
-
--gui-slider-thumb: #
|
|
15
|
-
--gui-text: #
|
|
16
|
-
--gui-muted: #
|
|
17
|
-
--gui-subtle: #
|
|
18
|
-
--gui-completed: #
|
|
19
|
-
--gui-border: #
|
|
20
|
-
--gui-border-soft: #
|
|
21
|
-
--gui-border-strong: #
|
|
22
|
-
--gui-control-border: #
|
|
23
|
-
--gui-check-border: #
|
|
24
|
-
--gui-control-bg: #fff;
|
|
25
|
-
--gui-surface: #
|
|
26
|
-
--gui-chip: #
|
|
27
|
-
--gui-hover: #
|
|
28
|
-
--gui-solid: #
|
|
29
|
-
--gui-solid-hover: #
|
|
30
|
-
--gui-on-solid: #
|
|
31
|
-
--gui-segment: #
|
|
32
|
-
--gui-segment-selected: #fff;
|
|
33
|
-
--gui-segment-shadow:
|
|
34
|
-
--gui-progress: #
|
|
35
|
-
--gui-progress-track: #
|
|
36
|
-
--gui-focus: #
|
|
37
|
-
--gui-bubble: #
|
|
38
|
-
--gui-popover-border: #
|
|
39
|
-
--gui-shadow:
|
|
40
|
-
--gui-code-bg: #
|
|
41
|
-
--gui-accent: #
|
|
42
|
-
--gui-series-plain: #
|
|
43
|
-
--gui-series-accent:
|
|
9
|
+
--gui-bg: var(--card, #fff);
|
|
10
|
+
--gui-chart: var(--well);
|
|
11
|
+
--gui-track: var(--rule, #e6e3dc);
|
|
12
|
+
--gui-thumb: var(--card, #fff);
|
|
13
|
+
--gui-slider-track: var(--rule, #e6e3dc);
|
|
14
|
+
--gui-slider-thumb: var(--ink, #1b1a18);
|
|
15
|
+
--gui-text: var(--ink, #1b1a18);
|
|
16
|
+
--gui-muted: var(--muted, #6e6b64);
|
|
17
|
+
--gui-subtle: var(--grey, #737069);
|
|
18
|
+
--gui-completed: var(--muted, #6e6b64);
|
|
19
|
+
--gui-border: var(--rule, #e6e3dc);
|
|
20
|
+
--gui-border-soft: var(--rule, #e6e3dc);
|
|
21
|
+
--gui-border-strong: var(--rule-strong, #d6d2c9);
|
|
22
|
+
--gui-control-border: var(--rule-strong, #d6d2c9);
|
|
23
|
+
--gui-check-border: var(--rule-strong, #d6d2c9);
|
|
24
|
+
--gui-control-bg: var(--card, #fff);
|
|
25
|
+
--gui-surface: var(--well, #f0eee8);
|
|
26
|
+
--gui-chip: var(--well, #f0eee8);
|
|
27
|
+
--gui-hover: var(--well, #f0eee8);
|
|
28
|
+
--gui-solid: var(--ink, #1b1a18);
|
|
29
|
+
--gui-solid-hover: var(--soft, #4a4844);
|
|
30
|
+
--gui-on-solid: var(--paper, #f8f7f3);
|
|
31
|
+
--gui-segment: var(--well, #f0eee8);
|
|
32
|
+
--gui-segment-selected: var(--card, #fff);
|
|
33
|
+
--gui-segment-shadow: none;
|
|
34
|
+
--gui-progress: var(--blue, #2c55b4);
|
|
35
|
+
--gui-progress-track: var(--well, #f0eee8);
|
|
36
|
+
--gui-focus: var(--blue, #2c55b4);
|
|
37
|
+
--gui-bubble: var(--blue-tint, #eaf0fc);
|
|
38
|
+
--gui-popover-border: var(--rule, #e6e3dc);
|
|
39
|
+
--gui-shadow: none;
|
|
40
|
+
--gui-code-bg: var(--well, #f0eee8);
|
|
41
|
+
--gui-accent: var(--blue, #2c55b4);
|
|
42
|
+
--gui-series-plain: var(--ink, #1b1a18);
|
|
43
|
+
--gui-series-accent: var(--blue);
|
|
44
44
|
--gui-series-new: #00a240;
|
|
45
45
|
--gui-series-waste: #e02e2a;
|
|
46
46
|
--gui-series-same: #924ff7;
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
--gui-discovery: #924ff7;
|
|
57
57
|
--gui-discovery-text: #8046d9;
|
|
58
58
|
--gui-discovery-soft: #924ff71a;
|
|
59
|
-
--gui-font:
|
|
59
|
+
--gui-font: var(--sans, -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", sans-serif);
|
|
60
60
|
--gui-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -67,40 +67,41 @@
|
|
|
67
67
|
.garden-ui[data-theme="dark"],
|
|
68
68
|
.garden-catalog[data-theme="dark"],
|
|
69
69
|
.garden-ui-preview[data-theme="dark"] {
|
|
70
|
-
--gui-bg:
|
|
71
|
-
--gui-chart:
|
|
72
|
-
--gui-text:
|
|
73
|
-
--gui-muted:
|
|
74
|
-
--gui-subtle:
|
|
75
|
-
--gui-completed:
|
|
76
|
-
--gui-border:
|
|
77
|
-
--gui-border-soft:
|
|
78
|
-
--gui-border-strong:
|
|
79
|
-
--gui-control-border:
|
|
80
|
-
--gui-check-border:
|
|
81
|
-
--gui-control-bg:
|
|
82
|
-
--gui-surface:
|
|
83
|
-
--gui-chip:
|
|
84
|
-
--gui-hover:
|
|
85
|
-
--gui-solid:
|
|
86
|
-
--gui-solid-hover:
|
|
87
|
-
--gui-on-solid:
|
|
88
|
-
--gui-segment:
|
|
89
|
-
--gui-segment-selected:
|
|
70
|
+
--gui-bg: var(--card);
|
|
71
|
+
--gui-chart: var(--well);
|
|
72
|
+
--gui-text: var(--ink);
|
|
73
|
+
--gui-muted: var(--muted);
|
|
74
|
+
--gui-subtle: var(--grey);
|
|
75
|
+
--gui-completed: var(--muted);
|
|
76
|
+
--gui-border: var(--rule);
|
|
77
|
+
--gui-border-soft: var(--rule);
|
|
78
|
+
--gui-border-strong: var(--rule-strong);
|
|
79
|
+
--gui-control-border: var(--rule-strong);
|
|
80
|
+
--gui-check-border: var(--rule-strong);
|
|
81
|
+
--gui-control-bg: var(--card);
|
|
82
|
+
--gui-surface: var(--well);
|
|
83
|
+
--gui-chip: var(--well);
|
|
84
|
+
--gui-hover: var(--tint);
|
|
85
|
+
--gui-solid: var(--ink);
|
|
86
|
+
--gui-solid-hover: var(--soft);
|
|
87
|
+
--gui-on-solid: var(--paper);
|
|
88
|
+
--gui-segment: var(--well);
|
|
89
|
+
--gui-segment-selected: var(--card);
|
|
90
90
|
--gui-segment-shadow: none;
|
|
91
|
-
--gui-track:
|
|
92
|
-
--gui-thumb:
|
|
93
|
-
--gui-slider-track:
|
|
94
|
-
--gui-slider-thumb:
|
|
95
|
-
--gui-progress:
|
|
96
|
-
--gui-progress-track:
|
|
97
|
-
--gui-focus:
|
|
98
|
-
--gui-bubble:
|
|
99
|
-
--gui-popover-border:
|
|
100
|
-
--gui-shadow:
|
|
101
|
-
--gui-code-bg:
|
|
102
|
-
--gui-accent:
|
|
103
|
-
--gui-series-plain:
|
|
91
|
+
--gui-track: var(--rule);
|
|
92
|
+
--gui-thumb: var(--card);
|
|
93
|
+
--gui-slider-track: var(--rule-strong);
|
|
94
|
+
--gui-slider-thumb: var(--ink);
|
|
95
|
+
--gui-progress: var(--blue);
|
|
96
|
+
--gui-progress-track: var(--well);
|
|
97
|
+
--gui-focus: var(--blue);
|
|
98
|
+
--gui-bubble: var(--blue-tint);
|
|
99
|
+
--gui-popover-border: var(--rule);
|
|
100
|
+
--gui-shadow: none;
|
|
101
|
+
--gui-code-bg: var(--well);
|
|
102
|
+
--gui-accent: var(--blue);
|
|
103
|
+
--gui-series-plain: var(--ink);
|
|
104
|
+
--gui-series-accent: var(--blue);
|
|
104
105
|
--gui-series-new: #04b84c;
|
|
105
106
|
--gui-series-waste: #fa423e;
|
|
106
107
|
--gui-info: #0285ff;
|
|
@@ -919,13 +920,14 @@
|
|
|
919
920
|
line-height: 1.3 !important;
|
|
920
921
|
letter-spacing: normal !important;
|
|
921
922
|
}
|
|
922
|
-
.
|
|
923
|
-
.garden-ui-diagram-canvas .garden-ui-diagram-on
|
|
924
|
-
.garden-ui-diagram-canvas .garden-ui-diagram-on
|
|
925
|
-
.garden-ui-diagram-canvas
|
|
926
|
-
.garden-ui-diagram-canvas .garden-ui-diagram-on
|
|
927
|
-
.garden-ui-diagram-canvas .garden-ui-diagram-on text
|
|
928
|
-
.garden-ui-diagram-canvas
|
|
923
|
+
/* Selected nodes keep the 「全部」 look, text included. Only the rest fades. */
|
|
924
|
+
.garden-ui-diagram-canvas:has(.garden-ui-diagram-on) .node:not(.garden-ui-diagram-on),
|
|
925
|
+
.garden-ui-diagram-canvas:has(.garden-ui-diagram-on) .statediagram-state:not(.garden-ui-diagram-on),
|
|
926
|
+
.garden-ui-diagram-canvas:has(.garden-ui-diagram-on) .cluster:not(.garden-ui-diagram-on) { opacity: 0.22; }
|
|
927
|
+
.garden-ui-diagram-canvas .garden-ui-diagram-on,
|
|
928
|
+
.garden-ui-diagram-canvas .garden-ui-diagram-on text,
|
|
929
|
+
.garden-ui-diagram-canvas .garden-ui-diagram-on .nodeLabel { opacity: 1; }
|
|
930
|
+
.garden-ui-diagram-canvas path.garden-ui-diagram-on { stroke: var(--gui-accent); stroke-width: 2px; }
|
|
929
931
|
|
|
930
932
|
.garden-ui-sandbox {
|
|
931
933
|
display: block;
|
|
@@ -1131,7 +1133,9 @@
|
|
|
1131
1133
|
position: relative;
|
|
1132
1134
|
top: -2px;
|
|
1133
1135
|
}
|
|
1134
|
-
.garden-ui-cite img
|
|
1136
|
+
.garden-ui-cite img,
|
|
1137
|
+
.garden-ui-cite-icon { width: 12px; height: 12px; border-radius: 2px; }
|
|
1138
|
+
.garden-ui-cite-icon { display: inline-block; background-position: center; background-size: contain; background-repeat: no-repeat; vertical-align: -2px; }
|
|
1135
1139
|
|
|
1136
1140
|
.garden-ui-pie { display: flex; flex-direction: column; align-items: stretch; gap: 0; margin: 0; }
|
|
1137
1141
|
.garden-ui-pie-title { align-self: stretch; margin: 0 0 8px; color: var(--gui-text); font-size: 16px; font-weight: 600; line-height: 26px; text-align: start; }
|