oficina / slides Public

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

Plain git — no account needed to clone.

Download

Download this file

1// The operations the inspector and the drive surface apply (spec §7.2),
2// over a Y.Doc in the browser — the same vocabulary as core/src/ops.rs,
3// with the same result. A new op is added to both or to neither; the
4// vectors under vectors/ hold the two to one view.
5//
6// applyOps(ydoc, ops, origin) parses and checks the whole batch against a
7// model of the deck first (ops-model.mjs) and throws an OpsError — with
8// the core's own message, prefixed `op N:` — having written nothing;
9// only then does it apply every op (ops-apply.mjs) inside one
10// ydoc.transact with the given origin, so the undo manager and the
11// save queue see one change.
12//
13// Ids: the core never draws entropy and neither does this module. Every
14// new slide or block id arrives in the op (`id`, `new_id`,
15// `new_block_ids`); the browser mints them with ids.mjs before calling.
16import { roots } from './ydoc.mjs'
17import { Model, OpsError, parseOp } from './ops-model.mjs'
18import { applyOne } from './ops-apply.mjs'
19
20export { OpsError } from './ops-model.mjs'
21export { view } from './view.mjs'
22
23function at (i, e, applying = false) {
24 const msg = e instanceof Error ? e.message : String(e)
25 return new OpsError(`op ${i}${applying ? ' (applying)' : ''}: ${msg}`, i)
26}
27
28/**
29 * Applies ops (an array of §7.2 operations) to ydoc in one transaction.
30 * Throws OpsError, applying nothing, when any op is malformed or names
31 * something the deck (as the batch so far leaves it) does not have.
32 */
33export function applyOps (ydoc, ops, origin = 'ops') {
34 if (!Array.isArray(ops)) throw new OpsError('ops must be a JSON array', -1)
35 const parsed = ops.map((raw, i) => {
36 try { return parseOp(raw) } catch (e) { throw at(i, e) }
37 })
38 const r = roots(ydoc)
39 const model = Model.read(r)
40 parsed.forEach((op, i) => {
41 try { model.check(op) } catch (e) { throw at(i, e) }
42 })
43 ydoc.transact(() => {
44 parsed.forEach((op, i) => {
45 try { applyOne(r, op) } catch (e) { throw at(i, e, true) }
46 })
47 }, origin)
48}
49