Commit graph

89 commits

Author SHA1 Message Date
Danila Poyarkov 1aa10a4fed
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 05:00:31 +04:00
Danila Poyarkov e532f616ba
refactor!: move shared primitives below dom-css and core (#771)
* refactor!: move shared primitives below dom-css and core

dom-css depended on core for color conversion, base64 helpers, text
direction, and web-font assets, so core could not use dom-css and every
caller special-cased HTML and Tailwind output.

Color conversion and management, base64 helpers, and text/layout
direction now live in scene-graph under `color`, `bytes`, and
`text-direction`. dom-css takes web-font resolution as an injected
`fonts` option and owns the font face types, so it depends only on
scene-graph and core can depend on it.

BREAKING CHANGE: `@open-pencil/core/color` and `@open-pencil/core/bytes`
are removed, and the direction helpers are no longer exported from
`@open-pencil/core/text`; import them from `@open-pencil/scene-graph`
subpaths. `exportHTMLBundle` takes a font resolver in `fonts` instead of
`'assets'`.

* fix(tools): import color parsing from scene-graph in visual bisect

* fix(mcp): declare the scene-graph dependency

MCP imports `@open-pencil/scene-graph/bytes` since base64 helpers moved
there, but only reached scene-graph through core, so isolated installs
and package checks depended on transitive resolution.

* refactor!: use js-base64 directly instead of a base64 wrapper

Base64 helpers had moved into scene-graph only to sit below dom-css,
but they are a thin wrapper over js-base64 and unrelated to the graph;
fig already called js-base64 directly.

Callers use js-base64 and check `isValid` where input comes from outside
(clipboard, imported HTML, tool arguments, the plugin API). A new
`open-pencil/no-hand-rolled-base64` lint rule rejects atob, btoa, and
Buffer Base64 conversions, and AGENTS.md records the convention.

BREAKING CHANGE: `@open-pencil/core/bytes` is removed; use `js-base64`.

* fix(dom-css): keep images with invalid Base64 inline in HTML export

`exportHTMLBundle` accepts documents parsed from outside HTML, and
js-base64 drops characters it cannot decode, so extracting an invalid
image data URL wrote different bytes. Such images now stay inline.
2026-09-26 11:39:11 +04:00
Danila Poyarkov 8131401ead
fix: explain unsupported browsers instead of a blank window (#745)
* fix: explain unsupported browsers instead of a blank window

The desktop app on macOS 13 with WebKit older than Safari 17.4 opened an
empty window because startup called Promise.withResolvers, which Vite lowers
nothing for: build.target only rewrites syntax and never polyfills APIs, and
the target itself was an implicit Vite default (#744).

Make the supported baseline explicit in src/app/shell/support/baseline.ts and
feed it to build.target, a lint rule that rejects newer static built-ins in
browser-shipped sources, and the documented system requirements. Replace
Promise.withResolvers with a createDeferred() helper.

Turn src/main.ts into a small gate that checks sentinel features before
dynamically importing the app, so an old engine still evaluates enough code
to render platform-specific update guidance: macOS/Safari via Software
Update, WebKitGTK and WebView2 on Linux and Windows, and each browser's
own update path on the web, with a prefilled bug report link. Render-blocking
errors during the first route are captured through app.config.errorHandler
and shown the same way instead of leaving the window blank.

Desktop facts come from tauri-plugin-os and a webview_version command; the
bundle now declares macOS 13 as its minimum system version.

* build: enforce the browser baseline from compatibility data

Replace the hand-maintained list of built-ins newer than the baseline with
two data-driven checks. The app and browser-shipped packages pin their
TypeScript lib to ES2023, the last edition Chrome 111, Firefox 128 and
Safari 16.4 implement in full, so a newer built-in such as
Promise.withResolvers fails type-checking. Web APIs, which lib.dom does not
version, go through eslint-plugin-compat under oxlint with the same browsers
in settings.browsers, scoped to sources that ship to a browser.

A unit test keeps the oxlint browser list and the tsconfig libs derived from
src/app/shell/support/baseline.ts, so the three cannot drift apart.

* fix: recognise production error codes in the boot observer

Vue passes the error reference URL as the errorHandler info argument in
production builds instead of the development string, so the observer never
classified a setup or render failure as fatal in the shipped app and the
boot-failure notice only appeared on the dev server. Match Vue's exported
ErrorCodes in both forms, and cover the component-setup path in the E2E
spec; the scenario was also verified against a production build.
2026-09-22 14:40:59 +04:00
Danila Poyarkov f2bfaba287 refactor: narrow lint policies and consolidate their support
Remove the disabled widening audit and its resolver. Fix Bun aliases and bounded reducer slices, reject parser failures in shared fixtures, and retain upstream attribution in NOTICE.
2026-09-14 10:10:27 +03:00
Danila Poyarkov 4317a352a0 feat(lint): reject low-evidence test and type patterns
Prevent module registry mocking, repeated reducer accumulator copies, and local widen-then-assert flows. Keep known-value widening available for audits without enabling its noisy global policy, and record upstream provenance for the adapted rules.
2026-09-11 11:57:29 +03:00
Danila Poyarkov 9bb9478833
refactor: replace complex conditional object spreads
- Add a typed, modular custom Oxlint rule package with direct regression coverage
- Replace complex conditional object spreads with explicit construction across the repository
- Preserve all existing custom rule registrations and diagnostic behavior
2026-09-01 19:49:57 +03:00
フォン 88c1077071
fix(cli): use Node fs for import command
Fixes openpencil import under Node.js by replacing Bun filesystem globals with node:fs/promises. Enforces the CLI runtime boundary through lint.
2026-08-24 20:26:52 +03:00
Danila Poyarkov 7f91594d0c refactor: standardize acronym casing
- Rename first-party API, RPC, JSON, CORS, SVG, JSX, and related identifiers to preserve acronym casing
- Keep upstream and serialized boundary names unchanged
- Add a lint guardrail and migration notes for exported APIs
2026-08-10 15:48:16 +03:00
Danila Poyarkov 9498dc203d chore(tools): harden package and dependency checks 2026-07-01 12:56:45 +03:00
Danila Poyarkov b5665afab5 fix(tauri): restore desktop clipboard access 2026-07-01 10:40:29 +03:00
Danila Poyarkov c1207f1be3 refactor(ui): organize app component domains
- Move root-level picker, input, and menu components into lowercase domain folders
- Update component namespace linting for kebab-case app domains
- Document FSD-lite component structure in AGENTS.md
2026-07-01 09:58:10 +03:00
Danila Poyarkov cde9cd4610 test(arch): guard panel UI conventions 2026-06-30 23:50:15 +03:00
Danila Poyarkov 898431e646 feat: split SceneGraph and Pen packages 2026-06-30 10:54:32 +03:00
Danila Poyarkov f5bd2425b6 feat(kiwi): scaffold standalone Kiwi package 2026-06-30 10:48:47 +03:00
Danila Poyarkov 72e3bc4fb5 chore: organize repo tooling under tools 2026-06-07 09:40:54 +03:00
Danila Poyarkov 2f8dfd883a chore(lint): catch duplicate type shapes
- Add AST-based duplicate object type shape detection
- Reuse shared variable consumption and visual bounds type shapes
- Keep duplicate type shape checks in the default lint gate
2026-05-25 00:47:33 +03:00
Danila Poyarkov 1ed7de6056 chore(lint): reject broad unknown type assertions
- Add AST-based lint checks for broad unknown object assertions and local JsonObject aliases
- Centralize JsonObject in core and package-local MCP RPC JSON typing
- Replace baseline Record<string, unknown> assertions with named shared/domain types
2026-05-25 00:26:02 +03:00
Danila Poyarkov 54310308dc refactor(kiwi): split schema text from runtime
- Move the Kiwi runtime under schema-runtime to match folder naming
- Load the Figma schema from a .kiwi text asset with static validation
- Assert Figma clipboard-derived field numbers for fragile layout/text fields
2026-05-21 14:54:12 +03:00
Danila Poyarkov 3a85632f38 refactor(ui): localize tooltip labels 2026-05-19 15:41:38 +03:00
Danila Poyarkov f4454aeb44 fix(mcp): report version mismatches 2026-05-19 11:12:01 +03:00
Danila Poyarkov f3649550f2 chore: enable stricter oxlint rules 2026-05-18 18:58:30 +03:00
Danila Poyarkov 92328a21d8 build(lint): enforce shared black color constants 2026-05-17 18:05:07 +03:00
Danila Poyarkov 29d7ae4817 refactor(vue): centralize canvas menu groups 2026-05-17 14:09:52 +03:00
Danila Poyarkov 8476ab2c99 chore(vue): guard browser side effects 2026-05-15 17:47:40 +03:00
Danila Poyarkov 4e942f77d7 chore(test): lint raw test id selectors 2026-05-15 17:10:35 +03:00
Danila Poyarkov 4a174e52ed chore(vue): lint generated test id literals 2026-05-15 13:14:51 +03:00
Danila Poyarkov 5f3a4f7816 chore(vue): prefer test id directive 2026-05-15 12:47:01 +03:00
Danila Poyarkov cb1c52521b chore(vue): enforce shared test id prop types 2026-05-15 12:21:08 +03:00
Danila Poyarkov 0749bfa755 chore(vue): standardize test id helpers 2026-05-15 12:07:58 +03:00
Danila Poyarkov e2eaf85cff chore(vue): enable stricter prop linting 2026-05-15 11:57:38 +03:00
Danila Poyarkov b46295a7bb fix(editor): close padding editor on canvas click 2026-05-15 11:49:18 +03:00
Danila Poyarkov 3eedd0740e chore: move code-pattern checks to oxlint 2026-05-14 22:22:07 +03:00
Danila Poyarkov c2afb8ddca chore(lint): enforce type safety in scripts
- Fix non-null assertions in visual-compare script
- Fix missing radix parameter
- Replace ImageMagick rgba() color with hex notation
- Remove no-non-null-assertion, no-hand-rolled-color, and radix script overrides
- Keep only no-console override for CLI scripts
2026-05-06 16:41:40 +03:00
Danila Poyarkov dfa9505805 chore(lint): enforce domain prefix folders project-wide
- Generalize sibling domain prefix linting beyond tests
- Move create icon tools under the existing create domain folder
- Keep create.ts exporting the icon tools through the domain folder
2026-05-06 14:33:17 +03:00
Danila Poyarkov aad26b535e test: move prefixed splits into domain folders
- Move newly split tests under explicit domain subfolders
- Update nested helper imports after the moves
- Add a lint guard against repeating existing sibling domains as filename prefixes
2026-05-06 14:27:21 +03:00
Danila Poyarkov b9da0dcb76 chore(lint): enforce test complexity limits
- Extract color picker fill comparison helpers
- Guard derived text assertions without optional chains
- Split resize math into smaller helper functions
- Remove the remaining complexity test exceptions
2026-05-06 14:18:29 +03:00
Danila Poyarkov 13a3475026 test(layout): split auto-layout coverage
- Move auto-layout tests into focused files by layout behavior
- Preserve sizing, wrapping, text measurement, and positioning coverage
- Remove the last max-lines test exception
2026-05-06 14:10:20 +03:00
Danila Poyarkov 5e7c042352 test(scene-graph): split basic coverage
- Move scene graph behavior tests into focused files
- Share basic scene graph helper builders from basic/helpers.ts
- Remove scene graph basic from max-lines exceptions
2026-05-06 14:05:58 +03:00
Danila Poyarkov c589818a71 test(clipboard): split node import coverage
- Move clipboard node import tests into focused files by behavior
- Preserve filtering, hierarchy, styling, component, and undo coverage
- Remove import-nodes from max-lines exceptions
2026-05-06 14:01:18 +03:00
Danila Poyarkov 9ebc61d78f test(figma): split API coverage
- Move FigmaAPI tests into focused files by feature area
- Share API construction from figma/api/helpers.ts
- Remove FigmaAPI coverage from max-lines exceptions
2026-05-06 13:37:15 +03:00
Danila Poyarkov 54ccc35e3e test(fig): split legacy import coverage
- Move legacy fig import tests into focused domain files
- Share NodeChange fixture builders from legacy/helpers.ts
- Remove legacy import from max-lines exceptions
2026-05-06 13:33:42 +03:00
Danila Poyarkov 42d346ba47 test(kiwi): split serialization regression coverage
- Move Kiwi serialization fix tests into one file per regression area
- Share codec setup and Kiwi helpers from serialize-fixes/helpers.ts
- Remove serialize fixes from max-lines exceptions
2026-05-06 13:12:53 +03:00
Danila Poyarkov 24629610a4 test(render): split canvas effect coverage
- Move canvas effect renderer tests into focused files by behavior
- Share renderer and canvas mocks from effects/helpers.ts
- Remove canvas effects from max-lines exceptions
2026-05-06 13:05:51 +03:00
Danila Poyarkov 93d5370d7d test(svg): split SVG export coverage
- Move SVG builder, path, and render export tests into focused files
- Share SVG export helpers from tests/engine/svg/export/helpers.ts
- Remove svg export from max-lines exceptions
2026-05-06 12:57:54 +03:00
Danila Poyarkov 21a3337a96 chore(tests): enforce no-empty-function
- Replace remaining empty mock callbacks with explicit undefined returns
- Remove the last no-empty-function test exceptions
- Validate check and affected renderer/text tests
2026-05-06 12:40:42 +03:00
Danila Poyarkov 432f945da6 chore(tests): narrow no-empty-function exceptions
- Replace simple no-op test callbacks with explicit undefined returns
- Remove no-empty-function exceptions for autosave, stroke picker, font settings, pen, tauri, AI adapter, and undo helper tests
- Validate check plus affected engine and E2E tests
2026-05-06 12:32:54 +03:00
Danila Poyarkov bbf122a5c5 chore(tests): route store access through browser bridge
- Expose window.openPencil.getStore() instead of a direct store property
- Update E2E helpers and specs to use the bridge getter
- Add lint coverage preventing direct window.openPencil.store access
2026-05-06 12:19:39 +03:00
Danila Poyarkov 657188b097 chore(tests): enforce non-null assertion rule
- Remove remaining test non-null assertions and delete the broad test override
- Add explicit guards for canvas, design panel, auto-layout, SVG, Kiwi, hit-test, scene graph, text editor, and clipboard tests
- Validate check plus affected engine and E2E coverage
2026-05-06 11:44:18 +03:00
Danila Poyarkov 8ec70330b4 chore(lint): centralize OpenPencil window API
- Route browser globals through src/app/window-api.ts instead of private __OPEN_PENCIL fields
- Move E2E tests to the public window.openPencil test API
- Add an oxlint rule banning direct window.__OPEN_PENCIL* access
2026-05-06 10:38:03 +03:00
Danila Poyarkov 9e4d7bee5d chore(lint): fix unused test code
- Remove stale imports and unused locals from split engine and e2e tests
- Drop the targeted no-unused-vars test allowances
- Keep check and affected test suites warning-free
2026-05-06 02:53:19 +03:00