-
Notifications
You must be signed in to change notification settings - Fork 4
refactor(clipboard-plugin): remove meta from editorjs clipboard payload #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ilyamore88
wants to merge
2
commits into
main
Choose a base branch
from
refactor/remove-clipboard-payload-meta
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
openspec/changes/archive/2026-07-21-remove-clipboard-payload-meta/.openspec.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| schema: spec-driven | ||
| created: 2026-07-21 |
40 changes: 40 additions & 0 deletions
40
openspec/changes/archive/2026-07-21-remove-clipboard-payload-meta/design.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| ## Context | ||
|
|
||
| `ClipboardPlugin` (`packages/plugins/clipboard-plugin/src/index.ts`) writes three flavours of the same selection onto the native clipboard on `ui:copy`: `text/plain`, `text/html`, and a custom `application/x-editor-js` JSON payload. That third payload is currently `{ blocks, meta: { version: '3.0.0' } }`, where the version is a hardcoded literal accompanied by a `@todo get version info from Core`. | ||
|
|
||
| Nothing in the repository reads the payload — a repo-wide grep for `application/x-editor-js` finds only the plugin itself, its co-located test, and the capability spec. Paste handling does not exist yet, so this is the last moment where the format can be narrowed without a migration path for internal consumers. | ||
|
|
||
| This change is deliberately small: it is a format simplification, not a redesign of clipboard handling. It is recorded as a change rather than a drive-by edit because the payload shape is a documented spec-level requirement. | ||
|
|
||
| ## Goals / Non-Goals | ||
|
|
||
| **Goals:** | ||
|
|
||
| - Make the `application/x-editor-js` payload exactly `{ blocks }`. | ||
| - Remove the module-private `Meta` interface and the `@todo` that pointed at a version-from-Core plumbing task that no longer needs doing. | ||
| - Keep the spec (`openspec/specs/clipboard-plugin/spec.md`) truthful about the emitted shape. | ||
|
|
||
| **Non-Goals:** | ||
|
|
||
| - Designing or implementing a paste handler that reads the payload. | ||
| - Introducing versioning by another route (payload envelope, MIME type suffix, separate clipboard entry). If a future change needs to distinguish formats, it decides then, with a real consumer to design against. | ||
| - Changing the MIME type string, the `text/plain` / `text/html` payloads, or the copy-event flow. | ||
| - Sourcing an editor version from Core for any other purpose. | ||
|
|
||
| ## Decisions | ||
|
|
||
| **Drop `meta` entirely rather than populate `version` from Core.** The alternative — plumbing a real version through `EditorAPI` into the plugin — was rejected because no consumer needs it. A version field earns its place when something branches on it; adding the plumbing first means maintaining a public format field on speculation. Deleting it is reversible: reintroducing `meta` later is an additive change to the payload, whereas a wrong version value baked into the format is not something readers can recover from. | ||
|
|
||
| **Keep `{ blocks }` as an object rather than serializing the bare array.** Emitting `JSON.stringify(blocks)` would be marginally smaller, but the object wrapper is what makes future extension additive — a reader that destructures `{ blocks }` keeps working when a sibling key appears, while a reader parsing a top-level array would break on any envelope change. The wrapper costs eleven bytes. | ||
|
|
||
| **No versioning shim or dual-write.** The plugin could write both shapes for a transition period. Rejected: there is no reader to transition, and a dual-write would immediately become the compatibility burden the change exists to avoid. | ||
|
|
||
| **Type change is module-private.** `ClipboardEditorJSObject` and `Meta` are not exported from the package, so removing `Meta` alters no published `.d.ts` surface. The break is on the wire only, which is why the proposal marks it BREAKING despite no TypeScript API moving. | ||
|
|
||
| ## Risks / Trade-offs | ||
|
|
||
| **An out-of-repo consumer reads `meta.version` from the clipboard** → Low: the payload has never been documented outside the spec file, the plugin landed recently (`f14b7ce`), and the value it carried was a placeholder, not a real version. Any such consumer was branching on a constant. Accepted without a deprecation window. | ||
|
|
||
| **A future paste implementation genuinely needs format discrimination** → Reintroducing a sibling key alongside `blocks` is additive and cheap; the object wrapper decision above preserves that path. Deciding the shape then, against a real reader, produces a better field than the placeholder does now. | ||
|
|
||
| **Stryker mutation testing on the plugin flags the simplified factory** → `#createClipboardObject` becomes a near-trivial wrapper, which gives mutation testing less to bite on. This is a reduction in code under test, not a coverage regression; the payload assertion in the co-located spec still pins the exact serialized string. |
30 changes: 30 additions & 0 deletions
30
openspec/changes/archive/2026-07-21-remove-clipboard-payload-meta/proposal.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| ## Why | ||
|
|
||
| The `application/x-editor-js` clipboard payload written by `ClipboardPlugin` carries a `meta.version` field that is hardcoded to `'3.0.0'` with a `@todo get version info from Core` — it is not read by anything and there is no paste-side consumer that could act on it. Shipping a placeholder version in a public clipboard format is worse than shipping nothing: any future paste handler that trusts the field would branch on a value that never reflected reality. Removing it now, before a paste handler exists, keeps the format honest and costs nothing. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - **BREAKING** (payload format): the `application/x-editor-js` clipboard payload becomes `{ blocks }` — the `meta` object and its `version` field are removed. | ||
| - Delete the `Meta` interface and the `meta` member of `ClipboardEditorJSObject` in `packages/plugins/clipboard-plugin/src/index.ts`. | ||
| - Simplify `#createClipboardObject` to return the blocks array wrapper only, dropping the `@todo` about sourcing the version from Core. | ||
| - Update the co-located test asserting the serialized payload to expect `{ blocks }`. | ||
|
|
||
| The break is contained: no code in this repository reads the payload, and no paste handling exists yet. Third-party readers of the clipboard format, if any exist, must stop expecting `meta`. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
|
|
||
| None. | ||
|
|
||
| ### Modified Capabilities | ||
|
|
||
| - `clipboard-plugin`: the "Rich clipboard data on copy" requirement changes the shape of the `application/x-editor-js` payload from `{ blocks, meta: { version } }` to `{ blocks }`. | ||
|
|
||
| ## Impact | ||
|
|
||
| - **Code**: `packages/plugins/clipboard-plugin/src/index.ts` (interfaces + `#createClipboardObject`), `packages/plugins/clipboard-plugin/src/index.spec.ts` (payload assertion). | ||
| - **Specs**: `openspec/specs/clipboard-plugin/spec.md` — purpose paragraph and the "Populating clipboard data for a block selection" scenario. | ||
| - **APIs**: no exported TypeScript API changes; `ClipboardEditorJSObject` and `Meta` are module-private. Only the on-the-wire clipboard payload changes. | ||
| - **Dependencies / other packages**: none. `grep` over the repo finds the MIME type referenced only inside the clipboard plugin and its spec. | ||
| - **Docs**: `docs/` contains no clipboard documentation, so nothing there is superseded. The plugin README describes the plugin at one line and needs no edit. |
34 changes: 34 additions & 0 deletions
34
...archive/2026-07-21-remove-clipboard-payload-meta/specs/clipboard-plugin/spec.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| ## MODIFIED Requirements | ||
|
|
||
| ### Requirement: Rich clipboard data on copy | ||
| The system SHALL provide `ClipboardPlugin`, which subscribes to the `ui:copy` event on construction and, when blocks are selected, populates the native clipboard event with `text/plain`, `text/html`, and `application/x-editor-js` data and prevents the native copy action. | ||
|
|
||
| #### Scenario: Populating clipboard data for a block selection | ||
| - **GIVEN** one or more blocks are selected and the native copy event exposes `clipboardData` | ||
| - **WHEN** the `ui:copy` event fires | ||
| - **THEN** the plugin prevents the native event's default action and calls `clipboardData.setData` with the DOM selection's plain text (`text/plain`), the DOM selection's cloned range contents as HTML (`text/html`), and a JSON-serialized `{ blocks }` object (`application/x-editor-js`) built from the selected blocks | ||
|
|
||
| #### Scenario: Omitting metadata from the EditorJS payload | ||
| - **GIVEN** blocks are selected and the `application/x-editor-js` payload is being built | ||
| - **WHEN** the plugin serializes the payload | ||
| - **THEN** the resulting JSON contains `blocks` as its only key and carries no `meta` object or version field | ||
|
|
||
| #### Scenario: Falling back to native copy when no blocks are selected | ||
| - **GIVEN** `api.selection.selectedBlocks` is empty | ||
| - **WHEN** the `ui:copy` event fires | ||
| - **THEN** the plugin returns without calling `preventDefault` or touching `clipboardData`, leaving the browser's native copy behavior intact | ||
|
|
||
| #### Scenario: Falling back to native copy when clipboard access is unavailable | ||
| - **GIVEN** blocks are selected but the native event's `clipboardData` is `undefined` (or `window.getSelection()` returns `null`) | ||
| - **WHEN** the `ui:copy` event fires | ||
| - **THEN** the plugin returns without calling `preventDefault`, leaving the browser's native copy behavior intact | ||
|
|
||
| #### Scenario: Building HTML from a multi-range selection | ||
| - **GIVEN** the DOM selection has zero or more `Range`s | ||
| - **WHEN** the plugin builds the `text/html` payload | ||
| - **THEN** it clones each range's contents into a shared `<template>` in range order and serializes the template's `innerHTML`, producing an empty string when the selection has no ranges (without allocating a template) | ||
|
|
||
| #### Scenario: Releasing the listener on destroy | ||
| - **GIVEN** a `ClipboardPlugin` instance is subscribed to `ui:copy` | ||
| - **WHEN** `destroy()` is called | ||
| - **THEN** it removes the `ui:copy` listener from the `EventBus` |
22 changes: 22 additions & 0 deletions
22
openspec/changes/archive/2026-07-21-remove-clipboard-payload-meta/tasks.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ## 1. Tests first | ||
|
|
||
| - [x] 1.1 In `packages/plugins/clipboard-plugin/src/index.spec.ts`, update the existing `'should add custom editorjs data-type to native event'` case so the expected `setData` payload is `JSON.stringify({ blocks: [...] })` with no `meta` key; confirm it fails against the current implementation | ||
| - [x] 1.2 Add a case named in should-notation — e.g. `it('should not include meta in the editorjs clipboard payload', ...)` — that parses the `application/x-editor-js` argument passed to `setData` and asserts `Object.keys(parsed)` equals `['blocks']`; confirm it fails | ||
|
|
||
| ## 2. Implementation | ||
|
|
||
| - [x] 2.1 In `packages/plugins/clipboard-plugin/src/index.ts`, delete the `Meta` interface and the `meta` member (with its doc comment) from `ClipboardEditorJSObject` | ||
| - [x] 2.2 Simplify `#createClipboardObject` to return `{ blocks }`, removing the `meta` literal and the `@todo get version info from Core` comment | ||
| - [x] 2.3 Update the `#createClipboardObject` doc comment so it no longer says the object carries metadata | ||
| - [x] 2.4 Run `yarn workspace @editorjs/clipboard-plugin test` and confirm both tests from group 1 now pass with no other regressions | ||
|
|
||
| ## 3. Spec and docs alignment | ||
|
|
||
| - [x] 3.1 Update `openspec/specs/clipboard-plugin/spec.md` — change the Purpose paragraph and the "Populating clipboard data for a block selection" scenario from `{ blocks, meta: { version } }` to `{ blocks }`, and add the "Omitting metadata from the EditorJS payload" scenario from the delta spec | ||
| - [x] 3.2 Run `openspec validate remove-clipboard-payload-meta` and resolve any reported issues | ||
|
|
||
| ## 4. Verification | ||
|
|
||
| - [x] 4.1 Run `yarn lint` scoped to the clipboard plugin and fix any findings introduced by the edit | ||
| - [x] 4.2 Grep the repo for `meta` and `x-editor-js` within `packages/plugins/clipboard-plugin` to confirm no stale references to the removed field remain outside `dist/`, `coverage/`, and `reports/` | ||
| - [x] 4.3 Run `yarn workspace @editorjs/clipboard-plugin test:mutations` if the package's Stryker config is part of CI, and confirm the score has not regressed below its configured threshold |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.