Operand

do no harem.

gram: docs

> ./CONTRIBUTING.md

# Contributing to @eigenpal/docx-editor-react
Thanks for your interest in contributing! This guide will help you get started.
## Prerequisites
- [Bun](https://bun.sh/) (v1.0+)
- [Node.js](https://nodejs.org/) (v18+)
## Development Setup
```bash
# Clone the repo
git clone https://github.com/eigenpal/docx-editor.git
cd docx-editor
# Install dependencies
bun install
# Start the dev server
bun run dev
# Open http://localhost:5173

Working on the parser, serializer, or layout engine? bun run reference:fetch pulls the gitignored ECMA-376 PDFs and supplementary ZIPs (~58 MB). The handwritten quick-refs and XSD schemas under reference/ stay committed.

Running Tests

# Type checking (fast, run often)
bun run typecheck
# Unit tests
bun test
# E2E tests (requires Playwright browsers)
npx playwright install --with-deps chromium
npx playwright test --timeout=30000 --workers=4
# Single test file
npx playwright test e2e/tests/formatting.spec.ts --timeout=30000

Code Style

The project uses ESLint and Prettier with pre-commit hooks (Husky + lint-staged), so formatting is handled automatically on commit.

# Manual lint/format
bun run lint:fix
bun run format

Contributor License Agreement

Contributors are required to sign our Contributor License Agreement. The CLA assistant will leave a comment on your first pull request with signing instructions — one short comment, about 30 seconds. That signature covers all of your future contributions.

Making Changes

  1. Fork the repository and create a branch from main
  2. Read the code before modifying it — understand the dual rendering system (see Architecture)
  3. Make your changes — keep them focused and minimal
  4. Add/update tests for your changes (see e2e/ for E2E tests)
  5. Verify everything works:
    bun run typecheck && bun test && bun run build:packages
  6. Submit a PR against main — the CLA bot will prompt you on your first one

Architecture Overview

The editor has two rendering systems:

See docs/ARCHITECTURE.md for the full architecture and CLAUDE.md for the agent-facing quick reference (also useful for humans).

Public API Surface

Every published package's @public exports are locked in docs/api/<pkg-slug>/<entry>.api.md snapshots generated by API Extractor. CI runs bun run api:check and fails on undocumented drift.

If you change a @public symbol — or add a new one — regenerate and commit the snapshot:

bun run --filter '@eigenpal/docx-editor-<pkg>' build
bun run api:extract
git add docs/api/<pkg-slug>/

The CI error message points at the source file for each drifted entry, so the fix is mechanical. Full details live in CLAUDE.md under "Public API surface".

Adding a DocxEditorProps field or DocxEditorRef method to either adapter also requires updating scripts/parity/parity.contract.json — the cross-adapter parity contract that tracks which fields are shared, deliberately Vue-deferred, or Vue-exclusive. bun run check:parity-contract (also run in CI) fails until the contract acknowledges the new symbol. The error message names the symbol and tells you which bucket to add it to.

Adding a new Vue composable: declare a Use<Name>Return interface and annotate the function's return type with it. Without the annotation the snapshot recursively inlines core's internal types into Vue's public surface.

Adding a new published package: edit scripts/lib/packages.mjs (one entry — name, root, slug, tsconfig, build hint). Add matching api:extract / api:check scripts in the new package's package.json delegating to ../../scripts/api-extractor.mjs --package <name>. Then run bun run api:extract && bun run docs:json to generate snapshots.

Consumer-facing JSON docs (docs/json/)

The same @public surface is also emitted as structured JSON for downstream docs sites: bun run docs:json writes docs/json/<pkg-slug>/<subpath>.json per published subpath, plus a root docs/json/index.json. The JSON is gitignored — downstream sites (e.g. docx-editor-page) clone the repo and run the script themselves. CI runs bun run docs:json as a smoke test so generator breakage surfaces in this repo, not in the consumer's build.

Adapter Parity

The editor ships first-party adapters for React (packages/react) and Vue (packages/vue). Both share @eigenpal/docx-editor-core, which owns the parser, ProseMirror schema, layout engine, layout bridge (page mapping, footnote convergence, header/footer measurement), and serializer. Adapters only own their framework-specific shell, components, and lifecycle wiring.

When you touch layout, parsing, or rendering logic, put it in core, not in an adapter. If you copy a 30-line helper from React to Vue, you've created a divergence trap. The footnote convergence loop (stabilizeFootnoteLayout in packages/core/src/layout-bridge/footnoteLayout.ts) is the canonical example: one helper, both adapters call it.

Parity smoke tests live under e2e/tests/parity/smoke/ and run each spec against both demos. Add one when you fix a bug that could plausibly affect rendering on either side.

Reporting Bugs

Open an issue at github.com/eigenpal/docx-editor/issues with:

License

By contributing, you agree that your contributions will be licensed under the MIT License.