plane
plane copied to clipboard
[WIKI-480] feat: unique id extension
Description
Add unique Id to each node of the document
Type of Change
- [x] Feature (non-breaking change which adds functionality)
Screenshots and Media (if applicable)
Test Scenarios
References
Summary by CodeRabbit
- New Features
- Added unique identifier generation and management for block content, including preservation and regeneration across duplication, copy/paste, drag/drop, and collaborative sync.
- Integrated provider-aware behavior so IDs can defer until collaboration state is synced.
- Bug Fixes
- Whitelisted "data-id" as an allowed data-* attribute to preserve IDs in content markup.
- Chores
- Exposed block node type constants and wired editor hooks to pass provider through extensions.
Walkthrough
Adds a UniqueID extension, plugin, and utilities to assign and enforce per-node IDs (provider-aware), threads a HocuspocusProvider through editor initialization, whitelists data-id in HTML validator, and propagates new props workItemIdentifier and issueSequenceId through editor components.
Changes
| Cohort / File(s) | Summary |
|---|---|
Content validation allowlist apps/api/plane/utils/content_validator.py |
Adds "data-id" to the allowed data-* attributes for all tags. |
CE & core constants packages/editor/src/ce/constants/extensions.ts, packages/editor/src/core/constants/extension.ts |
Adds ADDITIONAL_BLOCK_NODE_TYPES = []; adds UNIQUE_ID = "uniqueID" to CORE_EXTENSIONS and exports BLOCK_NODE_TYPES (list of block node types used for ID assignment). |
Provider wiring & editor hooks packages/editor/src/core/extensions/extensions.ts, packages/editor/src/core/hooks/use-editor.ts |
Adds import/type for HocuspocusProvider, extends extension args to accept provider, and passes provider through core extensions so UniqueID can access it. |
UniqueID extension packages/editor/src/core/extensions/unique-id/extension.ts |
New TipTap extension UniqueID (options, default generation, attributeName→data-id, provider-aware onCreate, conditional plugin registration, updateDocument flag). |
UniqueID plugin packages/editor/src/core/extensions/unique-id/plugin.ts |
New createUniqueIDPlugin(options) implementing duplicate detection, selective ID regeneration for changed ranges, skip for collab-sync transactions, paste/drag handling, and history suppression. |
UniqueID utilities packages/editor/src/core/extensions/unique-id/utils.ts |
Adds createIdsForView(view, options) to assign generated IDs to nodes missing the configured attribute and dispatch a non-history transaction. |
Editor public props: workItemIdentifier packages/editor/src/core/components/editors/rich-text/editor.tsx, packages/editor/src/core/components/menus/block-menu.tsx, packages/editor/src/core/types/editor.ts |
Adds optional workItemIdentifier to editor prop types and passes it to BlockMenu (menu prop added). |
DescriptionInput / issueSequenceId propagation apps/web/core/components/editor/rich-text/description-input/root.tsx, apps/web/core/components/editor/rich-text/editor.tsx, apps/web/core/components/inbox/content/issue-root.tsx, apps/web/core/components/issues/issue-detail/main-content.tsx, apps/web/core/components/issues/peek-overview/issue-detail.tsx |
Adds optional issueSequenceId?: number to DescriptionInput and RichTextEditor props and passes issue.sequence_id through multiple callers. |
Sequence Diagram(s)
sequenceDiagram
actor User
participant Editor as useEditor
participant Ext as UniqueID Extension
participant Provider as HocuspocusProvider
participant View as EditorView / Document
participant Plugin as UniqueID Plugin
User->>Editor: initialize editor (maybe with provider)
Editor->>Ext: create with { provider }
Ext->>Ext: addGlobalAttributes (attributeName -> data-id)
alt provider present
Ext->>Provider: wait for synced
Provider-->>Ext: synced
Ext->>View: createIdsForView(view, options)
else no provider
Ext->>View: createIdsForView(view, options)
end
Note over Plugin,View: runtime enforcement for edits, paste, drag
User->>Plugin: paste / drag / edit
Plugin->>View: scan changed ranges, detect missing/duplicate IDs
Plugin->>View: apply transforms to set/regenerate IDs (no history)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
- Pay special attention to provider sync gating and updateDocument behavior in
unique-id/extension.ts. - Review range iteration, duplicate detection, mark preservation, and transaction meta handling in
unique-id/plugin.ts. - Validate non-history transaction dispatch and attribute updates in
unique-id/utils.ts. - Confirm
data-idwhitelist change scope incontent_validator.py. - Quick type/prop propagation checks for
workItemIdentifierandissueSequenceId.
Poem
🐇
I hop through nodes and leave my print,
a tinydata-idon every mint.
When paste or drag makes duplicates start,
I nudge new names and play my part. ✨
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title clearly and specifically describes the main feature being added: a unique ID extension for the editor, directly reflecting the primary change across the codebase. |
| Description check | ✅ Passed | The description covers the main feature but lacks test scenarios, media/screenshots, and related issue references that the template specifies as sections, though the core information is present. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
feat-unique_id_extension
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.