hd-garden 0.5.4 → 0.5.5

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.
@@ -5,6 +5,7 @@ import ReactMarkdown from "react-markdown";
5
5
  import { stringify } from "yaml";
6
6
  import { markdownPlugins } from "../../lib/markdown-plugins";
7
7
  import { compileUiBlock } from "../../../ui/core/compile.mjs";
8
+ import { splitCompareLine } from "../../../ui/garden/compare-line.mjs";
8
9
  import { UiErrorCard, UiFigure, type Diagnostic, type UiPayload } from "../../../ui/react";
9
10
  import { FullscreenFrame, SandboxFrame } from "./chrome";
10
11
 
@@ -105,11 +106,27 @@ export function GardenStat({ props }: { props: Record<string, unknown> }) {
105
106
  );
106
107
  }
107
108
 
109
+ function CompareLine({ line }: { line: string }) {
110
+ const split = splitCompareLine(line);
111
+ if (!split) return <p><Rich text={line} /></p>;
112
+ return (
113
+ <p className="g-cmp-line">
114
+ <span className="g-cmp-t"><Rich text={split.title} />{split.separator}</span>
115
+ <Rich text={split.text} />
116
+ </p>
117
+ );
118
+ }
119
+
108
120
  export function GardenCompare({ props }: { props: Record<string, unknown> }) {
121
+ const items = Array.isArray(props.items) ? props.items as unknown[] : [];
109
122
  return (
110
123
  <div className="g-compare" role="group">
111
- {itemsOf(props).map((item, index) => {
112
- const { title, text, ...rest } = item;
124
+ {items.map((entry, index) => {
125
+ if (typeof entry === "string" || typeof entry === "number") {
126
+ return <section className="g-cmp" key={index}><CompareLine line={String(entry)} /></section>;
127
+ }
128
+ if (!entry || typeof entry !== "object") return null;
129
+ const { title, text, ...rest } = entry as Record<string, unknown>;
113
130
  const texts = text == null ? [] : Array.isArray(text) ? text : [text];
114
131
  return (
115
132
  <section className="g-cmp" key={index}>
package/app/styles/a2.css CHANGED
@@ -959,6 +959,28 @@ html[data-theme="dark"] .markdown-body .markdown-alert code {
959
959
  color: var(--ink);
960
960
  }
961
961
 
962
+ /* Cards in one compare block are one group: only the grid gap sits between
963
+ them, and the block keeps the space below it. */
964
+ .g-compare {
965
+ margin: 0 0 1.2em;
966
+ }
967
+
968
+ .g-compare > .g-cmp {
969
+ margin: 0;
970
+ }
971
+
972
+ .g-cmp > :last-child {
973
+ margin-bottom: 0;
974
+ }
975
+
976
+ /* One-line cell 「X:Y」: X sits on its own line like a title, colon kept. */
977
+ .g-cmp .g-cmp-t {
978
+ display: block;
979
+ margin: 0 0 8px;
980
+ font: 600 16px / 1.4 var(--sans);
981
+ color: var(--ink);
982
+ }
983
+
962
984
  .g-cmp p,
963
985
  .g-card p,
964
986
  .g-tl-x {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hd-garden",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "private": false,
5
5
  "description": "用 Markdown 写作、用 GitHub Pages 发布的个人博客引擎。",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@ items:
40
40
 
41
41
  ## compare · 对比
42
42
 
43
- 两三件东西并排,每格大约 60 字以内。
43
+ 两三件东西并排,每格大约 60 字以内。原文是「X:Y」的列表时,每格写成一行带引号的字符串,冒号前是标题,冒号原样显示。
44
44
 
45
45
  不该用:任何一格超过约 60 字时,用原文的列表,不要并排。
46
46
 
@@ -43,7 +43,7 @@ items:
43
43
  },
44
44
  compare: {
45
45
  label: "对比",
46
- when: "两三件东西并排,每格大约 60 字以内。",
46
+ when: "两三件东西并排,每格大约 60 字以内。原文是「X:Y」的列表时,每格写成一行带引号的字符串,冒号前是标题,冒号原样显示。",
47
47
  whenNot: "任何一格超过约 60 字时,用原文的列表,不要并排。",
48
48
  keys: ["items"],
49
49
  itemKeys: ["title", "text"],
@@ -2,10 +2,13 @@ import { CATALOG, suggestName } from "./catalog.mjs";
2
2
  import { isProseSteps, isTrivialInteractive } from "./enhance.mjs";
3
3
  import { blanksBetween, classifyFence, isFullCodeFence, scanFences } from "./parse.mjs";
4
4
  import { splitTitle } from "./title.mjs";
5
+ import { splitCompareLine } from "./compare-line.mjs";
5
6
 
6
7
  const COMPARE_LIMIT = 60;
7
8
 
8
9
  function cellText(item) {
10
+ // A one-line cell 「X:Y」: X is the title, only Y counts toward the length.
11
+ if (typeof item === "string") return splitCompareLine(item)?.text ?? item;
9
12
  if (!item || typeof item !== "object") return "";
10
13
  const parts = [];
11
14
  if (typeof item.text === "string") parts.push(item.text);
@@ -0,0 +1,82 @@
1
+ // A compare cell written as one line, 「X:Y」 or "X: Y". X is the title and Y
2
+ // the text. The split is at the first full-width colon, or a colon followed by
3
+ // a space, that is not inside inline code, link text or a link URL. The
4
+ // separator and any space after it are returned as written, so
5
+ // title + separator + text always equals the original line.
6
+
7
+ // End of a backtick code span starting at `start`, or -1 when it never closes.
8
+ function codeSpanEnd(line, start) {
9
+ let run = 0;
10
+ while (line[start + run] === "`") run += 1;
11
+ const fence = "`".repeat(run);
12
+ let at = start + run;
13
+ while (at < line.length) {
14
+ const next = line.indexOf(fence, at);
15
+ if (next < 0) return -1;
16
+ let close = 0;
17
+ while (line[next + close] === "`") close += 1;
18
+ if (close === run) return next + run;
19
+ at = next + close;
20
+ }
21
+ return -1;
22
+ }
23
+
24
+ // End of a bracketed run `[...]` or `(...)` starting at `start`, honouring
25
+ // nesting, escapes and code spans; -1 when it never closes.
26
+ function groupEnd(line, start, open, close) {
27
+ let depth = 0;
28
+ for (let at = start; at < line.length; at += 1) {
29
+ const char = line[at];
30
+ if (char === "\\") { at += 1; continue; }
31
+ if (char === "`") {
32
+ const end = codeSpanEnd(line, at);
33
+ if (end > 0) { at = end - 1; continue; }
34
+ }
35
+ if (char === open) depth += 1;
36
+ else if (char === close) {
37
+ depth -= 1;
38
+ if (depth === 0) return at + 1;
39
+ }
40
+ }
41
+ return -1;
42
+ }
43
+
44
+ // End of a Markdown link or image `[text](url)` / `[text][ref]` at `start`,
45
+ // or -1 when the brackets are not a link.
46
+ function linkEnd(line, start) {
47
+ const textEnd = groupEnd(line, start, "[", "]");
48
+ if (textEnd < 0) return -1;
49
+ if (line[textEnd] === "(") return groupEnd(line, textEnd, "(", ")");
50
+ if (line[textEnd] === "[") return groupEnd(line, textEnd, "[", "]");
51
+ return -1;
52
+ }
53
+
54
+ /** @param {string} line */
55
+ export function splitCompareLine(line) {
56
+ for (let at = 0; at < line.length; at += 1) {
57
+ const char = line[at];
58
+ if (char === "\\") { at += 1; continue; }
59
+ if (char === "`") {
60
+ const end = codeSpanEnd(line, at);
61
+ if (end > 0) { at = end - 1; continue; }
62
+ continue;
63
+ }
64
+ if (char === "[") {
65
+ const end = linkEnd(line, at);
66
+ if (end > 0) { at = end - 1; continue; }
67
+ continue;
68
+ }
69
+ if (char === "<") {
70
+ // Autolink <https://…>.
71
+ const end = line.indexOf(">", at);
72
+ if (end > 0 && /^<[a-z][a-z0-9+.-]*:[^\s<>]*>$/iu.test(line.slice(at, end + 1))) { at = end; continue; }
73
+ }
74
+ const isSeparator = char === ":" || (char === ":" && line[at + 1] === " ");
75
+ if (!isSeparator || at === 0) continue;
76
+ let end = at + 1;
77
+ while (end < line.length && /\s/u.test(line[end])) end += 1;
78
+ if (end >= line.length) return null;
79
+ return { title: line.slice(0, at), separator: line.slice(at, end), text: line.slice(end) };
80
+ }
81
+ return null;
82
+ }
@@ -305,7 +305,7 @@ ${e}</tr>
305
305
  `}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
306
306
  `}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${lr(e,!0)}</code>`}br(e){return"<br>"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let i=this.parser.parseInline(n),r=Hk(e);if(r===null)return i;e=r;let a='<a href="'+e+'"';return t&&(a+=' title="'+lr(t)+'"'),a+=">"+i+"</a>",a}image({href:e,title:t,text:n,tokens:i}){i&&(n=this.parser.parseInline(i,this.parser.textRenderer));let r=Hk(e);if(r===null)return lr(n);e=r;let a=`<img src="${e}" alt="${n}"`;return t&&(a+=` title="${lr(t)}"`),a+=">",a}text(e){return"tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:lr(e.text)}},ay=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return""+e}image({text:e}){return""+e}br(){return""}},Mi=class Q0{constructor(t){Ze(this,"options");Ze(this,"renderer");Ze(this,"textRenderer");this.options=t||ys,this.options.renderer=this.options.renderer||new Qh,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new ay}static parse(t,n){return new Q0(n).parse(t)}static parseInline(t,n){return new Q0(n).parseInline(t)}parse(t,n=!0){let i="";for(let r=0;r<t.length;r++){let a=t[r];if(this.options.extensions?.renderers?.[a.type]){let l=a,u=this.options.extensions.renderers[l.type].call({parser:this},l);if(u!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(l.type)){i+=u||"";continue}}let s=a;switch(s.type){case"space":{i+=this.renderer.space(s);continue}case"hr":{i+=this.renderer.hr(s);continue}case"heading":{i+=this.renderer.heading(s);continue}case"code":{i+=this.renderer.code(s);continue}case"table":{i+=this.renderer.table(s);continue}case"blockquote":{i+=this.renderer.blockquote(s);continue}case"list":{i+=this.renderer.list(s);continue}case"html":{i+=this.renderer.html(s);continue}case"def":{i+=this.renderer.def(s);continue}case"paragraph":{i+=this.renderer.paragraph(s);continue}case"text":{let l=s,u=this.renderer.text(l);for(;r+1<t.length&&t[r+1].type==="text";)l=t[++r],u+=`
307
307
  `+this.renderer.text(l);n?i+=this.renderer.paragraph({type:"paragraph",raw:u,text:u,tokens:[{type:"text",raw:u,text:u,escaped:!0}]}):i+=u;continue}default:{let l='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(l),"";throw new Error(l)}}}return i}parseInline(t,n=this.renderer){let i="";for(let r=0;r<t.length;r++){let a=t[r];if(this.options.extensions?.renderers?.[a.type]){let l=this.options.extensions.renderers[a.type].call({parser:this},a);if(l!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(a.type)){i+=l||"";continue}}let s=a;switch(s.type){case"escape":{i+=n.text(s);break}case"html":{i+=n.html(s);break}case"link":{i+=n.link(s);break}case"image":{i+=n.image(s);break}case"strong":{i+=n.strong(s);break}case"em":{i+=n.em(s);break}case"codespan":{i+=n.codespan(s);break}case"br":{i+=n.br(s);break}case"del":{i+=n.del(s);break}case"text":{i+=n.text(s);break}default:{let l='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(l),"";throw new Error(l)}}}return i}},Yh,Ro=(Yh=class{constructor(e){Ze(this,"options");Ze(this,"block");this.options=e||ys}preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?Oi.lex:Oi.lexInline}provideParser(){return this.block?Mi.parse:Mi.parseInline}},Ze(Yh,"passThroughHooks",new Set(["preprocess","postprocess","processAllTokens","emStrongMask"])),Ze(Yh,"passThroughHooksRespectAsync",new Set(["preprocess","postprocess","processAllTokens"])),Yh),z4=class{constructor(...e){Ze(this,"defaults",X0());Ze(this,"options",this.setOptions);Ze(this,"parse",this.parseMarkdown(!0));Ze(this,"parseInline",this.parseMarkdown(!1));Ze(this,"Parser",Mi);Ze(this,"Renderer",Qh);Ze(this,"TextRenderer",ay);Ze(this,"Lexer",Oi);Ze(this,"Tokenizer",Kh);Ze(this,"Hooks",Ro);this.use(...e)}walkTokens(e,t){let n=[];for(let i of e)switch(n=n.concat(t.call(this,i)),i.type){case"table":{let r=i;for(let a of r.header)n=n.concat(this.walkTokens(a.tokens,t));for(let a of r.rows)for(let s of a)n=n.concat(this.walkTokens(s.tokens,t));break}case"list":{let r=i;n=n.concat(this.walkTokens(r.items,t));break}default:{let r=i;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(a=>{let s=r[a].flat(1/0);n=n.concat(this.walkTokens(s,t))}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let i={...n};if(i.async=this.defaults.async||i.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let a=t.renderers[r.name];a?t.renderers[r.name]=function(...s){let l=r.renderer.apply(this,s);return l===!1&&(l=a.apply(this,s)),l}:t.renderers[r.name]=r.renderer}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let a=t[r.level];a?a.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level==="block"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level==="inline"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]))}"childTokens"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens)}),i.extensions=t),n.renderer){let r=this.defaults.renderer||new Qh(this.defaults);for(let a in n.renderer){if(!(a in r))throw new Error(`renderer '${a}' does not exist`);if(["options","parser"].includes(a))continue;let s=a,l=n.renderer[s],u=r[s];r[s]=(...o)=>{let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h||""}}i.renderer=r}if(n.tokenizer){let r=this.defaults.tokenizer||new Kh(this.defaults);for(let a in n.tokenizer){if(!(a in r))throw new Error(`tokenizer '${a}' does not exist`);if(["options","rules","lexer"].includes(a))continue;let s=a,l=n.tokenizer[s],u=r[s];r[s]=(...o)=>{let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h}}i.tokenizer=r}if(n.hooks){let r=this.defaults.hooks||new Ro;for(let a in n.hooks){if(!(a in r))throw new Error(`hook '${a}' does not exist`);if(["options","block"].includes(a))continue;let s=a,l=n.hooks[s],u=r[s];Ro.passThroughHooks.has(a)?r[s]=o=>{if(this.defaults.async&&Ro.passThroughHooksRespectAsync.has(a))return(async()=>{let c=await l.call(r,o);return u.call(r,c)})();let h=l.call(r,o);return u.call(r,h)}:r[s]=(...o)=>{if(this.defaults.async)return(async()=>{let c=await l.apply(r,o);return c===!1&&(c=await u.apply(r,o)),c})();let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h}}i.hooks=r}if(n.walkTokens){let r=this.defaults.walkTokens,a=n.walkTokens;i.walkTokens=function(s){let l=[];return l.push(a.call(this,s)),r&&(l=l.concat(r.call(this,s))),l}}this.defaults={...this.defaults,...i}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return Oi.lex(e,t??this.defaults)}parser(e,t){return Mi.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{let i={...n},r={...this.defaults,...i},a=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&i.async===!1)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof t>"u"||t===null)return a(new Error("marked(): input parameter is undefined or null"));if(typeof t!="string")return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));if(r.hooks&&(r.hooks.options=r,r.hooks.block=e),r.async)return(async()=>{let s=r.hooks?await r.hooks.preprocess(t):t,l=await(r.hooks?await r.hooks.provideLexer():e?Oi.lex:Oi.lexInline)(s,r),u=r.hooks?await r.hooks.processAllTokens(l):l;r.walkTokens&&await Promise.all(this.walkTokens(u,r.walkTokens));let o=await(r.hooks?await r.hooks.provideParser():e?Mi.parse:Mi.parseInline)(u,r);return r.hooks?await r.hooks.postprocess(o):o})().catch(a);try{r.hooks&&(t=r.hooks.preprocess(t));let s=(r.hooks?r.hooks.provideLexer():e?Oi.lex:Oi.lexInline)(t,r);r.hooks&&(s=r.hooks.processAllTokens(s)),r.walkTokens&&this.walkTokens(s,r.walkTokens);let l=(r.hooks?r.hooks.provideParser():e?Mi.parse:Mi.parseInline)(s,r);return r.hooks&&(l=r.hooks.postprocess(l)),l}catch(s){return a(s)}}}onError(e,t){return n=>{if(n.message+=`
308
- Please report this to https://github.com/markedjs/marked.`,e){let i="<p>An error occurred:</p><pre>"+lr(n.message+"",!0)+"</pre>";return t?Promise.resolve(i):i}if(t)return Promise.reject(n);throw n}}},gs=new z4;function Ye(e,t){return gs.parse(e,t)}Ye.options=Ye.setOptions=function(e){return gs.setOptions(e),Ye.defaults=gs.defaults,Gk(Ye.defaults),Ye};Ye.getDefaults=X0;Ye.defaults=ys;Ye.use=function(...e){return gs.use(...e),Ye.defaults=gs.defaults,Gk(Ye.defaults),Ye};Ye.walkTokens=function(e,t){return gs.walkTokens(e,t)};Ye.parseInline=gs.parseInline;Ye.Parser=Mi;Ye.parser=Mi.parse;Ye.Renderer=Qh;Ye.TextRenderer=ay;Ye.Lexer=Oi;Ye.lexer=Oi.lex;Ye.Tokenizer=Kh;Ye.Hooks=Ro;Ye.parse=Ye;var uI=Ye.options,oI=Ye.setOptions,cI=Ye.use,fI=Ye.walkTokens,hI=Ye.parseInline;var pI=Mi.parse,dI=Oi.lex;var La=Fe(Yn(),1);var iE=["card","stat","compare","timeline","chart","figure","html","interactive"];var rE={card:{label:"\u8D44\u6E90\u5361",when:"\u4E00\u7BC7\u8BBA\u6587\u3001\u4E00\u4E2A\u4ED3\u5E93\u6216\u4E00\u672C\u4E66\uFF0C\u8BFB\u8005\u9700\u8981\u6807\u9898\u3001\u94FE\u63A5\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6B63\u6587\u91CC\u5DF2\u7ECF\u6709\u8FD9\u53E5\u8BDD\u65F6\uFF0C\u4E0D\u8981\u518D\u5305\u4E00\u5F20\u5361\u3002",keys:["url","title","description","image","alt","points","meta","text","source","site","items"],example:"```garden card\nurl: https://arxiv.org/abs/2309.06180\ntitle: PagedAttention\ndescription: vLLM \u7684\u5206\u9875 KV \u7BA1\u7406\u3002\n```",triggers:["gcard"]},stat:{label:"\u6307\u6807",when:"\u4E00\u4E2A\u77ED\u6307\u6807\uFF1A\u6807\u7B7E\u3001\u6570\u5B57\u3001\u53EF\u9009\u7684\u4E00\u53E5\u8BF4\u660E\u548C\u6765\u6E90\u3002",whenNot:"\u6570\u5B57\u9700\u8981\u8BFB\u8005\u81EA\u5DF1\u4EE3\u5165\u53C2\u6570\u65F6\uFF0C\u5199\u6210\u60F3\u6CD5\uFF0C\u4E0D\u8981\u505A\u9759\u6001\u6307\u6807\u3002",keys:["items","label","value","unit","caption","source","text"],example:"```garden stat\nitems:\n - label: Llama-2-13B \xB7 4K \u4E0A\u4E0B\u6587\n value: 3.2\n unit: GiB\n source: https://arxiv.org/abs/2309.06180\n```",triggers:["gstat"]},compare:{label:"\u5BF9\u6BD4",when:"\u4E24\u4E09\u4EF6\u4E1C\u897F\u5E76\u6392\uFF0C\u6BCF\u683C\u5927\u7EA6 60 \u5B57\u4EE5\u5185\u3002",whenNot:"\u4EFB\u4F55\u4E00\u683C\u8D85\u8FC7\u7EA6 60 \u5B57\u65F6\uFF0C\u7528\u539F\u6587\u7684\u5217\u8868\uFF0C\u4E0D\u8981\u5E76\u6392\u3002",keys:["items"],itemKeys:["title","text"],example:"```garden compare\nitems:\n - title: \u81EA\u65CB\u9501\n text: \u4E34\u754C\u533A\u6781\u77ED\u65F6\u5FD9\u7B49\uFF0C\u4E0D\u8FDB\u5165\u4F11\u7720\u3002\n - title: \u4E92\u65A5\u9501\n text: \u4E89\u7528\u4E45\u5C31\u4F11\u7720\uFF0C\u907F\u514D\u7A7A\u8F6C\u5360\u6EE1 CPU\u3002\n```",triggers:["gcompare"]},timeline:{label:"\u65F6\u95F4\u7EBF",when:"\u7248\u672C\u6F14\u8FDB\u6216\u4E00\u6BB5\u5386\u53F2\uFF0C\u6BCF\u6761\u6709\u65E5\u671F\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6CA1\u6709\u65F6\u95F4\u987A\u5E8F\u65F6\uFF0C\u7528\u666E\u901A\u5217\u8868\u3002",keys:["title","items"],itemKeys:["date","title","text","source"],example:`\`\`\`garden timeline
308
+ Please report this to https://github.com/markedjs/marked.`,e){let i="<p>An error occurred:</p><pre>"+lr(n.message+"",!0)+"</pre>";return t?Promise.resolve(i):i}if(t)return Promise.reject(n);throw n}}},gs=new z4;function Ye(e,t){return gs.parse(e,t)}Ye.options=Ye.setOptions=function(e){return gs.setOptions(e),Ye.defaults=gs.defaults,Gk(Ye.defaults),Ye};Ye.getDefaults=X0;Ye.defaults=ys;Ye.use=function(...e){return gs.use(...e),Ye.defaults=gs.defaults,Gk(Ye.defaults),Ye};Ye.walkTokens=function(e,t){return gs.walkTokens(e,t)};Ye.parseInline=gs.parseInline;Ye.Parser=Mi;Ye.parser=Mi.parse;Ye.Renderer=Qh;Ye.TextRenderer=ay;Ye.Lexer=Oi;Ye.lexer=Oi.lex;Ye.Tokenizer=Kh;Ye.Hooks=Ro;Ye.parse=Ye;var uI=Ye.options,oI=Ye.setOptions,cI=Ye.use,fI=Ye.walkTokens,hI=Ye.parseInline;var pI=Mi.parse,dI=Oi.lex;var La=Fe(Yn(),1);var iE=["card","stat","compare","timeline","chart","figure","html","interactive"];var rE={card:{label:"\u8D44\u6E90\u5361",when:"\u4E00\u7BC7\u8BBA\u6587\u3001\u4E00\u4E2A\u4ED3\u5E93\u6216\u4E00\u672C\u4E66\uFF0C\u8BFB\u8005\u9700\u8981\u6807\u9898\u3001\u94FE\u63A5\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6B63\u6587\u91CC\u5DF2\u7ECF\u6709\u8FD9\u53E5\u8BDD\u65F6\uFF0C\u4E0D\u8981\u518D\u5305\u4E00\u5F20\u5361\u3002",keys:["url","title","description","image","alt","points","meta","text","source","site","items"],example:"```garden card\nurl: https://arxiv.org/abs/2309.06180\ntitle: PagedAttention\ndescription: vLLM \u7684\u5206\u9875 KV \u7BA1\u7406\u3002\n```",triggers:["gcard"]},stat:{label:"\u6307\u6807",when:"\u4E00\u4E2A\u77ED\u6307\u6807\uFF1A\u6807\u7B7E\u3001\u6570\u5B57\u3001\u53EF\u9009\u7684\u4E00\u53E5\u8BF4\u660E\u548C\u6765\u6E90\u3002",whenNot:"\u6570\u5B57\u9700\u8981\u8BFB\u8005\u81EA\u5DF1\u4EE3\u5165\u53C2\u6570\u65F6\uFF0C\u5199\u6210\u60F3\u6CD5\uFF0C\u4E0D\u8981\u505A\u9759\u6001\u6307\u6807\u3002",keys:["items","label","value","unit","caption","source","text"],example:"```garden stat\nitems:\n - label: Llama-2-13B \xB7 4K \u4E0A\u4E0B\u6587\n value: 3.2\n unit: GiB\n source: https://arxiv.org/abs/2309.06180\n```",triggers:["gstat"]},compare:{label:"\u5BF9\u6BD4",when:"\u4E24\u4E09\u4EF6\u4E1C\u897F\u5E76\u6392\uFF0C\u6BCF\u683C\u5927\u7EA6 60 \u5B57\u4EE5\u5185\u3002\u539F\u6587\u662F\u300CX\uFF1AY\u300D\u7684\u5217\u8868\u65F6\uFF0C\u6BCF\u683C\u5199\u6210\u4E00\u884C\u5E26\u5F15\u53F7\u7684\u5B57\u7B26\u4E32\uFF0C\u5192\u53F7\u524D\u662F\u6807\u9898\uFF0C\u5192\u53F7\u539F\u6837\u663E\u793A\u3002",whenNot:"\u4EFB\u4F55\u4E00\u683C\u8D85\u8FC7\u7EA6 60 \u5B57\u65F6\uFF0C\u7528\u539F\u6587\u7684\u5217\u8868\uFF0C\u4E0D\u8981\u5E76\u6392\u3002",keys:["items"],itemKeys:["title","text"],example:"```garden compare\nitems:\n - title: \u81EA\u65CB\u9501\n text: \u4E34\u754C\u533A\u6781\u77ED\u65F6\u5FD9\u7B49\uFF0C\u4E0D\u8FDB\u5165\u4F11\u7720\u3002\n - title: \u4E92\u65A5\u9501\n text: \u4E89\u7528\u4E45\u5C31\u4F11\u7720\uFF0C\u907F\u514D\u7A7A\u8F6C\u5360\u6EE1 CPU\u3002\n```",triggers:["gcompare"]},timeline:{label:"\u65F6\u95F4\u7EBF",when:"\u7248\u672C\u6F14\u8FDB\u6216\u4E00\u6BB5\u5386\u53F2\uFF0C\u6BCF\u6761\u6709\u65E5\u671F\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6CA1\u6709\u65F6\u95F4\u987A\u5E8F\u65F6\uFF0C\u7528\u666E\u901A\u5217\u8868\u3002",keys:["title","items"],itemKeys:["date","title","text","source"],example:`\`\`\`garden timeline
309
309
  items:
310
310
  - date: 2015
311
311
  title: \u5E76\u53D1\u6807\u8BB0
@@ -305,7 +305,7 @@ ${e}</tr>
305
305
  `}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
306
306
  `}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${lr(e,!0)}</code>`}br(e){return"<br>"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let i=this.parser.parseInline(n),r=Fk(e);if(r===null)return i;e=r;let a='<a href="'+e+'"';return t&&(a+=' title="'+lr(t)+'"'),a+=">"+i+"</a>",a}image({href:e,title:t,text:n,tokens:i}){i&&(n=this.parser.parseInline(i,this.parser.textRenderer));let r=Fk(e);if(r===null)return lr(n);e=r;let a=`<img src="${e}" alt="${n}"`;return t&&(a+=` title="${lr(t)}"`),a+=">",a}text(e){return"tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:lr(e.text)}},ay=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return""+e}image({text:e}){return""+e}br(){return""}},Mi=class Q0{constructor(t){Ze(this,"options");Ze(this,"renderer");Ze(this,"textRenderer");this.options=t||ys,this.options.renderer=this.options.renderer||new Xh,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new ay}static parse(t,n){return new Q0(n).parse(t)}static parseInline(t,n){return new Q0(n).parseInline(t)}parse(t,n=!0){let i="";for(let r=0;r<t.length;r++){let a=t[r];if(this.options.extensions?.renderers?.[a.type]){let l=a,u=this.options.extensions.renderers[l.type].call({parser:this},l);if(u!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(l.type)){i+=u||"";continue}}let s=a;switch(s.type){case"space":{i+=this.renderer.space(s);continue}case"hr":{i+=this.renderer.hr(s);continue}case"heading":{i+=this.renderer.heading(s);continue}case"code":{i+=this.renderer.code(s);continue}case"table":{i+=this.renderer.table(s);continue}case"blockquote":{i+=this.renderer.blockquote(s);continue}case"list":{i+=this.renderer.list(s);continue}case"html":{i+=this.renderer.html(s);continue}case"def":{i+=this.renderer.def(s);continue}case"paragraph":{i+=this.renderer.paragraph(s);continue}case"text":{let l=s,u=this.renderer.text(l);for(;r+1<t.length&&t[r+1].type==="text";)l=t[++r],u+=`
307
307
  `+this.renderer.text(l);n?i+=this.renderer.paragraph({type:"paragraph",raw:u,text:u,tokens:[{type:"text",raw:u,text:u,escaped:!0}]}):i+=u;continue}default:{let l='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(l),"";throw new Error(l)}}}return i}parseInline(t,n=this.renderer){let i="";for(let r=0;r<t.length;r++){let a=t[r];if(this.options.extensions?.renderers?.[a.type]){let l=this.options.extensions.renderers[a.type].call({parser:this},a);if(l!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(a.type)){i+=l||"";continue}}let s=a;switch(s.type){case"escape":{i+=n.text(s);break}case"html":{i+=n.html(s);break}case"link":{i+=n.link(s);break}case"image":{i+=n.image(s);break}case"strong":{i+=n.strong(s);break}case"em":{i+=n.em(s);break}case"codespan":{i+=n.codespan(s);break}case"br":{i+=n.br(s);break}case"del":{i+=n.del(s);break}case"text":{i+=n.text(s);break}default:{let l='Token with "'+s.type+'" type was not found.';if(this.options.silent)return console.error(l),"";throw new Error(l)}}}return i}},Jh,zo=(Jh=class{constructor(e){Ze(this,"options");Ze(this,"block");this.options=e||ys}preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?Oi.lex:Oi.lexInline}provideParser(){return this.block?Mi.parse:Mi.parseInline}},Ze(Jh,"passThroughHooks",new Set(["preprocess","postprocess","processAllTokens","emStrongMask"])),Ze(Jh,"passThroughHooksRespectAsync",new Set(["preprocess","postprocess","processAllTokens"])),Jh),U4=class{constructor(...e){Ze(this,"defaults",X0());Ze(this,"options",this.setOptions);Ze(this,"parse",this.parseMarkdown(!0));Ze(this,"parseInline",this.parseMarkdown(!1));Ze(this,"Parser",Mi);Ze(this,"Renderer",Xh);Ze(this,"TextRenderer",ay);Ze(this,"Lexer",Oi);Ze(this,"Tokenizer",Qh);Ze(this,"Hooks",zo);this.use(...e)}walkTokens(e,t){let n=[];for(let i of e)switch(n=n.concat(t.call(this,i)),i.type){case"table":{let r=i;for(let a of r.header)n=n.concat(this.walkTokens(a.tokens,t));for(let a of r.rows)for(let s of a)n=n.concat(this.walkTokens(s.tokens,t));break}case"list":{let r=i;n=n.concat(this.walkTokens(r.items,t));break}default:{let r=i;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(a=>{let s=r[a].flat(1/0);n=n.concat(this.walkTokens(s,t))}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let i={...n};if(i.async=this.defaults.async||i.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error("extension name required");if("renderer"in r){let a=t.renderers[r.name];a?t.renderers[r.name]=function(...s){let l=r.renderer.apply(this,s);return l===!1&&(l=a.apply(this,s)),l}:t.renderers[r.name]=r.renderer}if("tokenizer"in r){if(!r.level||r.level!=="block"&&r.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let a=t[r.level];a?a.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level==="block"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level==="inline"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]))}"childTokens"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens)}),i.extensions=t),n.renderer){let r=this.defaults.renderer||new Xh(this.defaults);for(let a in n.renderer){if(!(a in r))throw new Error(`renderer '${a}' does not exist`);if(["options","parser"].includes(a))continue;let s=a,l=n.renderer[s],u=r[s];r[s]=(...o)=>{let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h||""}}i.renderer=r}if(n.tokenizer){let r=this.defaults.tokenizer||new Qh(this.defaults);for(let a in n.tokenizer){if(!(a in r))throw new Error(`tokenizer '${a}' does not exist`);if(["options","rules","lexer"].includes(a))continue;let s=a,l=n.tokenizer[s],u=r[s];r[s]=(...o)=>{let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h}}i.tokenizer=r}if(n.hooks){let r=this.defaults.hooks||new zo;for(let a in n.hooks){if(!(a in r))throw new Error(`hook '${a}' does not exist`);if(["options","block"].includes(a))continue;let s=a,l=n.hooks[s],u=r[s];zo.passThroughHooks.has(a)?r[s]=o=>{if(this.defaults.async&&zo.passThroughHooksRespectAsync.has(a))return(async()=>{let c=await l.call(r,o);return u.call(r,c)})();let h=l.call(r,o);return u.call(r,h)}:r[s]=(...o)=>{if(this.defaults.async)return(async()=>{let c=await l.apply(r,o);return c===!1&&(c=await u.apply(r,o)),c})();let h=l.apply(r,o);return h===!1&&(h=u.apply(r,o)),h}}i.hooks=r}if(n.walkTokens){let r=this.defaults.walkTokens,a=n.walkTokens;i.walkTokens=function(s){let l=[];return l.push(a.call(this,s)),r&&(l=l.concat(r.call(this,s))),l}}this.defaults={...this.defaults,...i}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return Oi.lex(e,t??this.defaults)}parser(e,t){return Mi.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{let i={...n},r={...this.defaults,...i},a=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&i.async===!1)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof t>"u"||t===null)return a(new Error("marked(): input parameter is undefined or null"));if(typeof t!="string")return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));if(r.hooks&&(r.hooks.options=r,r.hooks.block=e),r.async)return(async()=>{let s=r.hooks?await r.hooks.preprocess(t):t,l=await(r.hooks?await r.hooks.provideLexer():e?Oi.lex:Oi.lexInline)(s,r),u=r.hooks?await r.hooks.processAllTokens(l):l;r.walkTokens&&await Promise.all(this.walkTokens(u,r.walkTokens));let o=await(r.hooks?await r.hooks.provideParser():e?Mi.parse:Mi.parseInline)(u,r);return r.hooks?await r.hooks.postprocess(o):o})().catch(a);try{r.hooks&&(t=r.hooks.preprocess(t));let s=(r.hooks?r.hooks.provideLexer():e?Oi.lex:Oi.lexInline)(t,r);r.hooks&&(s=r.hooks.processAllTokens(s)),r.walkTokens&&this.walkTokens(s,r.walkTokens);let l=(r.hooks?r.hooks.provideParser():e?Mi.parse:Mi.parseInline)(s,r);return r.hooks&&(l=r.hooks.postprocess(l)),l}catch(s){return a(s)}}}onError(e,t){return n=>{if(n.message+=`
308
- Please report this to https://github.com/markedjs/marked.`,e){let i="<p>An error occurred:</p><pre>"+lr(n.message+"",!0)+"</pre>";return t?Promise.resolve(i):i}if(t)return Promise.reject(n);throw n}}},gs=new U4;function Ye(e,t){return gs.parse(e,t)}Ye.options=Ye.setOptions=function(e){return gs.setOptions(e),Ye.defaults=gs.defaults,Yk(Ye.defaults),Ye};Ye.getDefaults=X0;Ye.defaults=ys;Ye.use=function(...e){return gs.use(...e),Ye.defaults=gs.defaults,Yk(Ye.defaults),Ye};Ye.walkTokens=function(e,t){return gs.walkTokens(e,t)};Ye.parseInline=gs.parseInline;Ye.Parser=Mi;Ye.parser=Mi.parse;Ye.Renderer=Xh;Ye.TextRenderer=ay;Ye.Lexer=Oi;Ye.lexer=Oi.lex;Ye.Tokenizer=Qh;Ye.Hooks=zo;Ye.parse=Ye;var dI=Ye.options,mI=Ye.setOptions,gI=Ye.use,yI=Ye.walkTokens,bI=Ye.parseInline;var xI=Mi.parse,vI=Oi.lex;var La=Fe(Yn(),1);var rE=["card","stat","compare","timeline","chart","figure","html","interactive"];var aE={card:{label:"\u8D44\u6E90\u5361",when:"\u4E00\u7BC7\u8BBA\u6587\u3001\u4E00\u4E2A\u4ED3\u5E93\u6216\u4E00\u672C\u4E66\uFF0C\u8BFB\u8005\u9700\u8981\u6807\u9898\u3001\u94FE\u63A5\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6B63\u6587\u91CC\u5DF2\u7ECF\u6709\u8FD9\u53E5\u8BDD\u65F6\uFF0C\u4E0D\u8981\u518D\u5305\u4E00\u5F20\u5361\u3002",keys:["url","title","description","image","alt","points","meta","text","source","site","items"],example:"```garden card\nurl: https://arxiv.org/abs/2309.06180\ntitle: PagedAttention\ndescription: vLLM \u7684\u5206\u9875 KV \u7BA1\u7406\u3002\n```",triggers:["gcard"]},stat:{label:"\u6307\u6807",when:"\u4E00\u4E2A\u77ED\u6307\u6807\uFF1A\u6807\u7B7E\u3001\u6570\u5B57\u3001\u53EF\u9009\u7684\u4E00\u53E5\u8BF4\u660E\u548C\u6765\u6E90\u3002",whenNot:"\u6570\u5B57\u9700\u8981\u8BFB\u8005\u81EA\u5DF1\u4EE3\u5165\u53C2\u6570\u65F6\uFF0C\u5199\u6210\u60F3\u6CD5\uFF0C\u4E0D\u8981\u505A\u9759\u6001\u6307\u6807\u3002",keys:["items","label","value","unit","caption","source","text"],example:"```garden stat\nitems:\n - label: Llama-2-13B \xB7 4K \u4E0A\u4E0B\u6587\n value: 3.2\n unit: GiB\n source: https://arxiv.org/abs/2309.06180\n```",triggers:["gstat"]},compare:{label:"\u5BF9\u6BD4",when:"\u4E24\u4E09\u4EF6\u4E1C\u897F\u5E76\u6392\uFF0C\u6BCF\u683C\u5927\u7EA6 60 \u5B57\u4EE5\u5185\u3002",whenNot:"\u4EFB\u4F55\u4E00\u683C\u8D85\u8FC7\u7EA6 60 \u5B57\u65F6\uFF0C\u7528\u539F\u6587\u7684\u5217\u8868\uFF0C\u4E0D\u8981\u5E76\u6392\u3002",keys:["items"],itemKeys:["title","text"],example:"```garden compare\nitems:\n - title: \u81EA\u65CB\u9501\n text: \u4E34\u754C\u533A\u6781\u77ED\u65F6\u5FD9\u7B49\uFF0C\u4E0D\u8FDB\u5165\u4F11\u7720\u3002\n - title: \u4E92\u65A5\u9501\n text: \u4E89\u7528\u4E45\u5C31\u4F11\u7720\uFF0C\u907F\u514D\u7A7A\u8F6C\u5360\u6EE1 CPU\u3002\n```",triggers:["gcompare"]},timeline:{label:"\u65F6\u95F4\u7EBF",when:"\u7248\u672C\u6F14\u8FDB\u6216\u4E00\u6BB5\u5386\u53F2\uFF0C\u6BCF\u6761\u6709\u65E5\u671F\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6CA1\u6709\u65F6\u95F4\u987A\u5E8F\u65F6\uFF0C\u7528\u666E\u901A\u5217\u8868\u3002",keys:["title","items"],itemKeys:["date","title","text","source"],example:`\`\`\`garden timeline
308
+ Please report this to https://github.com/markedjs/marked.`,e){let i="<p>An error occurred:</p><pre>"+lr(n.message+"",!0)+"</pre>";return t?Promise.resolve(i):i}if(t)return Promise.reject(n);throw n}}},gs=new U4;function Ye(e,t){return gs.parse(e,t)}Ye.options=Ye.setOptions=function(e){return gs.setOptions(e),Ye.defaults=gs.defaults,Yk(Ye.defaults),Ye};Ye.getDefaults=X0;Ye.defaults=ys;Ye.use=function(...e){return gs.use(...e),Ye.defaults=gs.defaults,Yk(Ye.defaults),Ye};Ye.walkTokens=function(e,t){return gs.walkTokens(e,t)};Ye.parseInline=gs.parseInline;Ye.Parser=Mi;Ye.parser=Mi.parse;Ye.Renderer=Xh;Ye.TextRenderer=ay;Ye.Lexer=Oi;Ye.lexer=Oi.lex;Ye.Tokenizer=Qh;Ye.Hooks=zo;Ye.parse=Ye;var dI=Ye.options,mI=Ye.setOptions,gI=Ye.use,yI=Ye.walkTokens,bI=Ye.parseInline;var xI=Mi.parse,vI=Oi.lex;var La=Fe(Yn(),1);var rE=["card","stat","compare","timeline","chart","figure","html","interactive"];var aE={card:{label:"\u8D44\u6E90\u5361",when:"\u4E00\u7BC7\u8BBA\u6587\u3001\u4E00\u4E2A\u4ED3\u5E93\u6216\u4E00\u672C\u4E66\uFF0C\u8BFB\u8005\u9700\u8981\u6807\u9898\u3001\u94FE\u63A5\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6B63\u6587\u91CC\u5DF2\u7ECF\u6709\u8FD9\u53E5\u8BDD\u65F6\uFF0C\u4E0D\u8981\u518D\u5305\u4E00\u5F20\u5361\u3002",keys:["url","title","description","image","alt","points","meta","text","source","site","items"],example:"```garden card\nurl: https://arxiv.org/abs/2309.06180\ntitle: PagedAttention\ndescription: vLLM \u7684\u5206\u9875 KV \u7BA1\u7406\u3002\n```",triggers:["gcard"]},stat:{label:"\u6307\u6807",when:"\u4E00\u4E2A\u77ED\u6307\u6807\uFF1A\u6807\u7B7E\u3001\u6570\u5B57\u3001\u53EF\u9009\u7684\u4E00\u53E5\u8BF4\u660E\u548C\u6765\u6E90\u3002",whenNot:"\u6570\u5B57\u9700\u8981\u8BFB\u8005\u81EA\u5DF1\u4EE3\u5165\u53C2\u6570\u65F6\uFF0C\u5199\u6210\u60F3\u6CD5\uFF0C\u4E0D\u8981\u505A\u9759\u6001\u6307\u6807\u3002",keys:["items","label","value","unit","caption","source","text"],example:"```garden stat\nitems:\n - label: Llama-2-13B \xB7 4K \u4E0A\u4E0B\u6587\n value: 3.2\n unit: GiB\n source: https://arxiv.org/abs/2309.06180\n```",triggers:["gstat"]},compare:{label:"\u5BF9\u6BD4",when:"\u4E24\u4E09\u4EF6\u4E1C\u897F\u5E76\u6392\uFF0C\u6BCF\u683C\u5927\u7EA6 60 \u5B57\u4EE5\u5185\u3002\u539F\u6587\u662F\u300CX\uFF1AY\u300D\u7684\u5217\u8868\u65F6\uFF0C\u6BCF\u683C\u5199\u6210\u4E00\u884C\u5E26\u5F15\u53F7\u7684\u5B57\u7B26\u4E32\uFF0C\u5192\u53F7\u524D\u662F\u6807\u9898\uFF0C\u5192\u53F7\u539F\u6837\u663E\u793A\u3002",whenNot:"\u4EFB\u4F55\u4E00\u683C\u8D85\u8FC7\u7EA6 60 \u5B57\u65F6\uFF0C\u7528\u539F\u6587\u7684\u5217\u8868\uFF0C\u4E0D\u8981\u5E76\u6392\u3002",keys:["items"],itemKeys:["title","text"],example:"```garden compare\nitems:\n - title: \u81EA\u65CB\u9501\n text: \u4E34\u754C\u533A\u6781\u77ED\u65F6\u5FD9\u7B49\uFF0C\u4E0D\u8FDB\u5165\u4F11\u7720\u3002\n - title: \u4E92\u65A5\u9501\n text: \u4E89\u7528\u4E45\u5C31\u4F11\u7720\uFF0C\u907F\u514D\u7A7A\u8F6C\u5360\u6EE1 CPU\u3002\n```",triggers:["gcompare"]},timeline:{label:"\u65F6\u95F4\u7EBF",when:"\u7248\u672C\u6F14\u8FDB\u6216\u4E00\u6BB5\u5386\u53F2\uFF0C\u6BCF\u6761\u6709\u65E5\u671F\u548C\u4E00\u53E5\u8BF4\u660E\u3002",whenNot:"\u6CA1\u6709\u65F6\u95F4\u987A\u5E8F\u65F6\uFF0C\u7528\u666E\u901A\u5217\u8868\u3002",keys:["title","items"],itemKeys:["date","title","text","source"],example:`\`\`\`garden timeline
309
309
  items:
310
310
  - date: 2015
311
311
  title: \u5E76\u53D1\u6807\u8BB0