Skip to content

feat(icon): add comark-icon, Iconify icons in Markdown drawn as CSS, and a resolver other plugins share - #54

Merged
vitehub-bot[bot] merged 8 commits into
mainfrom
feat/icon
Oct 21, 2026
Merged

vitehub-bot[bot] merged 8 commits into
mainfrom
feat/icon

Conversation

@onmax

@onmax onmax commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Stacked on #50. Adds comark-icon, an icon package for Comark modelled on Nuxt Icon. It has two jobs: an inline :icon component, and an icon resolver that other plugins share. #51 (tab icons) will be rebased onto it.

Press :icon{name="lucide:command"} K to search.
Built with :icon{name="logos:vue" label="Vue"}.

How it works

  • Resolving. Icons are resolved while parsing: first from collections, then from the Iconify API. The API is on by default, as in Nuxt Icon. fetch: false turns it off, and a URL points it at an Iconify API of your own. A collection is an @iconify-json/* set, or SVG markup by name for icons of your own. Downloads are cached once per process, and each request holds sorted names and stays under 500 characters, as Iconify asks.
  • Drawing. Each icon is a CSS image in a .ci span, so the page makes no request for it and it shows without a script. An icon that paints with currentColor becomes a mask in the text colour; any other is a background image. This is the same rule Nuxt Icon's CSS mode, UnoCSS preset-icons and @iconify/utils' getIconCSS use.
  • Names. Write set:name. Nuxt UI's i-lucide-apple and i-lucide:apple also work, since agents copy them from Nuxt UI and Comark docs. Hyphenated set names such as i-simple-icons-github are matched against Iconify's hyphenated prefixes.
  • Accessibility. An icon without label is decorative (aria-hidden). An icon with label gets role="img" and the label as its name.
  • Forced colors. Without forced-color-adjust: preserve-parent-color, Chromium paints mask icons in the page background colour and they vanish. I confirmed this with Playwright's forced-colors emulation: without the rule, the sidebar icons disappear; with it, they show in the system link colour.
  • Errors. An icon the plugin can't draw goes into meta.issues, naming the icon and the fix, and is left out of the page. The cases are a missing name, a malformed name, an unknown set or icon, and a failed request.
  • Renderers. HTML, Vue, React and Svelte output the same markup, and a test checks that. There is a component per renderer because @comark/react splits a style string at every :, which would cut the data: URL.
  • For other plugins. createIcons(options) returns a resolver with resolve(names) that never throws. describeIconProblem() words a problem the same way the :icon plugin does, and iconHtml()/iconStyles() or the Icon components draw the result.

Docs

  • docs/pages/icon/ adds the package's pages: overview, getting started, syntax and guides.
  • The site's sidebar and buttons now draw their icons with comark-icon from @iconify-json/lucide, replacing the hand-copied SVGs. The site's own icons don't touch the network: they use fetch: false.
  • The playground loads the plugin, and so does comark-lint, as an optional peer.

Decisions to review

  • The API is on by default. Output depends on Iconify unless a site passes collections. Iconify calls use outside its own components a "bonus that should not be abused", so requests are batched and cached.
  • Inline styles. Each icon carries its data URI in a style attribute, so a strict CSP needs style-src-attr 'unsafe-inline' and img-src data:. One stylesheet per document would avoid that, but I haven't tested it across the renderers.
  • No keyword map (such as pnpm → vscode-icons:file-type-pnpm) and no aliases. Tabs keeps its label-to-icon map in feat(tabs): add an icon prop, drawn by comark-icon from Iconify names or image URLs #51.
  • New dependencies: @iconify/utils (about 2 KB gzip for the functions used, with no Node built-ins) and @iconify/types. The root gains @iconify-json/lucide as a dev dependency.

Before release

comark-icon is a new package. It needs a trusted publisher on npmjs.com, with workflow release.yaml and environment npm, before its first release.

Checks

  • comark-icon tests: 11 passed.
  • The full suite: 193 passed.
  • vp check reports 0 errors; its 2 warnings are already in e2e/annotate.e2e.ts.
  • Vite Doctor on comark-icon: 0 warnings.
  • The docs build passes.
  • I checked the docs pages in a browser in light and dark mode, and under forced colors.

🤖 Generated with Claude Code

@pkg-pr-new

pkg-pr-new Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

comark-annotate

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-annotate@54

comark-carousel

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-carousel@54

comark-charts

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-charts@54

comark-code

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-code@54

comark-embed

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-embed@54

comark-github-callouts

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-github-callouts@54

comark-icon

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-icon@54

comark-include

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-include@54

comark-lint

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-lint@54

comark-tabs

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-tabs@54

comark-zoom

pnpm add https://pkg.pr.new/onmax/comark-plugins/comark-zoom@54

commit: 7134f5a

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 7134f5a 2026-10-21T11:04:51.643Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 21d474e 2026-10-21T10:42:23.820Z Visit the dashboard ↗
  • Build: Failed ❌

View logs ↗
72302ea 2026-10-21T10:31:30.940Z View logs ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 83b7f8a 2026-10-21T10:25:41.095Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ ae7e627 2026-10-21T09:58:36.752Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 161e6f2 2026-10-21T09:17:35.449Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ b37e707 2026-10-21T08:25:38.115Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ c81cb22 2026-10-21T08:14:51.644Z Visit the dashboard ↗
  • Build: Success ✅

View logs ↗
No Preview URL. Enable ↗ 95cb8b0 2026-10-21T07:42:42.117Z Visit the dashboard ↗

@vitehub-bot

vitehub-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor
Session Status Started Duration
Pending Completed Not started —
View session Starting Not started —

Latest result

Pull request merged.

Final answers

Session

Pull request merged.

Session

Waiting for GitHub merge request 0a2c1b0b-f79d-4fc8-9ec5-245845ffc3d5.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

Session

Fixed the required Doctor check failure (P1): removed the runtime typeof narrowing warning in comark-icon, resolved the prepared AGENTS.md conflict, and pushed one repair commit. Focused Vite Doctor now reports 0 warnings, errors, and blockers. Awaiting current-head checks and automated review.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

This PR has two input-validation and diagnostics issues that can produce the wrong icon or misleading remediation for supported custom collections.

Reviewed changes

  • Icon resolver — adds collection-first and Iconify API resolution with batching, caching, and problem values instead of thrown errors.
  • Markdown plugin — resolves :icon attributes during parsing, keeps draw data on valid nodes, removes invalid nodes, and appends readable issues.
  • Renderer integrations — adds shared CSS output and HTML, Vue, React, and Svelte components with matching accessibility behavior.
  • Package and docs integration — publishes the new package, wires it into the docs site and optional lint configuration, and documents offline/custom collection usage.

Note: 1 inline comment(s) dropped because they did not anchor to lines inside the PR diff:

  • packages/icon/src/resolve.ts:1093 (RIGHT) — line 1093 (RIGHT) is not inside a diff hunk

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

Comment thread packages/icon/src/resolve.ts Outdated
Base automatically changed from docs/package-sections to main October 21, 2026 08:24

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The incremental component escaping change is safe, but the PR still accepts malformed set:name values that can resolve and render a different icon than the author requested.

Reviewed changes

The incremental review covered the new component-side CSS URL escaping and its regression test, with the full PR diff and existing review feedback rechecked for context.

  • Escaped component sources — Kept arbitrary src values inside the quoted CSS url() used by the shared React, Vue, Svelte, and HTML rendering paths.
  • Added regression coverage — Verified that a component-provided source containing CSS delimiter characters is percent-encoded in the rendered React style.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

Comment thread packages/icon/src/resolve.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ℹ️ No new issues found in the latest commit; the previously reported resolver findings remain open.

Reviewed changes

  • Component CSS URL escaping — Applied shared escaping for quotes, backslashes, and CSS line-break characters before component-provided src values enter the quoted url() declaration, and added a React regression test covering an injection-shaped value.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The malformed icon-name validation finding from the prior review remains unresolved; this is not a new delta issue, but the PR cannot be approved while it is open.

Reviewed changes

The incremental review rechecked the component-side CSS URL escaping commit and the full PR context, including the previously reported resolver validation finding.

  • Escaped component sources — Kept arbitrary component-provided src values inside the quoted CSS url() declaration and added a regression test for CSS delimiter characters.

Focused verification was attempted, but the workspace install hook could not run because the environment cannot lock .git/config on its read-only filesystem.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

Comment thread packages/icon/src/resolve.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

The incremental review covered the commits since the prior Pullfrog review, with the full PR diff rechecked for context.

  • Rejected malformed icon names — Added validation for extra colon segments so malformed values fail before collection lookup, API batching, or rendering, and added regression coverage for the resulting issue and output.
  • Formatted docs resolver setup — Reformatted the docs build's shared icon resolver call without changing its behavior.

The focused test command could not run because the workspace's pnpm install prepare hook cannot lock .git/config in this read-only environment; source inspection and the incremental regression coverage found no remaining issue in the new commits.

Pullfrog  | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

The incremental review covered the dependency/catalog lockfile normalization and the lint integration changes since the prior Pullfrog review, with the complete PR diff rechecked for context.

  • Normalized workspace dependencies — Added the new package and docs dependencies to the workspace catalog and lockfile without changing runtime behavior.
  • Registered the lint plugin — Added comark-icon/html as an optional package in comark-lint, allowing installed projects to lint icon nodes and use its renderer components.
  • Retired resolver feedback — Confirmed the malformed-name validation is implemented and the prior Pullfrog threads were addressed and resolved.

The focused commands were attempted, but the workspace prepare hook failed with error: could not lock config file .git/config: Read-only file system; lockfile policy validation completed successfully during installation.

Pullfrog  | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The new zoom scroll-lock path can reserve the scrollbar gutter twice when the page already uses scrollbar-gutter: stable, causing a visible width shift while the zoom is open.

Reviewed changes

  • Reworked zoom scroll locking — Replaced the supported scrollbar-gutter assignment with unconditional padding-right reservation before hiding document overflow.
  • Normalized workspace integration — Updated dependency catalog and lockfile entries and registered comark-icon/html with the optional lint plugin configuration.

Note: 1 inline comment(s) dropped because they did not anchor to lines inside the PR diff:

  • packages/zoom/src/script.ts:1583 (RIGHT) — line 1583 (RIGHT) is not inside a diff hunk

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Resolved docs integration conflicts — Restored the docs section heading markup and retained the mono font preload while keeping the generated icon stylesheet in the page shell.

Pullfrog  | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

This incremental review covered the changes since the prior Pullfrog review: repaired the docs build's shared icon integration and tightened the plugin option check while rechecking the complete PR diff for context.

  • Repaired docs icon integration — Switched the generated docs site's icon helper to the shared comark-icon resolver, retained the custom scribble icon collection, and preserved the generated icon stylesheet in the page shell.
  • Tightened resolver detection — Required an object before treating plugin options as a shared resolver, avoiding incorrect handling of primitive option values.

Focused verification was attempted, but both commands were blocked by the workspace prepare hook: error: could not lock config file .git/config: Read-only file system. The lockfile supply-chain policy check passed; source inspection found no new issue in this delta.

Pullfrog  | View workflow run | Using gpt-5.6-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The latest commit makes a truthy primitive plugin option throw during plugin initialization instead of falling back to the normal icon options path.

Reviewed changes

The incremental review covered the commits since the prior Pullfrog review, with the complete PR diff rechecked for context.

  • Merged the code package integration — Added comark-code to the repository documentation, docs build, workspace dependencies, and lint's optional package discovery.
  • Changed icon option detection — Replaced the object guard around shared resolver detection with a direct in check while preserving the docs icon integration and existing resolver behavior.

Focused verification was blocked by the workspace prepare hook: error: could not lock config file .git/config: Read-only file system; lockfile policy validation completed before the hook failure.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-5.6-sol | 𝕏

Comment thread packages/icon/src/index.ts
@vitehub-bot

vitehub-bot Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Pullfrog: P2 runtime edge case; IconOptions | Icons excludes primitive values, so this does not affect a supported typed path, and the repair window forbids a push for this pass.

@vitehub-bot
vitehub-bot Bot merged commit 6a9ccdf into main Oct 21, 2026
8 of 9 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 21, 2026
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.

1 participant