docs/plans/2026-03-10-phase-3-core-execution.md
Complete phase 3 for @platejs/core.
Use TDD for every new spec cluster. Keep this file as the live record for status, findings, verification, and learnings.
packages/core/src coverage:
79.45% lines82.19% functions623 passing tests66 spec filespackages/core/type-tests/editor-plugin-contracts.tspackages/core/type-teststesting.mdc@platejs/corelcov filtered to packages/core/src points to these high-value low-coverage hotspots first:
internal/plugin/pluginInjectNodeProps.tslib/utils/overridePluginsByKey.tslib/utils/getInjectMatch.tsreact/stores/plate/createPlateStore.tslib/plugins/node-id/withNodeId.tsreact/utils/pipeOnChange.tsslate-react invariants remain the same shortlist:
use-slate-selectoruse-slateuse-selectededitabledecorationsPlateContainer, PlateView, and ContentVisibilityChunk stay deferred unless a real invariant forces them in.usePluginOption(plugin, 'state') was typed as supported but broken at runtime. Phase 3 fixes that contract instead of papering over it in tests.withNodeId can be covered directly, but Bun needs NodeIdPlugin loaded first to avoid a module-cycle false start during the spec import.slate-plugin-contracts.tsplate-plugin-contracts.tseditor-configure-contracts.tspnpm test:types is green with the split core fixtures.pluginInjectNodePropsgetInjectMatchoverridePluginsByKeyomitPluginContext (lib and react)pipeOnChangepipeOnNodeChangepipeOnTextChangecreatePlateStoreusePluginOptionuseEditorPluginuseElementSelectorcopyBlockMarksToSpanChildcleanHtmlTextNodescleanHtmlLinkElementsremoveHtmlNodesBetweenCommentsgetHtmlCommentsgetDataNodePropsstripHtmlClassNamesgetMarkBoundaryAffinitygetEventPlateIduseEventPlateIduseFocusEditorEventswithNodeId unit suite that covers:
_id override handofffilterText-driven id removalinsertNode / insertNodeslcov:
packages/core/src: 89.16% lines, 89.12% funcswithNodeId.ts: 100% lines, 100% funcscreatePlateStore.ts: 100% lines, 100% funcsusePluginOption.ts: 100% lines, 100% funcs678 passing tests90 spec filesbun run test:slowest -- --top 15 packages/core/src stayed under slow-bucket thresholds for new phase-3 specs. No test-suites move was needed..changeset/core-use-plugin-option-state-patch.mdpnpm test:typesbun test packages/core/src/lib/utils/overridePluginsByKey.spec.ts packages/core/src/lib/utils/omitPluginContext.spec.ts packages/core/src/react/plugin/omitPluginContext.spec.ts packages/core/src/lib/utils/pipeOnNodeChange.spec.ts packages/core/src/lib/utils/pipeOnTextChange.spec.ts packages/core/src/react/utils/pipeOnChange.spec.ts packages/core/src/lib/utils/getInjectMatch.spec.ts packages/core/src/internal/plugin/pluginInjectNodeProps.spec.tsbun test packages/core/src/react/stores/plate/createPlateStore.spec.tsx packages/core/src/react/stores/plate/usePluginOption.spec.tsx packages/core/src/react/stores/plate/useEditorPlugin.spec.tsx packages/core/src/react/stores/element/useElementSelector.spec.tsxbun test packages/core/src/lib/plugins/html/utils/copyBlockMarksToSpanChild.spec.ts packages/core/src/lib/plugins/html/utils/cleanHtmlTextNodes.spec.ts packages/core/src/lib/plugins/html/utils/cleanHtmlLinkElements.spec.ts packages/core/src/lib/plugins/html/utils/removeHtmlNodesBetweenComments.spec.ts packages/core/src/lib/plugins/html/utils/getHtmlComments.spec.ts packages/core/src/lib/plugins/html/utils/getDataNodeProps.spec.ts packages/core/src/static/utils/stripHtmlClassNames.spec.ts packages/core/src/lib/plugins/affinity/queries/getMarkBoundaryAffinity.spec.ts packages/core/src/react/plugins/event-editor/getEventPlateId.spec.ts packages/core/src/react/stores/event-editor/useEventPlateId.spec.tsx packages/core/src/react/plugins/event-editor/useFocusEditorEvents.spec.tsxbun test packages/core/src/lib/plugins/node-id/withNodeId.spec.tspnpm installpnpm turbo build --filter=./packages/corepnpm turbo typecheck --filter=./packages/corepnpm test:typesbun lint:fixbun test packages/core/srcbun run test:slowest -- --top 15 packages/core/srcbun test --coverage --coverage-reporter=lcov --coverage-dir=/tmp/plate-core-phase3-coverage packages/core/srcbun typecheck
packages/autoformat/src/lib/__tests__/withAutoformat/markup.spec.tsx['_***', '***_'] not assignable to mutable MatchRange[]package reality: mixed Slate/Plate nested fixtures create garbage type errors that hide the real contract. Separate Slate-only configure chains from Plate-only editor inference tests.package reality: core editor creation can trigger change handlers during setup. Clear handler mocks after creating the editor before asserting pipeOn*Change behavior.bug found: usePluginOption(plugin, 'state') needed a dedicated runtime branch. The type contract existed before the runtime contract did.package reality: usePlateStore() can hand back equivalent wrapper APIs over the same underlying store. Compare the inner .store when a test cares about identity.package reality: useIncrementVersion and useRedecorate keep separate local counters. Calling both is not additive on the same version key.bun typecheck failed outside @platejs/core in packages/autoformat/src/lib/__tests__/withAutoformat/markup.spec.tsx.