| name | sync-upstream |
| description | Use when upstream @lexical/code has new releases, when user asks to sync/merge/update from facebook/lexical, or when checking if this fork is behind upstream |
Sync Upstream @lexical/code
Overview
This repo is a minimal fork of @lexical/code with Prism.js removed. Only FacadePrism.ts differs from upstream. All other source files are byte-identical. This constraint makes merges predictable.
Architecture
src/
index.ts # byte-identical to upstream
CodeNode.ts # byte-identical to upstream
CodeHighlightNode.ts # byte-identical to upstream
CodeExtension.ts # byte-identical to upstream
CodeHighlighterPrism.ts # byte-identical to upstream
FlatStructureUtils.ts # byte-identical to upstream
FacadePrism.ts # ★ ONLY modified file — Prism stubbed out
shared/invariant.ts # shim for monorepo-internal import
.upstream/
VERSION # last synced upstream version
FacadePrism.ts.base # upstream FacadePrism.ts at last sync (for 3-way merge)
When to Use
- User says "sync", "update", "merge upstream", "new lexical version"
- Checking if fork is behind: compare
.upstream/VERSION with latest @lexical/code npm version
- After upstream releases a new version
Sync Process
Option A: Automated Script
./scripts/sync-upstream.sh
./scripts/sync-upstream.sh v0.42.0
The script handles everything: clone, copy identical files, 3-way merge FacadePrism.ts, rebuild, verify.
Option B: Manual (when script fails or structural changes detected)
-
Check current version:
cat .upstream/VERSION
-
Clone upstream at target version:
git clone --depth 1 --branch v0.XX.0 https://github.com/facebook/lexical.git /tmp/lexical-sync
-
Copy byte-identical files (6 files, direct overwrite):
for f in index.ts CodeNode.ts CodeHighlightNode.ts CodeExtension.ts CodeHighlighterPrism.ts FlatStructureUtils.ts; do
cp /tmp/lexical-sync/packages/lexical-code/src/$f src/$f
done
-
3-way merge FacadePrism.ts:
git merge-file src/FacadePrism.ts .upstream/FacadePrism.ts.base /tmp/lexical-sync/packages/lexical-code/src/FacadePrism.ts
-
Update base snapshot:
cp /tmp/lexical-sync/packages/lexical-code/src/FacadePrism.ts .upstream/FacadePrism.ts.base
echo "0.XX.0" > .upstream/VERSION
-
Rebuild and verify:
pnpm install && pnpm typecheck && pnpm build
grep -r "prismjs" dist/index.js dist/index.mjs
Resolving FacadePrism.ts Conflicts
Our modifications to FacadePrism.ts are in 4 isolated regions. When conflicts arise, preserve these:
Region 1: Prism imports → removed
Region 2: Prism export → stub
export const Prism: any = {
languages: {
diff: {PREFIXES: {}},
} as Record<string, any>,
tokenize(code: string, _grammar?: unknown): string[] {
return [code];
},
Token: class { },
};
Region 3: getCodeLanguages → use friendly name map
Region 4: isCodeLanguageLoaded → always true
Everything else (language maps, utility functions, tokenizeDiffHighlight, $getHighlightNodes, $mapTokensToLexicalStructure) should accept upstream changes as-is.
Handling Structural Changes
If upstream adds/removes/renames files:
- New file added: Copy it to
src/, add to IDENTICAL_FILES in sync script
- File renamed: Update sync script, update imports if needed
- File removed: Remove from
src/ and sync script
- New import in existing file: Usually fine — our tsconfig paths handle
shared/invariant and @lexical/code self-reference
- New dependency added: Add to
peerDependencies in package.json
Verification Checklist
After sync, confirm: