Operations
Every edit is a pure function on the model. This page shows each one as a
card: the document before, the act, and the document after. The cards are
drawn from the same YAML fixtures that @epure/vitest runs, under
packages/editor/src/design/operations/, so a card and its test cannot drift
apart.
The notation ■
A fixture writes a document in a small notation. One line is one block, and the text of the line is the block’s text.
Hello world
|Second one
|is the caret.{and}hold a selection, and the two may sit in different blocks.- A line may start with
@ato name its block. A line that names none gets a letter by position:a,b,c. Name the ids when the rule is about identity. When theafterof a scenario names none, ids are not compared. - A backslash keeps the character after it literal:
\|,\{,\},\\and\@. - An empty line is an empty block. A line that starts with
#,##or###is a heading block, and one that starts with-is an item of a list. The prefix is the block’s form, not part of its text. A line that must begin with such a prefix as text takes a backslash. - Marks are inline markdown in one canonical form:
**bold**,_italic_,`code`and[text](href). A set of marks nests in one order, link outside, then bold, then italic, then code. Bold and italic never open or close on a space, and two runs of one of them parted by spaces alone are one run. A literal marker takes a backslash. - The side of the caret at a marker says which marks are pending.
**open|**types the next letter bold and**open**|does not. Empty markers around the caret,**|**, hold a pending mark in plain text. - The act is a word, with its argument in parentheses:
backspace,delete,enter,bold,italic,code,link(/open-sets),heading(2),paragraph,item,display,moveUp,moveDown,paste(...),insert(math, U \in \tau),edit(a8f1, U \in \tau)andinput(For every ε| there is a δ.). Several acts make a list:[enter, enter]. The two arrows,->and<-, are acts too. The argument ofinputis plain text: the browser knows no marks, so none are read in it. The argument ofpasteis a document in the notation, one line per pasted block. - A scenario may carry
atoms, the section’s dictionary beside its blocks: an id, a type and a text.atomsAftersays what it holds after the act, and when absent the atoms are not compared. An atom the act mints takese1, thene2. A pipe in an atom’s text is the caret of the box under it, so the box is open on that atom at that offset. The course writes a literal bar as\lvertor\mid. - An id between double braces in a line, such as
{{a8f1}}, is a reference: characters of the plain text under a mark of its own. It is read before the selection markers, so a selection may open right before one and close right after it. A line that starts with::is a display block, which holds one reference alone. A card draws a reference as the editor does, the atom rendered by its type, and never as its characters.
The text of every scenario comes from one course on topology. The course needs what the editor finds hard: inline math, LaTeX blocks, letters composed from several keys, callouts and schemas.
A scenario is the document before, the act, and the document after:
- scenario: backspace at the start of a paragraph joins it with the previous one
before: |
Hello world.
|Second one
when: backspace
after: |
Hello world. |Second one
Join ■
Backspace at the start of a block joins it with the previous one. The first block keeps its id.
Before
- aA topology on a set X is a collection of subsets called open sets.
- bThe empty set and X itself are open.
After
- aA topology on a set X is a collection of subsets called open sets. The empty set and X itself are open.
Before
- aAny union of open sets is open.
- bAny finite intersection of open sets is open.
After
- aAny union of open sets is open. Any finite intersection of open sets is open.
Before
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
After
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
Before
- aThe closure of A is the smallest closed set containing A.
- b
- cThe interior of A is the largest open set inside A.
After
- aThe closure of A is the smallest closed set containing A.
- bThe interior of A is the largest open set inside A.
Split ■
Enter splits the block at the caret. The first half keeps the id and the second half takes a new one. Over a selection, the selection goes first.
Before
- aA map f from X to Y is continuous when the preimage of every open set is open.
After
- aA map f from X to Y is continuous when
- bthe preimage of every open set is open.
Before
- aContinuity is a statement about open sets, not about distances.
After
- aContinuity is a statement about
- bopen sets, not about distances.
Before
- aA homeomorphism is a continuous bijection with a continuous inverse.
After
- aA homeomorphism is a continuous bijection with a continuous inverse.
- b
Before
- aTwo spaces are homeomorphic when a homeomorphism runs between them.
After
- a—
- bTwo spaces are homeomorphic when a homeomorphism runs between them.
Before
- aThe circle and the square are homeomorphic. The circle and the line are not.
After
- aThe circle and the square are homeomorphic.
- b—
- cThe circle and the line are not.
Before
- aThe circle and the square are homeomorphic.
After
- aThe circle
- bare homeomorphic.
Delete ■
Delete removes the character after the caret. At the end of a block it joins the next block onto it, the mirror of backspace, and the caret stays where it was. Over a selection, delete and backspace both remove it. A selection across blocks trims the first block, trims the last, drops the blocks between and joins the two ends. The first id survives.
Before
- aEvery open ball is an open set.
After
- aEvery open ball is a open set.
Before
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
After
- aA set is closed when its complement is open. Both the empty set and X are closed.
Before
- aThe closure of A is the smallest closed set containing A.
After
- aThe closure of A is the smallest closed set containing A.
Before
- aA space is compact when every open cover has a countable subcover.
After
- aA space is compact when every open cover has a subcover.
Before
- aEvery metric space is Hausdorff.
- bEvery subspace of a Hausdorff space is Hausdorff.
- cThe product of two Hausdorff spaces is Hausdorff.
After
- aEvery metric space is Hausdorff.
Before
- aEvery metric space is Hausdorff.
- bEvery subspace of a Hausdorff space is Hausdorff.
- cThe product of two Hausdorff spaces is Hausdorff.
After
- aEvery metric space is Hausdorff.
Before
- aEvery metric space is Hausdorff.
- bThe product of two Hausdorff spaces is Hausdorff.
After
- aEvery metric space is –Hausdorff.
Input ■
Input is the browser’s input event. The argument is the block that holds the focus, as the browser left it: its whole text, and the caret or selection inside it. The model diffs the old text against the new one to find the span that changed, so marks move with it. Typing, composition, dead keys and autocorrect all land here.
Before
- aFor every there is a δ.
After
- aFor every ε there is a δ.
Before
- aA space is compact when every open cover has a countable subcover.
After
- aA space is compact when every open cover has a finite subcover.
Before
- aThe Hausdorff condition separates points by pen sets.
After
- aThe Hausdorff condition separates points by öpen sets.
Before
- aThe reals carry the order topology.
After
- aThe reals 𝕽 carry the order topology.
Before
- aEvery metric space is a Hausdorf space.
After
- aEvery metric space is a Hausdorff space.
Before
- aA basis is a family of open sets.
- bEvery open set is a union of members.
- cThe open balls form a basis of a metric space.
After
- aA basis is a family of open sets.
- bEvery open set is a union of basis members.
- cThe open balls form a basis of a metric space.
Marks ■
A mark extends when typing reaches its end, unless it is a link. No mark extends at its start. A toggle over a selection adds the mark to all of it or removes it from all of it, keeps the selection, and skips any code span. On a caret a toggle stores a pending mark for the next typed character. Punctuation typed at the end of a run lands outside it, so a sentence that ends on a bold word or a code span ends plain. A space typed at the end of a bold run keeps the run pending, so the next word rejoins it; a space typed at the end of a code span lands outside, since a span is one identifier. The keys are Cmd+B, Cmd+I and Cmd+E.
Before
- aThe interiorB is the largest open set inside A.
After
- aThe interior of AB is the largest open set inside A.
Before
- aThe proof uses the Heine–Borel theorem– once.
After
- aThe proof uses the Heine–Borel theorem twice, once.
Before
- a–Compactness is preserved by continuous maps.
After
- aNote: –Compactness is preserved by continuous maps.
Before
- aThe interiorB of A is the largest open set inside A.
After
- aThe interioB of A is the largest open set inside A.
Before
- aEvery open set is a union of basis members.
After
- aEvery memberB is a union of basis members.
Before
- aA compact space has a finite subcover for every open cover.
After
- aA compact space has a finite subcover for every open cover.
Before
- aA compact space has a finite subcover for every open cover.
After
- aA compact space has a finite subcover for every open cover.
Before
- aA compact space has a finite subcover for every open cover.
After
- aA compact space has a finite subcover for every open cover.
Before
- aA compact space has a finite subcover for every open cover.
After
- aA compact space has a finite subcover for every open cover.
Before
- aA space is compact when every open cover has a finite subcover.
After
- aA cBspace is compact when every open cover has a finite subcover.
Before
- aEvery compact subset of a Hausdorff space is closed.
After
- aEvery compact subset of a Hausdorff space is closed.
Before
- aThe set
Uis open in X.
After
- aThe set
Uis open in X.
Before
- aOpen sets are closed under unions.
After
- aOpen sets are
- b–closed under unions.
Before
- aClosed sets
- b–are the complements of open sets.
After
- aClosed sets are the complements of open sets.
Before
- aAny union of open sets is open.
- bAny finite intersection of open sets is open.
After
- aAny union of open sets is open.
- bAny finite intersection of open sets is open.
Before
- aEvery metric space is HausdorffB
After
- aEvery metric space is Hausdorff.
Before
- aThe open set is
U` and its complement is closed.
After
- aThe open set is
U, and its complement is closed.
Before
- aThe composite
fgis continuous.
After
- aThe composite
f.gis continuous.
Before
- aAn openB of X is a family of open sets.
After
- aAn open coverB of X is a family of open sets.
Before
- aLet be open in X.
After
- aLet
U` be open in X.
Before
- aThe open set
U`is a ball.
After
- aThe open set
Uis a ball.
Before
- aThe composite
fgis continuous.
After
- aThe composite
fgis continuous.
Caret ■
An arrow moves the caret one character, and at the end of a block it crosses to the next one. Wherever it lands, by arrow or by click, the caret takes the marks of its place: inside a bold, italic or code run at its end, outside a link at its end, outside any run at its start. Cmd+B takes the other side. After typing, the pending marks are the ones the last typed character took. After a deletion they follow the character before the caret. Up and down depend on line layout and belong to the view, not the model.
Before
- aEvery open set is a union of basis members.
After
- aEvery open set is a union of basis members.
Before
- aEvery open set is a union of basis members.
After
- aEvery open set is a union of basis members.
Before
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
After
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
Before
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
After
- aA set is closed when its complement is open.
- bBoth the empty set and X are closed.
Before
- aThe closure of A is the smallest closed set containing A.
After
- aThe closure of A is the smallest closed set containing A.
Before
- aAn openB cover of X is a family of open sets.
After
- aAn open cover of X is a family of open sets.
Before
- aAn open cover of X is a family of open sets.
After
- aAn openB cover of X is a family of open sets.
Before
- aEvery –open set is a union of basis members.
After
- aEvery open set is a union of basis members.
Before
- aAn open cover of X is a family of open sets.
After
- aAn openB cover of X is a family of open sets.
Before
- aSee compactness for the finite subcover property.
After
- aSee compactness– for the finite subcover property.
Before
- aAn openB cover of X is a family of open sets.
After
- aAn opens cover of X is a family of open sets.
Before
- aAn open– cover of X is a family of open sets.
After
- aAn opeB cover of X is a family of open sets.
Before
- aEvery open ball is an open set.
After
- aEvery open ball is a open set.
Before
- aAn open cover of X is a family of open sets.
After
- aAn openB cover of X is a family of open sets.
Before
- aThe proof uses the Heine–Borel theorem twice.
After
- aThe proof uses the Heine–Borel theorem– twice.
Before
- aEvery open set is a union of basis members.
After
- aEvery –open set is a union of basis members.
Move ■
A block moves one place at a time. The blocks a selection covers move together. Ids and offsets do not change, so the selection travels with them.
Before
- aOpen sets are closed under unions.
- bA topology is a collection of open sets.
After
- bA topology is a collection of open sets.
- aOpen sets are closed under unions.
Before
- aOpen sets are closed under unions.
- bA topology is a collection of open sets.
After
- bA topology is a collection of open sets.
- aOpen sets are closed under unions.
Before
- aA topology is a collection of open sets.
- bOpen sets are closed under unions.
After
- aA topology is a collection of open sets.
- bOpen sets are closed under unions.
Before
- aAny finite intersection of open sets is open.
- bThe empty set and X are open.
- cAny union of open sets is open.
After
- bThe empty set and X are open.
- cAny union of open sets is open.
- aAny finite intersection of open sets is open.
Paste ■
One pasted block goes into the text at the caret. Several split the block: the first pasted block joins the text before the caret, the last joins the text after, both the way a join does, and the rest sit between as new blocks. The caret lands at the end of what was pasted. Over a selection, the selection goes first.
Before
- aFor every ε there is a .
After
- aFor every ε there is a δ with the same property.
Before
- aThe preimage of an open set under a map is open.
After
- aThe preimage of an open set under a continuous map is open.
Before
- aA space is compact when every open cover has a countable subcover.
After
- aA space is compact when every open cover has a finite subcover.
Before
- aA topology on X has three axioms: and that is all.
After
- aA topology on X has three axioms: the empty set and X are open.
- bAny union of open sets is open.
- cAny finite intersection of open sets is open, and that is all.
Before
- aA topology on X has three axioms.
After
- aA topology on X has three axioms. The empty set and X are open.
- bAny union of open sets is open.
Heading ■
A block has a form: prose, a heading with its level, or an item of a list. The form is the line’s prefix on the port and in the notation, and it is not text in the model. Setting a form a block already has turns it back into prose, so one key toggles. On a split the form follows the text: the half that holds the title stays a heading, and an empty half is prose. Backspace at the start of a heading turns it into prose and does not join; the next backspace joins.
Before
- aOpen sets
After
- a# Open sets
Before
- a# Open sets
After
- aOpen sets
Before
- a# Open sets
After
- a## Open sets
Before
- a## Open sets
After
- aOpen sets
Before
- aOpen sets
- bClosed sets
After
- a## Open sets
- b## Closed sets
Before
- a# Open sets
After
- a# Open sets
- b
Before
- a# Open sets
After
- a—
- b# Open sets
Before
- a# Open sets and closed sets
After
- a# Open
- bsets and closed sets
Before
- aThe three axioms follow.
- b# Open sets
After
- aThe three axioms follow.
- bOpen sets
Before
- a# Open sets
- bA set is open when it belongs to τ.
After
- a# Open sets A set is open when it belongs to τ.
Before
- a# The open sets of X
After
- a# The open sets of a space X
Item ■
An item splits into two items, so a list goes on. Enter on an empty item leaves the list, and backspace at the start of an item turns it into prose.
Before
- aEvery open ball is open.
After
- a- Every open ball is open.
Before
- a- Every open ball is open.
After
- aEvery open ball is open.
Before
- a- Every open ball is open.
After
- a- Every open ball is open.
- b-
Before
- a- Every open ball is open.
- b-
After
- a- Every open ball is open.
- b
Before
- a- Every open ball is open.
After
- a- Every open ball
- b- is open.
Before
- a- Every open ball is open.
- b- The whole space is open.
After
- a- Every open ball is open.
- bThe whole space is open.
Before
- a- Every open ball is open.
- bThe whole space is open.
After
- a- Every open ball is open. The whole space is open.
Reference ■
A reference holds an atom in a block: the id between double braces, under a
mark of its own. The editor draws the atom by its type, and the browser may
not edit it. The caret never sits inside an atom.
What the arrows do at one is the type’s to say. A type that enters, such as
a formula, opens its box: right before the atom opens it with the caret at
the start of the source, and left after the atom opens it at the end. Inside
the box the arrows move through the source, and at its edges they leave it,
after the atom on the right and before it on the left. Escape leaves after
the atom. A type with a widget of its own, such as a video, is skipped whole,
and so is a reference to no atom. Typing beside an atom lands outside it,
and a mark toggled over a range that holds one covers it whole. Backspace
after an atom selects it, and delete before one does the same, so nothing
invisible is ever removed; the next backspace removes it and leaves its
atom in the section. edit changes the text of an atom and no block, and
in an open box it leaves the caret after what was typed. insert mints an
atom and places its reference at the caret; in the editor it is Cmd+M, and
the box takes the source. A pasted reference copies its atom under a new
id, so two references never share one atom by accident, and a reference to
an atom the section does not hold stays as it is.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aWatch {"row": "0f3a9c1e2b4d6a7f", "width": "wide"} before the proof.
After
- aWatch {"row": "0f3a9c1e2b4d6a7f", "width": "wide"} before the proof.
Before
- aWatch {"row": "0f3a9c1e2b4d6a7f", "width": "wide"} before the proof.
After
- aWatch {"row": "0f3a9c1e2b4d6a7f", "width": "wide"} before the proof.
Before
- aSee {{zz99}} for the proof.
After
- aSee {{zz99}} for the proof.
Before
- aA set is open by definition.
After
- aA set , is open by definition.
Before
- aA set is open by definition.
After
- aA set U, is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA open by definition.
Before
- aA set is open by definition.
After
- aA set
- bis open by definition.
Before
- aA set
- bis open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aA set is open by definition.
After
- aA set UB is open by definition.
Before
- aA set is open by definition.
After
- aA set is open by definition.
Before
- aEvery open ball is open.
After
- aEvery open ball is open.
Before
- aEvery open ball B is open.
After
- aEvery open ball is open.
Before
- aBoth are open.
After
- aBoth and are open.
Before
- aSee for the proof.
After
- aSee {{zz99}} for the proof.
Display ■
A display is a block form, beside paragraph, heading and item: it holds one reference alone and draws it as a block. A formula on its own line is a display, and the same formula in a sentence is inline; the atom is the same and its type says how it draws in each place. Only a block holding one reference alone takes the form, and a block that no longer does, after any edit, is prose again. Backspace at the start of a display joins it to the paragraph above and its atom lands inline. Enter at its end opens a paragraph under it. In the editor the form is Cmd+Alt+4.
Before
- aTwo sets are always open:
- b
After
- aTwo sets are always open:
- b::
Before
- aTwo sets are always open:
After
- aTwo sets are always open:
Before
- a::
After
- a
Before
- aTwo sets are always open:
After
- aTwo sets are always open:
- b::
Before
- a::
After
- a holds
Before
- aTwo sets are always open:
- b::
After
- aTwo sets are always open:
- b::
Before
- aTwo sets are always open:
- b::
After
- aTwo sets are always open:
- b::
Before
- aTwo sets are always open:
- b::
After
- aTwo sets are always open:
Before
- a::
After
- a::
Before
- a::
After
- a
Before
- a::
After
- a::
- b
Before
- a::
After
- a—
- b::
Before
- aThe pair is the first axiom.
- b::
After
- aThe pair is the first axiom.
- b::