Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 41 additions & 8 deletions packages/landing/scripts/gen-landing-snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,35 @@ function githubTreeUrl(slug: string): string {
/* -------------------------------------------------------------------------- */

/**
* Slice the leading `import ... from "@lobu/cli/config";` block out of a config file.
* Returns the import statement lines (the first `import` through its closing
* `from "...";`), or an empty array if none is found.
* Slice the leading import section out of a config file: every contiguous
* `import ...` statement (including `import type X from "./*.ts"`), tolerating
* blank lines between them. Capturing the type imports too means generic
* references shown in the snippet (e.g. `connectorFromFile<typeof X>`) resolve
* to a visible import rather than reading as undefined symbols. Returns an
* empty array if no import is found.
*/
function sliceImportBlock(raw: string): string[] {
const lines = raw.split("\n");
const start = lines.findIndex((l) => /^\s*import\b/.test(l));
if (start < 0) return [];
let end = start;
let inStatement = true;
for (let i = start; i < lines.length; i++) {
end = i;
if (/;\s*$/.test(lines[i])) break;
const line = lines[i];
if (inStatement) {
end = i;
if (/;\s*$/.test(line)) inStatement = false;
continue;
}
if (/^\s*import\b/.test(line)) {
inStatement = true;
end = i;
if (/;\s*$/.test(line)) inStatement = false;
} else if (line.trim() === "") {
// tolerate blank lines between import statements
} else {
break;
}
}
return lines.slice(start, end + 1);
}
Expand Down Expand Up @@ -253,12 +270,28 @@ function fileSnippet(
};
}

/** The imports + the first `defineAgent({...})` block, the representative
* agent slice for the landing "Agents" section. */
/** The imports + `defineAgent` + a real `defineWatcher` + the `defineConfig`
* manifest that wires connectors, entities, watchers, and agents together.
* Only the repetitive entity/relationship definitions are elided (behind a
* comment), so the snippet shows the differentiated piece (a watcher's prompt
* + extraction schema) and stays one coherent control-plane file. The
* homepage shows this as the single "it's real" anchor. */
function agentConfigSlice(raw: string): string {
const imports = sliceImportBlock(raw);
const agent = sliceDefineCall(raw, "defineAgent");
return [...imports, "", ...agent].join("\n");
const watcher = sliceDefineCall(raw, "defineWatcher");
const config = sliceDefineCall(raw, "defineConfig");
return [
...imports,
"",
...agent,
"",
"// entity types and relationships defined here…",
"",
...watcher,
"",
...config,
].join("\n");
}

function entitySlice(raw: string): string {
Expand Down
144 changes: 100 additions & 44 deletions packages/landing/src/components/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ComponentChildren } from "preact";
import { useState } from "preact/hooks";

export type CodeSnippet = {
code: string;
Expand All @@ -15,6 +16,14 @@ type CodeBlockProps = {
badge?: string;
/** Extra footer text rendered next to the GitHub link. */
footnote?: ComponentChildren;
/**
* When true, the code body collapses behind a "show the code" toggle so the
* page reads value-first for non-TS skimmers. The tab bar (filename + line
* count) stays visible as the affordance. Defaults to false (always open).
*/
collapsible?: boolean;
/** Initial open state when `collapsible`. Defaults to false (collapsed). */
defaultOpen?: boolean;
};

type Token = { kind: TokenKind; text: string };
Expand Down Expand Up @@ -443,63 +452,110 @@ export function CodeBlock({
tabLabel,
badge,
footnote,
collapsible = false,
defaultOpen = false,
}: CodeBlockProps) {
const lines = highlight(snippet.code, snippet.language);
const [open, setOpen] = useState(defaultOpen);
const showBody = !collapsible || open;

return (
const tabBar = (
<div
class="overflow-hidden rounded-lg border"
class="flex items-center justify-between border-b px-4 py-2 font-mono text-[11.5px] lowercase"
style={{
backgroundColor: "var(--color-landing-code-bg)",
borderColor: "var(--color-page-border)",
color: "var(--color-landing-code-comment)",
backgroundColor: "var(--color-landing-code-bg-soft)",
borderColor: "rgba(255,255,255,0.06)",
}}
>
<div
class="flex items-center justify-between border-b px-4 py-2 font-mono text-[11.5px] lowercase"
style={{
color: "var(--color-landing-code-comment)",
backgroundColor: "var(--color-landing-code-bg-soft)",
borderColor: "rgba(255,255,255,0.06)",
}}
>
<span>{tabLabel ?? snippet.path}</span>
<span>{tabLabel ?? snippet.path}</span>
<span class="flex items-center gap-3">
{badge ? (
<span style={{ color: "var(--color-landing-code-comment)" }}>
{badge}
</span>
) : null}
</div>

<pre
class="overflow-x-auto px-5 py-4 font-mono text-[12.5px] leading-[1.65]"
style={{ color: "var(--color-landing-code-text)" }}
>
<code class="block">
{lines.map((toks, idx) => (
<span class="block whitespace-pre" key={idx}>
{tokensToJsx(toks)}
{idx < lines.length - 1 ? "\n" : ""}
{collapsible ? (
<span
class="flex items-center gap-1"
style={{ color: "var(--color-tg-accent)" }}
>
{open ? "hide code" : "show the code"}
<span
aria-hidden="true"
style={{
display: "inline-block",
transform: open ? "rotate(90deg)" : "none",
transition: "transform 0.15s ease",
}}
>
</span>
</span>
) : null}
</span>
</div>
);

return (
<div
class="overflow-hidden rounded-lg border"
style={{
backgroundColor: "var(--color-landing-code-bg)",
borderColor: "var(--color-page-border)",
}}
>
{collapsible ? (
<button
type="button"
class="block w-full cursor-pointer text-left"
aria-expanded={open}
onClick={() => setOpen((v) => !v)}
>
{tabBar}
</button>
) : (
tabBar
)}

{showBody ? (
<>
<pre
class="overflow-x-auto px-5 py-4 font-mono text-[12.5px] leading-[1.65]"
style={{ color: "var(--color-landing-code-text)" }}
>
<code class="block">
{lines.map((toks, idx) => (
<span class="block whitespace-pre" key={idx}>
{tokensToJsx(toks)}
{idx < lines.length - 1 ? "\n" : ""}
</span>
))}
</code>
</pre>

<div
class="flex items-center justify-between border-t px-4 py-2 font-mono text-[11px] lowercase"
style={{
color: "var(--color-landing-code-comment)",
backgroundColor: "var(--color-landing-code-bg-soft)",
borderColor: "rgba(255,255,255,0.06)",
}}
>
<span>{lines.length} lines</span>
<span class="flex items-center gap-3">
{footnote}
<a
href={snippet.githubUrl}
rel="noopener noreferrer"
target="_blank"
>
see on github →
</a>
</span>
))}
</code>
</pre>

<div
class="flex items-center justify-between border-t px-4 py-2 font-mono text-[11px] lowercase"
style={{
color: "var(--color-landing-code-comment)",
backgroundColor: "var(--color-landing-code-bg-soft)",
borderColor: "rgba(255,255,255,0.06)",
}}
>
<span>{lines.length} lines</span>
<span class="flex items-center gap-3">
{footnote}
<a href={snippet.githubUrl} rel="noopener noreferrer" target="_blank">
see on github →
</a>
</span>
</div>
</div>
</>
) : null}
</div>
);
}
Loading
Loading