* feat(draw-image): add SVG template render engine * feat(draw-image): add opencode plugin and tool tests * test(draw-image): add vitest unit integration e2e suite * chore(draw-image): wire CI dependabot docs and ADR * docs(handoff): set PR number * docs(handoff): fix PR number placeholder in frontmatter * fix(ci): use tempfile and trailing newline in draw-image tests --------- Co-authored-by: opencode-agent <agent@opencode.local>
32 lines
No EOL
1.6 KiB
TypeScript
32 lines
No EOL
1.6 KiB
TypeScript
import { spawnSync } from "child_process"
|
|
import { tool } from "@opencode-ai/plugin"
|
|
import path from "path"
|
|
|
|
export default tool({
|
|
description: "Render an on-brand cover PNG from an SVG template. Resolves Lucide icons and brand logos into slots, applies brand palette, renders via sharp. Returns { path, hash, status }.",
|
|
args: {
|
|
template: tool.schema.string().describe("Template name (file in templates/ without .svg extension, e.g. 'cover')"),
|
|
title: tool.schema.string().describe("Title text rendered at the bottom of the cover"),
|
|
subtitle: tool.schema.string().optional().describe("Optional subtitle text below the title"),
|
|
slots: tool.schema.string().optional().describe("Comma-separated slot assignments, e.g. 'icon=mic,sub-icon=opencode,badge=./x.svg'"),
|
|
out: tool.schema.string().optional().describe("Output PNG path (default: ./assets/cover.png)"),
|
|
},
|
|
async execute(args, context) {
|
|
const drawImageDir = path.resolve(import.meta.dir, "..", "draw-image")
|
|
const cliPath = path.join(drawImageDir, "cli.ts")
|
|
|
|
const cliArgs = ["render", args.template, "--title", args.title]
|
|
if (args.subtitle) cliArgs.push("--subtitle", args.subtitle)
|
|
if (args.slots) cliArgs.push("--slots", args.slots)
|
|
if (args.out) cliArgs.push("--out", args.out)
|
|
|
|
const r = spawnSync("node", ["--experimental-strip-types", cliPath, ...cliArgs], {
|
|
encoding: "utf-8",
|
|
cwd: context.worktree,
|
|
})
|
|
if (r.status !== 0) {
|
|
return `⚠️ draw-image failed (exit ${r.status}): ${r.stderr || r.stdout}`
|
|
}
|
|
return r.stdout.trim()
|
|
},
|
|
}) |