oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1// Generates the Yjs wire fixtures that define compatibility for the Rust
2// core. These are the contract: never edit a fixture to make a test pass.
3// A deliberate rule change regenerates them in the same commit.
4import * as Y from 'yjs'
5import { mkdirSync, writeFileSync } from 'node:fs'
6import { join, dirname } from 'node:path'
7import { fileURLToPath } from 'node:url'
8
9const dataDir = join(dirname(fileURLToPath(import.meta.url)), 'data')
10mkdirSync(dataDir, { recursive: true })
11
12function emit(name, build) {
13 const doc = new Y.Doc()
14 // new Y.Doc() assigns a random clientID. Fixed IDs ensure that running the
15 // generator twice produces byte-identical fixtures (required for the
16 // regeneration gate that later tasks add).
17 doc.clientID = 1
18 build(doc)
19 const update = Y.encodeStateAsUpdate(doc)
20 writeFileSync(join(dataDir, `${name}.update.bin`), Buffer.from(update))
21 writeFileSync(
22 join(dataDir, `${name}.expected.json`),
23 JSON.stringify({
24 text: doc.getText('content').toString(),
25 delta: doc.getText('content').toDelta()
26 }, null, 2) + '\n'
27 )
28 console.log(`${name}: ${update.length} bytes`)
29}
30
31emit('hello', (doc) => {
32 doc.getText('content').insert(0, 'hello world')
33})
34
35emit('unicode', (doc) => {
36 // Surrogate pairs and combining marks: Yjs indexes UTF-16 code units and
37 // Rust indexes UTF-8 bytes, so this is where an index-conversion bug shows.
38 doc.getText('content').insert(0, 'héllo 🌍 café')
39})
40
41emit('formatted', (doc) => {
42 // Rich text formatting: bold is the key assertion. The delta field captures
43 // the formatting structure that toString() would strip, verifying that the
44 // Rust side correctly decodes format operations.
45 const t = doc.getText('content')
46 t.insert(0, 'plain bold plain')
47 t.format(6, 4, { bold: true })
48})
49
50emit('concurrent', (doc) => {
51 // Two docs diverge and merge. The merged state is order-independent, so
52 // Rust must arrive at the same bytes from the same inputs.
53 const a = new Y.Doc()
54 a.clientID = 1
55 const b = new Y.Doc()
56 b.clientID = 2
57 // Note: doc.clientID (set to 3 here) overrides the emit() assignment above.
58 // The clientID of this local doc must differ from a and b to ensure
59 // deterministic merge ordering.
60 doc.clientID = 3
61 a.getText('content').insert(0, 'AAA')
62 b.getText('content').insert(0, 'BBB')
63 Y.applyUpdate(a, Y.encodeStateAsUpdate(b))
64 Y.applyUpdate(b, Y.encodeStateAsUpdate(a))
65 Y.applyUpdate(doc, Y.encodeStateAsUpdate(a))
66})
67