Public
Edited
Sep 26, 2024
Insert cell
Insert cell
Insert cell
TextLeaf = Text.empty.constructor
Insert cell
Insert cell
TextNode = Text.of(new Array(33).fill('')).constructor
Insert cell
Insert cell
Insert cell
text = Text.of([...new Array(1023).fill('').map((x, i) => ''), 'aaa', 'bbbbb', 'ccccccc', ...new Array(1022).fill('')])
Insert cell
Insert cell
function dumpNodes(t, r) {
if (t instanceof TextLeaf) {
r.push([t, {id: r.length}])
} else {
for (const c of t.children) {
dumpNodes(c, r)
}
}
return r
}
Insert cell
Insert cell
leafToData = new Map(dumpNodes(text, []))
Insert cell
Insert cell
function changedPaths(text, map) {
const stack = []
const result = []
function recurse(t) {
if (t instanceof TextLeaf) {
if (!map.has(t)) {
result.push([...stack, t])
}
return
}
stack.push(t)
t.children.map(recurse)
stack.pop()
}

recurse(text)
return result
}
Insert cell
Insert cell
text2 = text.replace(1025, 1035, Text.of(['xxx']))
Insert cell
Insert cell
data = changedPaths(text2, leafToData)
Insert cell
Insert cell
class VL {
constructor(len) {
if (!Number.isSafeInteger(len)) throw 0
this.len = len
Object.freeze(this)
}
get length() { return this.len }
toString() { return ' '.repeat(this.len) }
slice(x, y) {
if (!((x == null || x >= 0) &&
(y == null || y >= 0))) {
throw new RangeError('Negative slices are unimplemented')
}
if (x == null) return this
if (y == null || y > this.len) return VL.of(Math.max(0, this.len - x))
return VL.of(y - x)
}

static interned = {}
static {
for (let i = 0; i < 16; i++) {
this.interned[i] = new VL(i)
}
}
static of(len) {
if (len < 0) {
throw new RangeError('Negative lengths are disallowed')
}
if (len < 16) { return VL.interned[len] }
return new VL(len)
}
}
Insert cell
Insert cell
Text.empty instanceof Text
Insert cell
TextLeafPlus = ({['TextLeaf✳️']: class extends TextLeaf {
constructor(text, length, data) {
super(text, length)
this._enhanced = true
this.data = data
}
}}['TextLeaf✳️'])
Insert cell
TextNodePlus = ({['TextNode✳️']: class extends TextNode {
constructor(children, length, data) {
super(children, length)
this._enhanced = true
this.data = data
}
}}['TextNode✳️'])
Insert cell
Insert cell
function enhanceText(t) {
let n = 0, m = 1e6
function _enh(t) {
if (t._enhanced) {
return t
}
if (t.children == null) {
// a leaf
const text = t.text.map(s => s instanceof VL ? s : VL.of(s.length))
return new TextLeafPlus(text, t.length, n++)
} else {
// a node
const children = t.children.map(c => _enh(c))
return new TextNodePlus(children, t.length, m++)
}
}
return _enh(t)
}
Insert cell
s0 = Text.of([...new Array(2048)].fill('').map(() => VL.of(Math.floor(Math.random() * 1000))))
Insert cell
s1 = enhanceText(s0)
Insert cell
Insert cell
randomChangeToS1 = {
let a = Math.floor(Math.random() * 1000000)
let b = Math.floor(Math.random() * 1000000)
if (a > b) [a, b] = [b, a]
return ChangeSet.of({from: a, to: b, insert: ''}, s1.length)
}
Insert cell
s2 = randomChangeToS1.apply(s1)
Insert cell
s3 = enhanceText(s2)
Insert cell
Insert cell
CMState = import('@codemirror/state')
Insert cell
Text = /* you can use it in the console! */ window._Text = CMState.Text
Insert cell
ChangeSet = CMState.ChangeSet
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more