Skip to content

feat: design-to-code user tool (#35)#37

Merged
let-sunny merged 8 commits intomainfrom
feat/design-to-code-tool
Mar 25, 2026
Merged

feat: design-to-code user tool (#35)#37
let-sunny merged 8 commits intomainfrom
feat/design-to-code-tool

Conversation

@let-sunny
Copy link
Copy Markdown
Owner

@let-sunny let-sunny commented Mar 24, 2026

Summary

design-to-code를 사용자 구현 도구로 제공. 분석 → 디자인 트리 → 에셋 → 프롬프트를 한 패키지로.

canicode implement <input>

canicode implement ./fixtures/my-design
canicode implement ./fixtures/my-design --prompt ./my-react-prompt.md --image-scale 3

출력:

canicode-implement/
  analysis.json      # 이슈 + 점수
  design-tree.txt    # DOM-like 트리 + CSS (~N tokens)
  images/            # PNG 에셋 (hero-banner@2x.png)
  vectors/           # SVG 에셋
  PROMPT.md          # 코드 생성 프롬프트

변경 사항

이미지 에셋 매핑

  • save-fixture에서 IMAGE fill 노드 PNG @2x 다운로드
  • 노드 이름 기반 파일명 (sanitize + dedupe)
  • mapping.json으로 nodeId → 파일명 매핑
  • design-tree에서 url(images/hero-banner@2x.png) 출력

해상도 옵션

  • --image-scale: 2 (PC, default), 3 (mobile)

커스텀 프롬프트

  • --prompt <path>: 사용자 프롬프트 파일
  • 기본: 내장 HTML+CSS 프롬프트

문서

  • README: Design to Code 섹션 추가
  • CLAUDE.md: implement 경로 추가
  • canicode docs implement: 가이드 토픽

E2E 검증 완료

  • save-fixture → images/ 6개 PNG 다운로드 ✅
  • implement → images/ 복사 + design-tree url() 출력 ✅
  • mapping.json dedupe (같은 이름 → image, image-2, ...) ✅

Test plan

  • pnpm test:run — 317 tests passed
  • pnpm lint — clean
  • E2E: save-fixture with IMAGE fills → images/ 생성
  • E2E: implement → images + design-tree url() 연결
  • E2E: canicode docs implement 출력

Closes #35

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a new canicode implement command to generate a design-to-code package (analysis, design tree, prompt and exported assets) from a Figma URL or local fixture.
    • Supports downloading image and vector assets with configurable image scale and output location; continues past per-asset failures.
  • Documentation

    • Updated CLI docs, README and prompt guidance with usage examples, options (prompt, image-scale, token, output) and recommended next steps for consuming the package.

save-fixture now downloads PNG exports (@2x) for nodes with IMAGE
fills, saved with sanitized node names (e.g. "hero-banner@2x.png"
instead of "I593-8035@2x.png"). A mapping.json links node IDs to
filenames.

design-tree outputs url(images/hero-banner@2x.png) instead of [IMAGE]
when the image directory and mapping are available.

- collectImageNodes: walks tree for IMAGE fill nodes
- sanitizeFilename: node name → kebab-case, dedup with -2, -3
- mapping.json: nodeId → filename for design-tree lookup
- Auto-detect images/ dir in design-tree CLI (mirrors vectors/ pattern)
- 3 new tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

This PR adds a new canicode implement CLI command and documentation, extends the CLI to download and export image assets (with scale validation), and updates the design-tree engine to accept an imageDir mapping so IMAGE fills can emit background-image: url(images/...) when mapped.

Changes

Cohort / File(s) Summary
Documentation & Skill Definition
.claude/skills/canicode-implement/SKILL.md, .claude/skills/design-to-code/PROMPT.md, CLAUDE.md, README.md
Added implement skill/docs, updated prompt usage to canicode implement, documented CLI usage, options, output package layout and workflow.
CLI Docs Dispatcher
src/cli/docs.ts
Added printDocsImplement() and registered implement in DOCS_TOPICS; updated docs index output.
CLI Core & Commands
src/cli/index.ts
Added implement <input> command; image export support and --image-scale for save-fixture; new helpers (collectImageNodes, sanitizeFilename); copy/download logic for vectors/ and images/; --image-dir propagation to design-tree; robust per-asset failure handling and mapping.json generation.
Design-Tree Engine & Tests
src/core/engine/design-tree.ts, src/core/engine/design-tree.test.ts
Added imageDir?: string to DesignTreeOptions; renderNode takes imageMapping and emits mapped url(images/...) when present, otherwise background-image: [IMAGE]; implemented single-load of images/mapping.json. Added tests for mapped and fallback IMAGE cases.

Sequence Diagram

sequenceDiagram
    participant User as User/CLI
    participant CLI as implement<br/>Handler
    participant FSys as File System
    participant FigmaAPI as Figma API<br/>(optional)
    participant DTEngine as Design-Tree<br/>Engine

    User->>CLI: canicode implement <input> --options
    CLI->>CLI: Validate input (URL or path)
    
    alt Input is Figma URL
        CLI->>FigmaAPI: Fetch document, vectors
        FigmaAPI-->>CLI: Design data, nodeIds
        CLI->>FigmaAPI: Export images (IMAGE fills)
        FigmaAPI-->>CLI: PNG blobs + mapping
        CLI->>FSys: Write images/ + mapping.json
    else Input is Fixture Path
        CLI->>FSys: Load existing fixture
        FSys-->>CLI: analysis.json, vectors/, images/
    end
    
    CLI->>DTEngine: generateDesignTreeWithStats(analysis, imageDir, vectorDir)
    DTEngine->>FSys: Read images/mapping.json (if provided)
    FSys-->>DTEngine: File mapping
    DTEngine-->>CLI: design-tree.txt (with image URLs or [IMAGE])
    
    CLI->>FSys: Write output package (analysis.json, design-tree.txt, PROMPT.md, vectors/, images/)
    CLI-->>User: Package generated
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • let-sunny/canicode#21 — Related changes to design-tree IMAGE-fill handling that this PR builds upon by adding image mapping and URL emission.
  • let-sunny/canicode#28 — Related modifications to design-tree pipeline and CLI integration (generateDesignTreeWithStats) that this PR extends to support imageDir and mapping.json.

Poem

🐰 I hopped through Figma, files in tow,
Mapped images, prompts, and outputs aglow.
A package assembled, assets all aligned,
Feed the prompt to code — let the builder unwind! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: design-to-code user tool (#35)' clearly and specifically summarizes the main change: introducing a user-facing design-to-code implementation tool.
Linked Issues check ✅ Passed All four linked issue objectives are met: image asset mapping (#35-1), resolution-specific handling (#35-2), stack flexibility via --prompt (#35-3), and user-facing implement command (#35-4).
Out of Scope Changes check ✅ Passed All changes are within scope: documentation updates, CLI command implementation, image asset handling, and design-tree integration directly support the linked issue objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/design-to-code-tool

Comment @coderabbitai help to get the list of available commands and usage tips.

let-sunny and others added 6 commits March 25, 2026 08:38
save-fixture now accepts --image-scale <n> (default 2, range 1-4).
Filenames reflect the scale: hero-banner@3x.png for mobile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split DESIGN-TO-CODE-PROMPT.md into base rules + stack-specific templates:
- stacks/html-css.md (default, calibration)
- stacks/react-tailwind.md
- stacks/react-css-modules.md
- stacks/vue-css.md

Base prompt now includes image asset handling rules and stack selection guide.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eDir)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLI command that prepares a design-to-code package:
- analysis.json (issues + scores)
- design-tree.txt (with token estimate)
- images/ + vectors/ (asset directories)
- PROMPT.md (base + stack-specific)

Supports: --stack (html-css, react-tailwind, react-css-modules, vue-css)
          --image-scale (2 for PC, 3 for mobile)
          --output (default: ./canicode-implement/)

Also adds /canicode-implement skill for Claude Code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- README: add "Design to Code" section + "Generate code from design" row
- CLAUDE.md: add implement to CLI description
- CLI docs: add "implement" topic with usage, options, stacks, workflow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove fixed stack selection (html-css, react-tailwind, etc.) in favor
of --prompt <path> for user-supplied prompt files. Default remains
built-in HTML+CSS prompt.

- Remove stacks/ directory and VALID_STACKS constant
- Add --prompt option to implement command
- Simplify prompt assembly (custom file OR built-in default)
- Update README, CLAUDE.md, CLI docs to reflect new approach

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny let-sunny marked this pull request as ready for review March 25, 2026 00:00
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli/docs.ts (1)

340-342: ⚠️ Potential issue | 🟡 Minor

Error message missing implement topic.

The available topics list in the error message doesn't include the newly added implement topic.

📝 Proposed fix
   } else {
     console.error(`Unknown docs topic: ${topic}`);
-    console.error(`Available topics: setup, rules, config, visual-compare, design-tree`);
+    console.error(`Available topics: setup, rules, config, implement, visual-compare, design-tree`);
     process.exit(1);
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/docs.ts` around lines 340 - 342, Update the error output in the docs
topic handling to include the newly added "implement" topic: modify the
console.error that prints available topics (the lines referencing Available
topics: setup, rules, config, visual-compare, design-tree) to also list
implement so the message reflects the true set of choices when topic (variable
topic) is unknown in the docs command handler in src/cli/docs.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/canicode-implement/SKILL.md:
- Line 63: The fenced code block in SKILL.md is missing a language specifier for
the opening backticks; update the opening fence that currently reads just ``` to
include a language (e.g., use ```text) so the block containing
"canicode-implement/" is marked as ```text, ensuring proper rendering and syntax
highlighting for that snippet.
- Around line 40-43: The fenced code block in SKILL.md lacks blank lines
surrounding it; add an empty line before the opening ```bash and an empty line
after the closing ``` so the block is properly separated from surrounding text
(specifically ensure there's a blank line between the code fence and the
preceding list item and another blank line before the "4. Clean up temp fixture
if desired" paragraph).
- Around line 29-31: The CLI example in SKILL.md uses the inconsistent flag
--stack; update the example command string (the code block containing npx
canicode implement "https://www.figma.com/design/ABC/File?node-id=1-234") to use
--prompt ./my-vue-prompt.md instead of --stack vue-css so it matches the
intended usage; replace the --stack token with the --prompt token and the sample
path as shown.
- Around line 24-25: Update the example command to use the current CLI option
--prompt instead of the removed --stack option: replace "npx canicode implement
./fixtures/my-design --stack react-tailwind" with "npx canicode implement
./fixtures/my-design --prompt ./my-react-prompt.md" and add a short note that
built-in stack templates were removed and custom prompt files should be passed
with --prompt.
- Around line 47-59: Update the options table and explanatory section to replace
the removed `--stack <name>` option with the new `--prompt <file>` option:
change the table row to "`--prompt <file>` | Custom prompt file (replaces
built-in stacks) | `./prompts/default.json` or unset" (or appropriate default),
remove or rewrite the "Available stacks" list that references built-in stacks,
and instead add a short explanation that custom prompt files should be used
(with an example file name and how to select it). Ensure references to `--stack`
in the surrounding text are removed or replaced with `--prompt` and that any
examples or defaults (like `html-css`) are updated to reflect the new
prompt-based workflow.

In `@src/cli/docs.ts`:
- Around line 299-301: Update the workflow example that currently shows
"canicode implement ./my-fixture --stack react-tailwind" to use the new CLI
option name "--prompt" instead of "--stack" (e.g., "canicode implement
./my-fixture --prompt react-tailwind" or reference a prompt file), since the CLI
implementation uses "--prompt"; modify the text in the docs.ts constant/string
containing the WORKFLOW example and replace occurrences of "--stack" with
"--prompt" to keep docs and src/cli/index.ts consistent.

In `@src/cli/index.ts`:
- Around line 1038-1051: The design tree is being generated by
generateDesignTreeWithStats before live Figma images are downloaded because
fixtureBase (and thus imageDir) is undefined for URL inputs, producing [IMAGE]
placeholders; update the flow so image assets are downloaded first (or call
generateDesignTreeWithStats again after downloads) and ensure imageDir is set
when invoking generateDesignTreeWithStats (reference isJsonFile, isFixtureDir,
fixtureBase, imageDir, vectorDir, and generateDesignTreeWithStats) so the final
design-tree.txt reflects the downloaded images rather than placeholders.
- Around line 1135-1169: Add creation of a mapping from image node id →
downloaded file path during the image download loop (use the existing
imgNodes/filename variables), write that mapping JSON to images/mapping.json
(e.g., writeFile(resolve(imgOutDir, "mapping.json"), JSON.stringify(mapping,
null, 2))), and after the try block completes re-run the same logic that
generates/writes design-tree.txt (the earlier design-tree.txt writer used around
lines 1045-1051) so the tree can substitute image placeholders with
url(images/...) using the newly written mapping.json.

---

Outside diff comments:
In `@src/cli/docs.ts`:
- Around line 340-342: Update the error output in the docs topic handling to
include the newly added "implement" topic: modify the console.error that prints
available topics (the lines referencing Available topics: setup, rules, config,
visual-compare, design-tree) to also list implement so the message reflects the
true set of choices when topic (variable topic) is unknown in the docs command
handler in src/cli/docs.ts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4d44d3dc-b9a6-4bad-81df-73286ca7d0cc

📥 Commits

Reviewing files that changed from the base of the PR and between 7eb744e and be6df3a.

📒 Files selected for processing (8)
  • .claude/skills/canicode-implement/SKILL.md
  • .claude/skills/design-to-code/PROMPT.md
  • CLAUDE.md
  • README.md
  • src/cli/docs.ts
  • src/cli/index.ts
  • src/core/engine/design-tree.test.ts
  • src/core/engine/design-tree.ts

Comment on lines +40 to +43
```bash
npx canicode implement fixtures/_mcp-temp --stack html-css
```
4. Clean up temp fixture if desired
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Markdown formatting: add blank lines around fenced code block.

📝 Proposed fix
 3. **Run implement** on the saved fixture:
+
    ```bash
    npx canicode implement fixtures/_mcp-temp --stack html-css
    ```
+
 4. Clean up temp fixture if desired
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
npx canicode implement fixtures/_mcp-temp --stack html-css
```
4. Clean up temp fixture if desired
3. **Run implement** on the saved fixture:
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 40-40: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 42-42: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/canicode-implement/SKILL.md around lines 40 - 43, The fenced
code block in SKILL.md lacks blank lines surrounding it; add an empty line
before the opening ```bash and an empty line after the closing ``` so the block
is properly separated from surrounding text (specifically ensure there's a blank
line between the code fence and the preceding list item and another blank line
before the "4. Clean up temp fixture if desired" paragraph).

… cleanup

Major fixes:
- Reorder implement command: download assets FIRST, then generate
  design tree — so live URL images get url() paths instead of [IMAGE]
- Write mapping.json for live URL image downloads
- Update imageDir/vectorDir to point to downloaded assets

Minor fixes:
- SKILL.md: replace --stack with --prompt throughout
- docs.ts: fix --stack reference in workflow example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/canicode-implement/SKILL.md:
- Around line 49-59: The documented output tree is missing images/mapping.json;
update the SKILL.md Output Structure block to include images/mapping.json under
the images/ directory so the example reflects the actual CLI output and the
design tree's url(images/...) substitution. Specifically, add a line like
"images/mapping.json   # Mapping of original asset names to output filenames
(used for url(images/...))" beneath the images/ entry in the canicode-implement
tree so readers see that file is produced when image assets are present.

In `@src/cli/docs.ts`:
- Around line 319-325: The invalid-topic hint's hard-coded list of available
docs topics needs to include the new "implement" topic so typed commands like
`canicode docs implemnt` don't incorrectly indicate it's unavailable; update the
string list/message that prints available topics (the code that references
DOCS_TOPICS keys for the invalid-topic hint) to include "implement" (match the
key in DOCS_TOPICS) or, better, derive the hint dynamically from DOCS_TOPICS'
keys so the help output stays in sync with DOCS_TOPICS (modify the code that
currently prints the hard-coded list of topics to use Object.keys(DOCS_TOPICS)
or add "implement" to that literal list).
- Around line 291-298: Update the documented package layout under the OUTPUT
section (the block starting with the literal header "OUTPUT" and the list
entries like "images/") to include the new images/mapping.json file; add a line
describing "images/mapping.json — JSON map used by the design tree to replace
[IMAGE] with url(images/...)" so the documented output matches the implement
behavior that writes/copies images/mapping.json and the design tree uses it for
image URL substitution.

In `@src/cli/index.ts`:
- Around line 888-923: The mapping.json is built from nodeIdToFilename
regardless of whether the image was actually downloaded; change the code to only
persist mappings for successfully written files by creating a new Map or object
(e.g., downloadedMapping) and, inside the successful fetch/write branch (the
block where resp.ok and writeFile succeed), add downloadedMapping.set(id,
filename) (or downloadedMapping[id] = filename); after the download loop
serialize downloadedMapping to mapping.json instead of nodeIdToFilename; apply
the same change to the other image-export loop referenced (the block analogous
around generateDesignTreeWithStats) so mapping.json contains only files that
exist on disk.
- Around line 1016-1026: In the Implement CLI action handler (the async .action
callback in src/cli/index.ts), detect when options.nodeId (or equivalent node-id
property on ImplementOptions) is not provided and emit a visible warning before
proceeding (e.g., console.warn or processLogger.warn) that the command will
process the entire Figma file and may produce large prompts/assets; place this
check just before calling loadFile or packaging so users see it early and keep
existing behavior when nodeId is present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3133544f-174d-4604-9612-d2a7ddf6c7df

📥 Commits

Reviewing files that changed from the base of the PR and between be6df3a and d65a4f6.

📒 Files selected for processing (3)
  • .claude/skills/canicode-implement/SKILL.md
  • src/cli/docs.ts
  • src/cli/index.ts

Comment on lines +49 to +59
## Output Structure

```text
canicode-implement/
analysis.json # Full analysis with issues and scores
design-tree.txt # DOM-like tree with styles, structure, embedded SVGs
PROMPT.md # Code generation prompt (default or custom)
screenshot.png # Figma screenshot (if available)
vectors/ # SVG assets for VECTOR nodes
images/ # PNG assets for IMAGE fill nodes (hero-banner@2x.png)
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Show images/mapping.json in the documented output tree.

The CLI writes/copies that file when image assets are present, and the design tree uses it for url(images/...) substitution. Leaving it out here makes the skill package layout incomplete.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/canicode-implement/SKILL.md around lines 49 - 59, The
documented output tree is missing images/mapping.json; update the SKILL.md
Output Structure block to include images/mapping.json under the images/
directory so the example reflects the actual CLI output and the design tree's
url(images/...) substitution. Specifically, add a line like "images/mapping.json
# Mapping of original asset names to output filenames (used for
url(images/...))" beneath the images/ entry in the canicode-implement tree so
readers see that file is produced when image assets are present.

Comment on lines +291 to +298
OUTPUT
canicode-implement/
analysis.json Analysis report with issues and scores
design-tree.txt DOM-like tree with CSS styles (~N tokens)
images/ PNG assets with human-readable names (hero-banner@2x.png)
vectors/ SVG assets for vector nodes
PROMPT.md Stack-specific code generation prompt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document images/mapping.json in the package layout.

implement now writes/copies that file when image assets are present, and the design tree uses it to replace [IMAGE] with url(images/...). Leaving it out here makes the documented output incomplete.

As per coding guidelines, "**/*.{ts,js}: If the code change introduces behavior that contradicts existing documentation (README.md, CLAUDE.md, JSDoc comments), flag it and suggest updating the relevant documentation to stay in sync."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/docs.ts` around lines 291 - 298, Update the documented package layout
under the OUTPUT section (the block starting with the literal header "OUTPUT"
and the list entries like "images/") to include the new images/mapping.json
file; add a line describing "images/mapping.json — JSON map used by the design
tree to replace [IMAGE] with url(images/...)" so the documented output matches
the implement behavior that writes/copies images/mapping.json and the design
tree uses it for image URL substitution.

Comment on lines 319 to 325
const DOCS_TOPICS: Record<string, () => void> = {
setup: printDocsSetup,
install: printDocsSetup, // alias
rules: printDocsRules,
config: printDocsConfig,
implement: printDocsImplement,
"visual-compare": printDocsVisualCompare,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update the invalid-topic hint for the new topic.

Adding implement here also needs the hard-coded list on Line 341 updated. Right now a typo like canicode docs implemnt tells users that implement is unavailable even though it is now routed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/docs.ts` around lines 319 - 325, The invalid-topic hint's hard-coded
list of available docs topics needs to include the new "implement" topic so
typed commands like `canicode docs implemnt` don't incorrectly indicate it's
unavailable; update the string list/message that prints available topics (the
code that references DOCS_TOPICS keys for the invalid-topic hint) to include
"implement" (match the key in DOCS_TOPICS) or, better, derive the hint
dynamically from DOCS_TOPICS' keys so the help output stays in sync with
DOCS_TOPICS (modify the code that currently prints the hard-coded list of topics
to use Object.keys(DOCS_TOPICS) or add "implement" to that literal list).

Comment on lines +888 to +923
const usedNames = new Map<string, number>();
const nodeIdToFilename = new Map<string, string>();
for (const { id, name } of imageNodes) {
let base = sanitizeFilename(name);
const count = usedNames.get(base) ?? 0;
usedNames.set(base, count + 1);
if (count > 0) base = `${base}-${count + 1}`;
nodeIdToFilename.set(id, `${base}@${imgScale}x.png`);
}

let imgDownloaded = 0;
for (const [id, imgUrl] of Object.entries(imageUrls)) {
if (!imgUrl) continue;
const filename = nodeIdToFilename.get(id);
if (!filename) continue;
try {
const resp = await fetch(imgUrl);
if (resp.ok) {
const buf = Buffer.from(await resp.arrayBuffer());
await writeFile(resolve(imageDir, filename), buf);
imgDownloaded++;
}
} catch {
// Skip failed downloads
}
}

const mapping: Record<string, string> = {};
for (const [id, filename] of nodeIdToFilename) {
mapping[id] = filename;
}
await writeFile(
resolve(imageDir, "mapping.json"),
JSON.stringify(mapping, null, 2),
"utf-8"
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Only persist mappings for image files that were actually written.

Both blocks build mapping.json from the requested node set, not from successful exports. If getNodeImages() omits a node or one fetch fails, generateDesignTreeWithStats() will still emit url(images/...) for a file that is not on disk, and the [IMAGE] fallback is lost. Track a separate downloaded-only mapping and serialize that instead.

Also applies to: 1135-1167

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/index.ts` around lines 888 - 923, The mapping.json is built from
nodeIdToFilename regardless of whether the image was actually downloaded; change
the code to only persist mappings for successfully written files by creating a
new Map or object (e.g., downloadedMapping) and, inside the successful
fetch/write branch (the block where resp.ok and writeFile succeed), add
downloadedMapping.set(id, filename) (or downloadedMapping[id] = filename); after
the download loop serialize downloadedMapping to mapping.json instead of
nodeIdToFilename; apply the same change to the other image-export loop
referenced (the block analogous around generateDesignTreeWithStats) so
mapping.json contains only files that exist on disk.

Comment on lines +1016 to +1026
.action(async (input: string, options: ImplementOptions) => {
try {

const outputDir = resolve(options.output ?? "canicode-implement");
mkdirSync(outputDir, { recursive: true });

console.log("\nPreparing implementation package...\n");

// 1. Load file
const { file } = await loadFile(input, options.token);
console.log(`Design: ${file.name}`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Warn before packaging an unscoped Figma URL.

implement silently processes the entire file when node-id is missing. The other CLI entry points already warn in that case, and this new command can produce unexpectedly large prompts and asset downloads.

📝 Suggested fix
  .action(async (input: string, options: ImplementOptions) => {
    try {
+      if (isFigmaUrl(input) && !parseFigmaUrl(input).nodeId) {
+        console.warn("\nWarning: No node-id specified. Implementing entire file may produce a very large package.");
+        console.warn("Tip: Add ?node-id=XXX to target a specific section.\n");
+      }
+
       const outputDir = resolve(options.output ?? "canicode-implement");
       mkdirSync(outputDir, { recursive: true });
As per coding guidelines, "`src/cli/**/*.{ts,tsx}`: If no `node-id` is provided to the CLI, print a warning."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/index.ts` around lines 1016 - 1026, In the Implement CLI action
handler (the async .action callback in src/cli/index.ts), detect when
options.nodeId (or equivalent node-id property on ImplementOptions) is not
provided and emit a visible warning before proceeding (e.g., console.warn or
processLogger.warn) that the command will process the entire Figma file and may
produce large prompts/assets; place this check just before calling loadFile or
packaging so users see it early and keep existing behavior when nodeId is
present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: design-to-code를 사용자 구현 도구로 제공 (에셋 매핑 + 스택 유연화)

1 participant