mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
Merge remote-tracking branch 'origin/main' into staging
This commit is contained in:
commit
8928e274fc
168
AGENTS.md
168
AGENTS.md
@ -1,139 +1,63 @@
|
||||
# IA Agent guide for Penpot monorepo
|
||||
# AI Agent Guide
|
||||
|
||||
This document provides comprehensive context and guidelines for AI
|
||||
agents working on this repository.
|
||||
This document provides the core context and operating guidelines for AI agents
|
||||
working in this repository.
|
||||
|
||||
CRITICAL: When you encounter a file reference (e.g.,
|
||||
@rules/general.md), use your Read tool to load it on a need-to-know
|
||||
basis. They're relevant to the SPECIFIC task at hand.
|
||||
## Before You Start
|
||||
|
||||
Before responding to any user request, you must:
|
||||
|
||||
## STOP - DO NOT PROCEED WITHOUT COMPLETING THESE STEPS
|
||||
1. Read this file completely.
|
||||
2. Identify which modules are affected by the task.
|
||||
3. Load the `AGENTS.md` file **only** for each affected module (see the
|
||||
architecture table below). Not all modules have an `AGENTS.md` — verify the
|
||||
file exists before attempting to read it.
|
||||
4. Do **not** load `AGENTS.md` files for unrelated modules.
|
||||
|
||||
Before responding to ANY user request, you MUST:
|
||||
## Role: Senior Software Engineer
|
||||
|
||||
1. **READ** the CONTRIBUTING.md file
|
||||
2. **READ** this file and has special focus on your ROLE.
|
||||
You are a high-autonomy Senior Full-Stack Software Engineer. You have full
|
||||
permission to navigate the codebase, modify files, and execute commands to
|
||||
fulfill your tasks. Your goal is to solve complex technical tasks with high
|
||||
precision while maintaining a strong focus on maintainability and performance.
|
||||
|
||||
### Operational Guidelines
|
||||
|
||||
## ROLE: SENIOR SOFTWARE ENGINEER
|
||||
1. Before writing code, describe your plan. If the task is complex, break it
|
||||
down into atomic steps.
|
||||
2. Be concise and autonomous.
|
||||
3. Do **not** touch unrelated modules unless the task explicitly requires it.
|
||||
4. Commit only when explicitly asked. Follow the commit format rules in
|
||||
`CONTRIBUTING.md`.
|
||||
5. When searching code, prefer `ripgrep` (`rg`) over `grep` — it respects
|
||||
`.gitignore` by default.
|
||||
|
||||
You are a high-autonomy Senior Software Engineer. You have full
|
||||
permission to navigate the codebase, modify files, and execute
|
||||
commands to fulfill your tasks. Your goal is to solve complex
|
||||
technical tasks with high precision, focusing on maintainability and
|
||||
performance.
|
||||
## Architecture Overview
|
||||
|
||||
Penpot is an open-source design tool composed of several modules:
|
||||
|
||||
### OPERATIONAL GUIDELINES
|
||||
| Directory | Language | Purpose | Has `AGENTS.md` |
|
||||
|-----------|----------|---------|:----------------:|
|
||||
| `frontend/` | ClojureScript + SCSS | Single-page React app (design editor) | Yes |
|
||||
| `backend/` | Clojure (JVM) | HTTP/RPC server, PostgreSQL, Redis | Yes |
|
||||
| `common/` | Cljc (shared Clojure/ClojureScript) | Data types, geometry, schemas, utilities | Yes |
|
||||
| `render-wasm/` | Rust -> WebAssembly | High-performance canvas renderer (Skia) | Yes |
|
||||
| `exporter/` | ClojureScript (Node.js) | Headless Playwright-based export (SVG/PDF) | No |
|
||||
| `mcp/` | TypeScript | Model Context Protocol integration | No |
|
||||
| `plugins/` | TypeScript | Plugin runtime and example plugins | No |
|
||||
|
||||
1. Always begin by analyzing this document and understand the
|
||||
architecture and read the additional context from AGENTS.md of the
|
||||
affected modules.
|
||||
2. Before writing code, describe your plan. If the task is complex,
|
||||
break it down into atomic steps.
|
||||
3. Be concise and autonomous as possible in your task.
|
||||
4. Commit only if it explicitly asked, and use the CONTRIBUTING.md
|
||||
document to understand the commit format guidelines.
|
||||
5. Do not touch unrelated modules if not proceed or not explicitly
|
||||
asked (per example you probably do not need to touch and read
|
||||
docker/ directory unless the task explicitly requires it)
|
||||
6. When searching code, always use `ripgrep` (rg) instead of grep if
|
||||
available, as it respects `.gitignore` by default.
|
||||
Some submodules use `pnpm` workspaces. The root `package.json` and
|
||||
`pnpm-lock.yaml` manage shared dependencies. Helper scripts live in `scripts/`.
|
||||
|
||||
|
||||
## ARCHITECTURE OVERVIEW
|
||||
|
||||
Penpot is a full-stack design tool composed of several distinct
|
||||
components separated in modules and subdirectories:
|
||||
|
||||
| Component | Language | Role | IA Agent CONTEXT |
|
||||
|-----------|----------|------|----------------
|
||||
| `frontend/` | ClojureScript + SCSS | Single-page React app (design editor) | @frontend/AGENTS.md |
|
||||
| `backend/` | Clojure (JVM) | HTTP/RPC server, PostgreSQL, Redis | @backend/AGENTS.md |
|
||||
| `common/` | Cljc (shared Clojure/ClojureScript) | Data types, geometry, schemas, utilities | @common/AGENTS.md |
|
||||
| `exporter/` | ClojureScript (Node.js) | Headless Playwright-based export (SVG/PDF) | @exporter/AGENTS.md |
|
||||
| `render-wasm/` | Rust → WebAssembly | High-performance canvas renderer using Skia | @render-wasm/AGENTS.md |
|
||||
| `mcp/` | TypeScript | Model Context Protocol integration | @mcp/AGENTS.md |
|
||||
| `plugins/` | TypeScript | Plugin runtime and example plugins | @plugins/AGENTS.md |
|
||||
|
||||
Several of the mentionend submodules are internall managed with `pnpm` workspaces.
|
||||
|
||||
|
||||
## COMMIT FORMAT
|
||||
|
||||
We have very precise rules on how our git commit messages must be
|
||||
formatted.
|
||||
|
||||
The commit message format is:
|
||||
### Module Dependency Graph
|
||||
|
||||
```
|
||||
<type> <subject>
|
||||
|
||||
[body]
|
||||
|
||||
[footer]
|
||||
frontend ──> common
|
||||
backend ──> common
|
||||
exporter ──> common
|
||||
frontend ──> render-wasm (loads compiled WASM)
|
||||
```
|
||||
|
||||
Where type is:
|
||||
|
||||
- :bug: `:bug:` a commit that fixes a bug
|
||||
- :sparkles: `:sparkles:` a commit that adds an improvement
|
||||
- :tada: `:tada:` a commit with a new feature
|
||||
- :recycle: `:recycle:` a commit that introduces a refactor
|
||||
- :lipstick: `:lipstick:` a commit with cosmetic changes
|
||||
- :ambulance: `:ambulance:` a commit that fixes a critical bug
|
||||
- :books: `:books:` a commit that improves or adds documentation
|
||||
- :construction: `:construction:` a WIP commit
|
||||
- :boom: `:boom:` a commit with breaking changes
|
||||
- :wrench: `:wrench:` a commit for config updates
|
||||
- :zap: `:zap:` a commit with performance improvements
|
||||
- :whale: `:whale:` a commit for Docker-related stuff
|
||||
- :paperclip: `:paperclip:` a commit with other non-relevant changes
|
||||
- :arrow_up: `:arrow_up:` a commit with dependency updates
|
||||
- :arrow_down: `:arrow_down:` a commit with dependency downgrades
|
||||
- :fire: `:fire:` a commit that removes files or code
|
||||
- :globe_with_meridians: `:globe_with_meridians:` a commit that adds or updates
|
||||
translations
|
||||
|
||||
The commit should contain a sign-off at the end of the patch/commit
|
||||
description body. It can be automatically added by adding the `-s`
|
||||
parameter to `git commit`.
|
||||
|
||||
This is an example of what the line should look like:
|
||||
|
||||
```
|
||||
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
|
||||
```
|
||||
|
||||
Please, use your real name (sorry, no pseudonyms or anonymous
|
||||
contributions are allowed).
|
||||
|
||||
CRITICAL: The commit Signed-off-by is mandatory and should match the commit author.
|
||||
|
||||
Each commit should have:
|
||||
|
||||
- A concise subject using the imperative mood.
|
||||
- The subject should capitalize the first letter, omit the period
|
||||
at the end, and be no longer than 65 characters.
|
||||
- A blank line between the subject line and the body.
|
||||
- An entry in the CHANGES.md file if applicable, referencing the
|
||||
GitHub or Taiga issue/user story using these same rules.
|
||||
|
||||
Examples of good commit messages:
|
||||
|
||||
- `:bug: Fix unexpected error on launching modal`
|
||||
- `:bug: Set proper error message on generic error`
|
||||
- `:sparkles: Enable new modal for profile`
|
||||
- `:zap: Improve performance of dashboard navigation`
|
||||
- `:wrench: Update default backend configuration`
|
||||
- `:books: Add more documentation for authentication process`
|
||||
- `:ambulance: Fix critical bug on user registration process`
|
||||
- `:tada: Add new approach for user registration`
|
||||
|
||||
More info:
|
||||
|
||||
- https://gist.github.com/parmentf/035de27d6ed1dce0b36a
|
||||
- https://gist.github.com/rxaviers/7360908
|
||||
|
||||
|
||||
`common` is referenced as a local dependency (`{:local/root "../common"}`) by
|
||||
both `frontend` and `backend`. Changes to `common` can therefore affect multiple
|
||||
modules — test across consumers when modifying shared code.
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
- Fix tooltip activated when tab change [Taiga #13627](https://tree.taiga.io/project/penpot/issue/13627)
|
||||
|
||||
|
||||
## 2.14.0 (Unreleased)
|
||||
## 2.14.0
|
||||
|
||||
### :boom: Breaking changes & Deprecations
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ Redis for messaging/caching.
|
||||
|
||||
## General Guidelines
|
||||
|
||||
This is a golden rule for backend development standards. To ensure consistency
|
||||
across the Penpot JVM stack, all contributions must adhere to these criteria:
|
||||
To ensure consistency across the Penpot JVM stack, all contributions must adhere
|
||||
to these criteria:
|
||||
|
||||
### 1. Testing & Validation
|
||||
|
||||
@ -16,14 +16,14 @@ across the Penpot JVM stack, all contributions must adhere to these criteria:
|
||||
tests in `test/backend_tests/` must be added or updated.
|
||||
|
||||
* **Execution:**
|
||||
* **Isolated:** Run `clojure -M:dev:test --focus backend-tests.my-ns-test` for the specific task.
|
||||
* **Regression:** Run `clojure -M:dev:test` for ensure the suite passes without regressions in related functional areas.
|
||||
* **Isolated:** Run `clojure -M:dev:test --focus backend-tests.my-ns-test` for the specific test namespace.
|
||||
* **Regression:** Run `clojure -M:dev:test` to ensure the suite passes without regressions in related functional areas.
|
||||
|
||||
### 2. Code Quality & Formatting
|
||||
|
||||
* **Linting:** All code must pass `clj-kondo` checks (run `pnpm run lint:clj`)
|
||||
* **Formatting:** All the code must pass the formatting check (run `pnpm run
|
||||
check-fmt`). Use the `pnpm run fmt` fix the formatting issues. Avoid "dirty"
|
||||
check-fmt`). Use `pnpm run fmt` to fix formatting issues. Avoid "dirty"
|
||||
diffs caused by unrelated whitespace changes.
|
||||
* **Type Hinting:** Use explicit JVM type hints (e.g., `^String`, `^long`) in
|
||||
performance-critical paths to avoid reflection overhead.
|
||||
@ -40,18 +40,18 @@ namespaces structure:
|
||||
- `app.db.*` – Database layer
|
||||
- `app.tasks.*` – Background job tasks
|
||||
- `app.main` – Integrant system setup and entrypoint
|
||||
- `app.loggers` – Internal loggers (auditlog, mattermost, etc) (do not be confused with `app.common.loggin`)
|
||||
- `app.loggers` – Internal loggers (auditlog, mattermost, etc.) (not to be confused with `app.common.logging`)
|
||||
|
||||
### RPC
|
||||
|
||||
The PRC methods are implement in a some kind of multimethod structure using
|
||||
`app.util.serivices` namespace. The main RPC methods are collected under
|
||||
The RPC methods are implemented using a multimethod-like structure via the
|
||||
`app.util.services` namespace. The main RPC methods are collected under
|
||||
`app.rpc.commands` namespace and exposed under `/api/rpc/command/<cmd-name>`.
|
||||
|
||||
The RPC method accepts POST and GET requests indistinctly and uses `Accept`
|
||||
header for negotiate the response encoding (which can be transit, the defaut or
|
||||
plain json). It also accepts transit (defaut) or json as input, which should be
|
||||
indicated using `Content-Type` header.
|
||||
The RPC method accepts POST and GET requests indistinctly and uses the `Accept`
|
||||
header to negotiate the response encoding (which can be Transit — the default —
|
||||
or plain JSON). It also accepts Transit (default) or JSON as input, which should
|
||||
be indicated using the `Content-Type` header.
|
||||
|
||||
The main convention is: use `get-` prefix on RPC name when we want READ
|
||||
operation.
|
||||
@ -107,7 +107,7 @@ are config maps with `::ig/ref` for dependencies. Components implement
|
||||
(db/insert! conn :table row)))
|
||||
```
|
||||
|
||||
Almost all methods on `app.db` namespace accepts `pool`, `conn` or
|
||||
Almost all methods in the `app.db` namespace accept `pool`, `conn`, or
|
||||
`cfg` as params.
|
||||
|
||||
Migrations live in `src/app/migrations/` as numbered SQL files. They run automatically on startup.
|
||||
@ -116,7 +116,7 @@ Migrations live in `src/app/migrations/` as numbered SQL files. They run automat
|
||||
### Error Handling
|
||||
|
||||
The exception helpers are defined on Common module, and are available under
|
||||
`app.commin.exceptions` namespace.
|
||||
`app.common.exceptions` namespace.
|
||||
|
||||
Example of raising an exception:
|
||||
|
||||
@ -132,10 +132,11 @@ Common types: `:not-found`, `:validation`, `:authorization`, `:conflict`, `:inte
|
||||
|
||||
### Performance Macros (`app.common.data.macros`)
|
||||
|
||||
Always prefer these macros over their `clojure.core` equivalents — they compile to faster JavaScript:
|
||||
Always prefer these macros over their `clojure.core` equivalents — they provide
|
||||
optimized implementations:
|
||||
|
||||
```clojure
|
||||
(dm/select-keys m [:a :b]) ;; ~6x faster than core/select-keys
|
||||
(dm/select-keys m [:a :b]) ;; faster than core/select-keys
|
||||
(dm/get-in obj [:a :b :c]) ;; faster than core/get-in
|
||||
(dm/str "a" "b" "c") ;; string concatenation
|
||||
```
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
# Penpot Common – Agent Instructions
|
||||
|
||||
A shared module with code written in Clojure, ClojureScript and
|
||||
JavaScript. Contains multplatform code that can be used and executed
|
||||
from frontend, backend or exporter modules. It uses clojure reader
|
||||
conditionals for specify platform specific implementation.
|
||||
A shared module with code written in Clojure, ClojureScript, and
|
||||
JavaScript. Contains multiplatform code that can be used and executed
|
||||
from the frontend, backend, or exporter modules. It uses Clojure reader
|
||||
conditionals to specify platform-specific implementations.
|
||||
|
||||
## General Guidelines
|
||||
|
||||
This is a golden rule for common module development. To ensure
|
||||
consistency across the penpot stack, all contributions must adhere to
|
||||
To ensure consistency across the Penpot stack, all contributions must adhere to
|
||||
these criteria:
|
||||
|
||||
### 1. Testing & Validation
|
||||
@ -16,11 +15,11 @@ these criteria:
|
||||
If code is added or modified in `src/`, corresponding tests in
|
||||
`test/common_tests/` must be added or updated.
|
||||
|
||||
* **Environment:** Tests should run in a JS (nodejs) and JVM
|
||||
* **Environment:** Tests should run in both JS (Node.js) and JVM environments.
|
||||
* **Location:** Place tests in the `test/common_tests/` directory, following the
|
||||
namespace structure of the source code (e.g., `app.common.colors` ->
|
||||
`common-tests.colors-test`).
|
||||
* **Execution:** The tests should be executed on both: JS (nodejs) and JVM environments
|
||||
* **Execution:** Tests should be executed on both JS (Node.js) and JVM environments:
|
||||
* **Isolated:**
|
||||
* JS: To run a focused ClojureScript unit test: edit the
|
||||
`test/common_tests/runner.cljs` to narrow the test suite, then
|
||||
@ -37,8 +36,8 @@ If code is added or modified in `src/`, corresponding tests in
|
||||
* **Formatting:** All code changes must pass the formatting check
|
||||
* Run `pnpm run check-fmt:clj` for CLJ/CLJS/CLJC
|
||||
* Run `pnpm run check-fmt:js` for JS
|
||||
* Use the `pnpm run fmt` fix all the formatting issues (`pnpm run
|
||||
fmt:clj` or `pnpm run fmt:js` for isolated formatting fix)
|
||||
* Use `pnpm run fmt` to fix all formatting issues (`pnpm run
|
||||
fmt:clj` or `pnpm run fmt:js` for isolated formatting fix).
|
||||
|
||||
## Code Conventions
|
||||
|
||||
@ -50,16 +49,16 @@ namespaces structure:
|
||||
- `app.common.types.*` – Shared data types for shapes, files, pages using Malli schemas
|
||||
- `app.common.schema` – Malli abstraction layer, exposes the most used functions from malli
|
||||
- `app.common.geom.*` – Geometry and shape transformation helpers
|
||||
- `app.common.data` – Generic helpers used around all application
|
||||
- `app.common.math` – Generic math helpers used around all aplication
|
||||
- `app.common.data` – Generic helpers used across the entire application
|
||||
- `app.common.math` – Generic math helpers used across the entire application
|
||||
- `app.common.json` – Generic JSON encoding/decoding helpers
|
||||
- `app.common.data.macros` – Performance macros used everywhere
|
||||
|
||||
|
||||
### Reader Conditionals
|
||||
|
||||
We use reader conditionals to target for differentiate an
|
||||
implementation depending on the target platform where code should run:
|
||||
We use reader conditionals to differentiate implementations depending on the
|
||||
target platform where the code runs:
|
||||
|
||||
```clojure
|
||||
#?(:clj (import java.util.UUID)
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
# Penpot Frontend – Agent Instructions
|
||||
|
||||
ClojureScript based frontend application that uses React, RxJS as main
|
||||
ClojureScript-based frontend application that uses React and RxJS as its main
|
||||
architectural pieces.
|
||||
|
||||
|
||||
## General Guidelines
|
||||
|
||||
This is a golden rule for frontend development standards. To ensure consistency
|
||||
across the penpot stack, all contributions must adhere to these criteria:
|
||||
To ensure consistency across the Penpot stack, all contributions must adhere to
|
||||
these criteria:
|
||||
|
||||
|
||||
### 1. Testing & Validation
|
||||
@ -22,7 +21,7 @@ If code is added or modified in `src/`, corresponding tests in
|
||||
running backend. Test are developed using cljs.test.
|
||||
* **Mocks & Stubs:** * Use proper mocks for any side-effecting
|
||||
functions (e.g., API calls, storage access).
|
||||
* Avoid testing through the UI (DOM), we have e2e tests for that/
|
||||
* Avoid testing through the UI (DOM); we have e2e tests for that.
|
||||
* Use `with-redefs` or similar ClojureScript mocking utilities to isolate the logic under test.
|
||||
* **No Flakiness:** Tests must be deterministic. Do not use `setTimeout` or real
|
||||
network calls. Use synchronous mocks for asynchronous workflows where
|
||||
@ -34,15 +33,15 @@ If code is added or modified in `src/`, corresponding tests in
|
||||
* **Isolated:** To run a focused ClojureScript unit test: edit the
|
||||
`test/frontend_tests/runner.cljs` to narrow the test suite, then `pnpm run
|
||||
test`.
|
||||
* **Regression:** Run `pnpm run test` without modifications on the runner (preferred)
|
||||
* **Regression:** To run `pnpm run test` without modifications on the runner (preferred)
|
||||
|
||||
|
||||
#### Integration Tests (Playwright)
|
||||
|
||||
Integration tests are developed under `frontend/playwright` directory, we use
|
||||
mocks for remove communication with backend.
|
||||
mocks for remote communication with the backend.
|
||||
|
||||
You should not add, modify or run the integration tests unless it exlicitly asked for.
|
||||
You should not add, modify or run the integration tests unless explicitly asked.
|
||||
|
||||
|
||||
```
|
||||
@ -50,7 +49,7 @@ pnpm run test:e2e # Playwright e2e tests
|
||||
pnpm run test:e2e --grep "pattern" # Single e2e test by pattern
|
||||
```
|
||||
|
||||
Ensure everything installed before executing tests with `./scripts/setup` script.
|
||||
Ensure everything is installed before executing tests with the `./scripts/setup` script.
|
||||
|
||||
|
||||
### 2. Code Quality & Formatting
|
||||
@ -68,8 +67,8 @@ Ensure everything installed before executing tests with `./scripts/setup` script
|
||||
|
||||
### 3. Implementation Rules
|
||||
|
||||
* **Logic vs. View:** If logic is embedded in an UI component, extract it into a
|
||||
function in the same namespace if is only used locally or look for a helper
|
||||
* **Logic vs. View:** If logic is embedded in a UI component, extract it into a
|
||||
function in the same namespace if it is only used locally, or look for a helper
|
||||
namespace to make it unit-testable.
|
||||
|
||||
|
||||
@ -113,7 +112,7 @@ State is a single atom managed by a Potok store. Events implement protocols
|
||||
```
|
||||
|
||||
The state is located under `app.main.store` namespace where we have
|
||||
the `emit!` function responsible of emiting events.
|
||||
the `emit!` function responsible for emitting events.
|
||||
|
||||
Example:
|
||||
|
||||
@ -128,15 +127,14 @@ Example:
|
||||
(st/emit! (my-event)))
|
||||
```
|
||||
|
||||
On `app.main.refs` we have reactive references which lookup into the main state
|
||||
for just inner data or precalculated data. That references are very usefull but
|
||||
should be used with care because, per example if we have complex operation, this
|
||||
operation will be executed on each state change, and sometimes is better to have
|
||||
simple references and use react `use-memo` for more granular memoization.
|
||||
On `app.main.refs` we have reactive references which look up the main state
|
||||
for inner data or precalculated data. These references are very useful but
|
||||
should be used with care because, for example, if we have a complex operation,
|
||||
this operation will be executed on each state change. Sometimes it is better to
|
||||
have simple references and use React `use-memo` for more granular memoization.
|
||||
|
||||
Prefer helpers from `app.util.dom` instead of using direct dom calls, if no helper is
|
||||
available, prefer adding a new helper for handling it and the use the
|
||||
new helper.
|
||||
Prefer helpers from `app.util.dom` instead of using direct DOM calls. If no
|
||||
helper is available, prefer adding a new helper and then using it.
|
||||
|
||||
### UI Components (React & Rumext: mf/defc)
|
||||
|
||||
@ -175,19 +173,20 @@ lifecycle management. These are analogous to standard React hooks:
|
||||
```
|
||||
|
||||
The `mf/use-state` in difference with React.useState, returns an atom-like
|
||||
object, where you can use `swap!` or `reset!` for to perform an update and
|
||||
`deref` for get the current value.
|
||||
object, where you can use `swap!` or `reset!` to perform an update and
|
||||
`deref` to get the current value.
|
||||
|
||||
You also has `mf/deref` hook (which does not follow the `use-` naming pattern)
|
||||
and it's purpose is watch (subscribe to changes) on atom or derived atom (from
|
||||
okulary) and get the current value. Is mainly used for subscribe to lenses
|
||||
defined in `app.main.refs` or (private lenses defined in namespaces).
|
||||
You also have the `mf/deref` hook (which does not follow the `use-` naming
|
||||
pattern) and its purpose is to watch (subscribe to changes on) an atom or
|
||||
derived atom (from okulary) and get the current value. It is mainly used to
|
||||
subscribe to lenses defined in `app.main.refs` or private lenses defined in
|
||||
namespaces.
|
||||
|
||||
Rumext also comes with improved syntax macros as alternative to `mf/use-effect`
|
||||
and `mf/use-memo` functions. Examples:
|
||||
|
||||
|
||||
Example for `mf/with-memo` macro:
|
||||
Example for `mf/with-effect` macro:
|
||||
|
||||
```clj
|
||||
;; Using functions
|
||||
@ -221,7 +220,7 @@ Example for `mf/with-memo` macro:
|
||||
(filterv #(= team-id (:team-id %)))))
|
||||
```
|
||||
|
||||
Prefer using the macros for it syntax simplicity.
|
||||
Prefer using the macros for their syntax simplicity.
|
||||
|
||||
|
||||
#### 4. Component Usage (Hiccup Syntax)
|
||||
@ -282,22 +281,22 @@ CSS modules pattern):
|
||||
- If a value isn't in the DS, use the `px2rem(n)` mixin: `@use "ds/_utils.scss"
|
||||
as *; padding: px2rem(23);`.
|
||||
- Do **not** create new SCSS variables for one-off values.
|
||||
- Use physical directions with logical ones to support RTL/LTR naturally.
|
||||
- ❌ `margin-left`, `padding-right`, `left`, `right`.
|
||||
- ✅ `margin-inline-start`, `padding-inline-end`, `inset-inline-start`.
|
||||
- Always use the `use-typography` mixin from `ds/typography.scss`.
|
||||
- ✅ `@include t.use-typography("title-small");`
|
||||
- Use physical directions with logical ones to support RTL/LTR naturally:
|
||||
- Avoid: `margin-left`, `padding-right`, `left`, `right`.
|
||||
- Prefer: `margin-inline-start`, `padding-inline-end`, `inset-inline-start`.
|
||||
- Always use the `use-typography` mixin from `ds/typography.scss`:
|
||||
- Example: `@include t.use-typography("title-small");`
|
||||
- Use `$br-*` for radius and `$b-*` for thickness from `ds/_borders.scss`.
|
||||
- Use only tokens from `ds/colors.scss`. Do **NOT** use `design-tokens.scss` or
|
||||
legacy color variables.
|
||||
- Use mixins only those defined in`ds/mixins.scss`. Avoid legacy mixins like
|
||||
- Use mixins only from `ds/mixins.scss`. Avoid legacy mixins like
|
||||
`@include flexCenter;`. Write standard CSS (flex/grid) instead.
|
||||
- Use the `@use` instead of `@import`. If you go to refactor existing SCSS file,
|
||||
try to replace all `@import` with `@use`. Example: `@use "ds/_sizes.scss" as
|
||||
*;` (Use `as *` to expose variables directly).
|
||||
- Avoid deep selector nesting or high-specificity (IDs). Flatten selectors:
|
||||
- ❌ `.card { .title { ... } }`
|
||||
- ✅ `.card-title { ... }`
|
||||
- Avoid: `.card { .title { ... } }`
|
||||
- Prefer: `.card-title { ... }`
|
||||
- Leverage component-level CSS variables for state changes (hover/focus) instead
|
||||
of rewriting properties.
|
||||
|
||||
@ -324,5 +323,5 @@ Always prefer these macros over their `clojure.core` equivalents — they compil
|
||||
### Configuration
|
||||
|
||||
`src/app/config.clj` reads globally defined variables and exposes precomputed
|
||||
configuration vars ready to be used from other parts of the application
|
||||
configuration values ready to be used from other parts of the application.
|
||||
|
||||
|
||||
@ -366,12 +366,19 @@ export function getInlineStyle(state, blockKey, offset) {
|
||||
const NEWLINE_REGEX = /\r\n?|\n/g;
|
||||
|
||||
function splitTextIntoTextBlocks(text) {
|
||||
if (text == null) {
|
||||
return [];
|
||||
}
|
||||
return text.split(NEWLINE_REGEX);
|
||||
}
|
||||
|
||||
export function insertText(state, text, attrs, inlineStyles) {
|
||||
const blocks = splitTextIntoTextBlocks(text);
|
||||
|
||||
if (blocks.length === 0) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const character = CharacterMetadata.create({style: OrderedSet(inlineStyles)});
|
||||
|
||||
let blockArray = DraftPasteProcessor.processText(
|
||||
|
||||
@ -295,6 +295,22 @@
|
||||
|
||||
(def default-paste-from-blob (create-paste-from-blob false))
|
||||
|
||||
(defn- clipboard-permission-error?
|
||||
"Check if the given error is a clipboard permission error
|
||||
(NotAllowedError DOMException)."
|
||||
[cause]
|
||||
(and (instance? js/DOMException cause)
|
||||
(= (.-name cause) "NotAllowedError")))
|
||||
|
||||
(defn- on-clipboard-permission-error
|
||||
[cause]
|
||||
(if (clipboard-permission-error? cause)
|
||||
(rx/of (ntf/show {:content (tr "errors.clipboard-permission-denied")
|
||||
:type :toast
|
||||
:level :warning
|
||||
:timeout 5000}))
|
||||
(rx/throw cause)))
|
||||
|
||||
(defn paste-from-clipboard
|
||||
"Perform a `paste` operation using the Clipboard API."
|
||||
[]
|
||||
@ -303,7 +319,8 @@
|
||||
(watch [_ _ _]
|
||||
(->> (clipboard/from-navigator default-options)
|
||||
(rx/mapcat default-paste-from-blob)
|
||||
(rx/take 1)))))
|
||||
(rx/take 1)
|
||||
(rx/catch on-clipboard-permission-error)))))
|
||||
|
||||
(defn paste-from-event
|
||||
"Perform a `paste` operation from user emmited event."
|
||||
@ -483,11 +500,20 @@
|
||||
(-> entry t/decode-str paste-transit-props))
|
||||
|
||||
(on-error [cause]
|
||||
(let [data (ex-data cause)]
|
||||
(if (:not-implemented data)
|
||||
(rx/of (ntf/warn (tr "errors.clipboard-not-implemented")))
|
||||
(js/console.error "Clipboard error:" cause))
|
||||
(rx/empty)))]
|
||||
(cond
|
||||
(clipboard-permission-error? cause)
|
||||
(rx/of (ntf/show {:content (tr "errors.clipboard-permission-denied")
|
||||
:type :toast
|
||||
:level :warning
|
||||
:timeout 5000}))
|
||||
|
||||
(:not-implemented (ex-data cause))
|
||||
(rx/of (ntf/warn (tr "errors.clipboard-not-implemented")))
|
||||
|
||||
:else
|
||||
(do
|
||||
(js/console.error "Clipboard error:" cause)
|
||||
(rx/empty))))]
|
||||
|
||||
(->> (clipboard/from-navigator default-options)
|
||||
(rx/mapcat #(.text %))
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
content (if (and (not preserve-move-to)
|
||||
(= (-> content last :command) :move-to))
|
||||
(path/content (take (dec (count content)) content))
|
||||
content)]
|
||||
(path/content content))]
|
||||
(st/set-content state content)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
||||
@ -221,12 +221,13 @@
|
||||
|
||||
handle-pasted-text
|
||||
(fn [text _ _]
|
||||
(let [current-block-styles (ted/get-editor-current-block-data state)
|
||||
inline-styles (ted/get-editor-current-inline-styles state)
|
||||
style (merge current-block-styles inline-styles)
|
||||
state (-> (ted/insert-text state text style)
|
||||
(handle-change))]
|
||||
(st/emit! (dwt/update-editor-state shape state)))
|
||||
(when (seq text)
|
||||
(let [current-block-styles (ted/get-editor-current-block-data state)
|
||||
inline-styles (ted/get-editor-current-inline-styles state)
|
||||
style (merge current-block-styles inline-styles)
|
||||
state (-> (ted/insert-text state text style)
|
||||
(handle-change))]
|
||||
(st/emit! (dwt/update-editor-state shape state))))
|
||||
"handled")]
|
||||
|
||||
(mf/use-layout-effect on-mount)
|
||||
|
||||
@ -205,10 +205,10 @@
|
||||
|
||||
detach-value
|
||||
(mf/use-fn
|
||||
(mf/deps on-detach index)
|
||||
(mf/deps on-detach index color)
|
||||
(fn [_]
|
||||
(when on-detach
|
||||
(on-detach index))))
|
||||
(on-detach index color))))
|
||||
|
||||
handle-select
|
||||
(mf/use-fn
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
on-color-detach
|
||||
(mf/use-fn
|
||||
(mf/deps index on-color-detach)
|
||||
(fn [color]
|
||||
(fn [_ color]
|
||||
(on-color-detach index color)))
|
||||
|
||||
on-remove
|
||||
|
||||
@ -170,8 +170,17 @@
|
||||
[^js node name]
|
||||
(let [name (str/camel name)]
|
||||
(loop [current node]
|
||||
(if (or (nil? current) (obj/in? (.-dataset current) name))
|
||||
(cond
|
||||
(nil? current)
|
||||
nil
|
||||
|
||||
(not= (.-nodeType current) js/Node.ELEMENT_NODE)
|
||||
(recur (.-parentElement current))
|
||||
|
||||
(obj/in? (.-dataset current) name)
|
||||
current
|
||||
|
||||
:else
|
||||
(recur (.-parentElement current))))))
|
||||
|
||||
(defn get-parent-with-selector
|
||||
|
||||
@ -1328,6 +1328,10 @@ msgstr "Character limit exceeded"
|
||||
msgid "errors.clipboard-not-implemented"
|
||||
msgstr "Your browser cannot do this operation"
|
||||
|
||||
#: src/app/main/data/workspace/clipboard.cljs
|
||||
msgid "errors.clipboard-permission-denied"
|
||||
msgstr "Clipboard access denied. Please allow clipboard permissions in your browser to paste content"
|
||||
|
||||
#: src/app/main/errors.cljs:235
|
||||
msgid "errors.comment-error"
|
||||
msgstr "There was an error with the comment"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"instructions": ["CONTRIBUTING.md", "AGENTS.md"]
|
||||
"instructions": ["AGENTS.md"]
|
||||
}
|
||||
|
||||
@ -15,8 +15,9 @@
|
||||
"fmt": "./scripts/fmt"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@github/copilot": "^1.0.2",
|
||||
"@github/copilot": "^1.0.11",
|
||||
"@types/node": "^20.12.7",
|
||||
"esbuild": "^0.25.9"
|
||||
"esbuild": "^0.25.9",
|
||||
"opencode-ai": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
176
pnpm-lock.yaml
generated
176
pnpm-lock.yaml
generated
@ -9,14 +9,17 @@ importers:
|
||||
.:
|
||||
devDependencies:
|
||||
'@github/copilot':
|
||||
specifier: ^1.0.2
|
||||
version: 1.0.2
|
||||
specifier: ^1.0.11
|
||||
version: 1.0.11
|
||||
'@types/node':
|
||||
specifier: ^20.12.7
|
||||
version: 20.19.37
|
||||
esbuild:
|
||||
specifier: ^0.25.9
|
||||
version: 0.25.12
|
||||
opencode-ai:
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
|
||||
packages:
|
||||
|
||||
@ -176,44 +179,44 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@github/copilot-darwin-arm64@1.0.2':
|
||||
resolution: {integrity: sha512-dYoeaTidsphRXyMjvAgpjEbBV41ipICnXURrLFEiATcjC4IY6x2BqPOocrExBYW/Tz2VZvDw51iIZaf6GXrTmw==}
|
||||
'@github/copilot-darwin-arm64@1.0.11':
|
||||
resolution: {integrity: sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-darwin-x64@1.0.2':
|
||||
resolution: {integrity: sha512-8+Z9dYigEfXf0wHl9c2tgFn8Cr6v4RAY8xTgHMI9mZInjQyxVeBXCxbE2VgzUtDUD3a705Ka2d8ZOz05aYtGsg==}
|
||||
'@github/copilot-darwin-x64@1.0.11':
|
||||
resolution: {integrity: sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-linux-arm64@1.0.2':
|
||||
resolution: {integrity: sha512-ik0Y5aTXOFRPLFrNjZJdtfzkozYqYeJjVXGBAH3Pp1nFZRu/pxJnrnQ1HrqO/LEgQVbJzAjQmWEfMbXdQIxE4Q==}
|
||||
'@github/copilot-linux-arm64@1.0.11':
|
||||
resolution: {integrity: sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-linux-x64@1.0.2':
|
||||
resolution: {integrity: sha512-mHSPZjH4nU9rwbfwLxYJ7CQ90jK/Qu1v2CmvBCUPfmuGdVwrpGPHB5FrB+f+b0NEXjmemDWstk2zG53F7ppHfw==}
|
||||
'@github/copilot-linux-x64@1.0.11':
|
||||
resolution: {integrity: sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-win32-arm64@1.0.2':
|
||||
resolution: {integrity: sha512-tLW2CY/vg0fYLp8EuiFhWIHBVzbFCDDpohxT/F/XyMAdTVSZLnopCcxQHv2BOu0CVGrYjlf7YOIwPfAKYml1FA==}
|
||||
'@github/copilot-win32-arm64@1.0.11':
|
||||
resolution: {integrity: sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot-win32-x64@1.0.2':
|
||||
resolution: {integrity: sha512-cFlc3xMkKKFRIYR00EEJ2XlYAemeh5EZHsGA8Ir2G0AH+DOevJbomdP1yyCC5gaK/7IyPkHX3sGie5sER2yPvQ==}
|
||||
'@github/copilot-win32-x64@1.0.11':
|
||||
resolution: {integrity: sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
hasBin: true
|
||||
|
||||
'@github/copilot@1.0.2':
|
||||
resolution: {integrity: sha512-716SIZMYftldVcJay2uZOzsa9ROGGb2Mh2HnxbDxoisFsWNNgZlQXlV7A+PYoGsnAo2Zk/8e1i5SPTscGf2oww==}
|
||||
'@github/copilot@1.0.11':
|
||||
resolution: {integrity: sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==}
|
||||
hasBin: true
|
||||
|
||||
'@types/node@20.19.37':
|
||||
@ -224,6 +227,70 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
opencode-ai@1.3.0:
|
||||
resolution: {integrity: sha512-il/dC3B55m5mZV2u72emfPqkZBTzrlZwqGI4Ds5Ld6kt2LTUzBZtKB8sOfy7Bmw2qIel0hLZdoKc8wxLjaXQDw==}
|
||||
hasBin: true
|
||||
|
||||
opencode-darwin-arm64@1.3.0:
|
||||
resolution: {integrity: sha512-OB+yl/BZkjQhnjjFc+KT57iqhPlXNq3E0oIcHHlGiG63L2LTY3zfi9OhzaoemL+or2CWnpCITUe91yTAddiSEQ==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-darwin-x64-baseline@1.3.0:
|
||||
resolution: {integrity: sha512-Th5yiWOSDeEcjnKWhR8b267Uf8r+jwLFhv30JK4x07Zdmu3Jjjr6TdMvjLgEOv3PWmHf/1yYz22Xachb+QST0A==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-darwin-x64@1.3.0:
|
||||
resolution: {integrity: sha512-jivDUpmhzkT7WZp7pXVSb9fdnEVuhKBsnve/9fIkI/UFHxomiZ2NIaNRbHxG26PYT9a1IR4D5QvXBq623g2Mnw==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
opencode-linux-arm64-musl@1.3.0:
|
||||
resolution: {integrity: sha512-EmXBHyRSzWCnD/KDpaSi8ldgjOa+1t5c5tRASyL/lnbinsrZekxub3lI+oxRvKJXESKdgq9EP4gkp6t2fqGsFw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-arm64@1.3.0:
|
||||
resolution: {integrity: sha512-rWEEKo4oqgJ/zk670ywg6uhEPwbUIQCwYCeh+xJ3IlgPltQNiIjqUbzbRqAmEfI1Uj9DCdbZ2TUtHayRv8umKw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-baseline-musl@1.3.0:
|
||||
resolution: {integrity: sha512-sb7LyPlf+5/t4pQ3whcHPVlb7R7SRY0Bgjgy55amEs3xRuKnC3BfSoj8CAoY50M/yVAbOj0haoxu4LFixljwNw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-baseline@1.3.0:
|
||||
resolution: {integrity: sha512-STZtcgGgeRlaFCmkk+mNm+01d02JCzCPvP9kWwNpRF6FBGTcFZ97MxEoGvk+7mEqMueImVQZOR21NiYN6anQhw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64-musl@1.3.0:
|
||||
resolution: {integrity: sha512-Jc/EbYgqmT2J2WLPm7EQWBYfSqetWTrI4Ipc4KFrSB/LbM/7lfXkjpemjQaYNlDTVkvPXaUPFJUpisH64xZ+4g==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-linux-x64@1.3.0:
|
||||
resolution: {integrity: sha512-U9aS0wl0uBDxXncqSYhYBDDQP2ZwiTiuJSLM6MgtFJTbUXuTZZCKmQ8p7C5/+Nxpl4sY5xK+ZaCJcS3k3WGN3g==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
opencode-windows-arm64@1.3.0:
|
||||
resolution: {integrity: sha512-3iWo9lOctaWQ+8QHRKszINPTLjLtb0ztzedlvdY5HAiot9MUK/G5MHeskutxQ7sMvTACiAp02ey+Ml/f/jyf7Q==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
opencode-windows-x64-baseline@1.3.0:
|
||||
resolution: {integrity: sha512-pYuY+9LqPLB/GrlZQr67Cl8RlV6vcay4fW8L3TjabwJOinFMDX9OpNo+DkdKJW7YtPtHD78cXaNDEV8tv9Nx2A==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
opencode-windows-x64@1.3.0:
|
||||
resolution: {integrity: sha512-iFd/6GwfM3jlI2tOb3f12m5ddDY8Ug2HiUU1xmxWJvDnbDBdftlHrzD5twlbIHnKoGvohepX8iWk+A/UN2cXKQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
@ -307,32 +374,32 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-darwin-arm64@1.0.2':
|
||||
'@github/copilot-darwin-arm64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-darwin-x64@1.0.2':
|
||||
'@github/copilot-darwin-x64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-linux-arm64@1.0.2':
|
||||
'@github/copilot-linux-arm64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-linux-x64@1.0.2':
|
||||
'@github/copilot-linux-x64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-win32-arm64@1.0.2':
|
||||
'@github/copilot-win32-arm64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot-win32-x64@1.0.2':
|
||||
'@github/copilot-win32-x64@1.0.11':
|
||||
optional: true
|
||||
|
||||
'@github/copilot@1.0.2':
|
||||
'@github/copilot@1.0.11':
|
||||
optionalDependencies:
|
||||
'@github/copilot-darwin-arm64': 1.0.2
|
||||
'@github/copilot-darwin-x64': 1.0.2
|
||||
'@github/copilot-linux-arm64': 1.0.2
|
||||
'@github/copilot-linux-x64': 1.0.2
|
||||
'@github/copilot-win32-arm64': 1.0.2
|
||||
'@github/copilot-win32-x64': 1.0.2
|
||||
'@github/copilot-darwin-arm64': 1.0.11
|
||||
'@github/copilot-darwin-x64': 1.0.11
|
||||
'@github/copilot-linux-arm64': 1.0.11
|
||||
'@github/copilot-linux-x64': 1.0.11
|
||||
'@github/copilot-win32-arm64': 1.0.11
|
||||
'@github/copilot-win32-x64': 1.0.11
|
||||
|
||||
'@types/node@20.19.37':
|
||||
dependencies:
|
||||
@ -367,4 +434,55 @@ snapshots:
|
||||
'@esbuild/win32-ia32': 0.25.12
|
||||
'@esbuild/win32-x64': 0.25.12
|
||||
|
||||
opencode-ai@1.3.0:
|
||||
optionalDependencies:
|
||||
opencode-darwin-arm64: 1.3.0
|
||||
opencode-darwin-x64: 1.3.0
|
||||
opencode-darwin-x64-baseline: 1.3.0
|
||||
opencode-linux-arm64: 1.3.0
|
||||
opencode-linux-arm64-musl: 1.3.0
|
||||
opencode-linux-x64: 1.3.0
|
||||
opencode-linux-x64-baseline: 1.3.0
|
||||
opencode-linux-x64-baseline-musl: 1.3.0
|
||||
opencode-linux-x64-musl: 1.3.0
|
||||
opencode-windows-arm64: 1.3.0
|
||||
opencode-windows-x64: 1.3.0
|
||||
opencode-windows-x64-baseline: 1.3.0
|
||||
|
||||
opencode-darwin-arm64@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-darwin-x64-baseline@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-darwin-x64@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-arm64-musl@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-arm64@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-baseline-musl@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-baseline@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64-musl@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-linux-x64@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-windows-arm64@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-windows-x64-baseline@1.3.0:
|
||||
optional: true
|
||||
|
||||
opencode-windows-x64@1.3.0:
|
||||
optional: true
|
||||
|
||||
undici-types@6.21.0: {}
|
||||
|
||||
@ -59,4 +59,4 @@ parent/child relationships are tracked separately.
|
||||
The WASM module is loaded by `app.render-wasm.*` namespaces in the
|
||||
frontend. ClojureScript calls exported Rust functions to push shape
|
||||
data, then calls `render_frame`. Do not change export function
|
||||
signatures without updating the ClojureScript bridge.
|
||||
signatures without updating the corresponding ClojureScript bridge.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user