Skip to content

Latest commit

 

History

History
92 lines (67 loc) · 5.09 KB

File metadata and controls

92 lines (67 loc) · 5.09 KB

AGENTS.md

This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.

Overview

Lexical-based rich editor ecosystem. Modular packages: core editor, UI primitives, content renderers, plugins, extensions, and integration bundles.

Build: Vite 7 + Vanilla Extract CSS-in-TS. ESM only (.mjs). TypeScript 5.9. Lexical 0.42. pnpm 10. Node >= 20.

Commands

pnpm dev                                           # demo/ dev playground (all features)
pnpm --filter @haklex/rich-editor dev:build        # watch mode for core
pnpm build                                         # turbo build (all)
pnpm build:packages                                # workspace packages under packages/
pnpm --filter @haklex/rich-editor build            # single package
pnpm lint                                          # turbo lint (all)
npx eslint path/to/file.ts                         # lint single file
npx prettier --write path/to/file.ts               # format single file
npx vitest run packages/rich-renderer-katex/tests/ # run specific tests
pnpm release:rich                                  # bump + build + publish @haklex/*

Toolchain

  • ESLint: eslint-config-hyoban. Key rule: react/no-use-context: 'error' — must use React 19 use(Context) not useContext().
  • Versioning: All @haklex/* share one version (from packages/rich-editor/package.json), managed by bumpp.
  • Pre-commit: simple-git-hooks + lint-staged (prettier + eslint on staged files).
  • Build: Shared Vite config in vite.shared.ts (createViteConfig()). Auto-externalizes deps/peerDeps. Output: ESM .mjs + .d.ts. Vanilla Extract for CSS-in-TS (zero runtime).

Static / Edit Split (Core Architecture)

The ecosystem splits nodes and renderers into static (read-only) and edit (editor-only) variants for tree-shaking.

  • Static Node/Renderer: Display-only. No @haklex/rich-editor-ui or lucide-react imports. Used by RichRenderer.
  • Edit Node/Renderer: Extends static variant. Adds heavy deps (Popover, DropdownMenu, NestedComposer). Used by RichEditor.

Split criteria: Only split when the edit path introduces heavy imports absent from the static path.

Registration:

  • @haklex/rich-editor src/config.ts → static nodes → RichRenderer
  • @haklex/rich-editor src/config-edit.ts → edit nodes → RichEditor
  • @haklex/rich-renderers src/config.tsenhancedRendererConfig (static renderers)
  • @haklex/rich-renderers-edit src/config.tsenhancedEditRendererConfig (edit renderers)

Adding a new node with edit UI: Create FooNode with RendererWrapper in decorate(), then FooEditNode extends FooNode overriding decorate() with edit decorator. Register base in config.ts, edit in config-edit.ts. Create FooRenderer (static) + FooEditRenderer (edit). Add to respective aggregator configs.

Package Dependency Graph

@haklex/rich-kit-shiro (integration bundle — ShiroEditor / ShiroRenderer)
├── @haklex/rich-editor (core: nodes + plugins + styles + contexts)
│   ├── @haklex/rich-editor-ui (Dialog, Dropdown, Popover via @base-ui/react)
│   ├── @haklex/rich-headless (server-side node registry, zero React)
│   └── @haklex/rich-style-token (theme tokens, CSS variables, variant presets)
├── @haklex/rich-static-renderer (SSR engine, RichRenderer component)
├── @haklex/rich-renderers (static renderer aggregator)
├── @haklex/rich-renderers-edit (edit renderer aggregator)
├── @haklex/rich-ext-{code-snippet,embed,excalidraw,gallery} (heavy extensions)
├── @haklex/rich-plugin-{block-handle,floating-toolbar,link-edit,mention,slash-menu,table,toolbar}
└── @haklex/rich-renderer-katex (KaTeX edit nodes)

@haklex/rich-diff (standalone diff viewer)
@haklex/rich-editor-demo (dev playground, workspace at demo/)

Key Conventions

  • Context Provider value stability: Never pass object literals as context value. Primitives OK directly; objects must be useMemo'd.
  • Neutral colors: Use #737373 / #a3a3a3 (neutral-500/400) for muted text/borders. No tinted grays (slate, zinc).
  • Styling: Vanilla Extract (*.css.ts) throughout. No Tailwind in editor packages.
  • Variant system: article (sans-serif, 16px), note (CJK serif, 16px), comment (sans-serif, 14px). Controlled by variant prop + ColorSchemeContext.

Downstream Consumers

Shiroi (Next.js frontend, ../Shiroi)
  └── @haklex/rich-kit-shiro (npm, native React)

admin-vue3 (Vue 3 dashboard, ../admin-vue3)
  └── @haklex/{rich-editor,rich-editor-ui,rich-kit-shiro,rich-plugin-toolbar,rich-style-token,rich-diff,rich-ext-nested-doc}
      React-in-Vue bridge: createRoot() inside Vue defineComponent (src/components/editor/rich/RichEditor.tsx)

mx-core (NestJS backend, ../mx-core)
  └── @haklex/rich-headless
      Server-side: createHeadlessEditor() + allHeadlessNodes + $toMarkdown() for Lexical JSON → Markdown

Release flow: pnpm release:rich → bump + build + publish to npm. Then update pinned versions in admin-vue3/package.json and mx-core/apps/core/package.json.