├── docs ├── .nojekyll ├── src │ ├── # │ ├── .gitignore │ ├── appendix.md │ ├── rtf.md │ ├── frontend.md │ ├── deploying.md │ ├── book.toml │ ├── server.md │ ├── storage.md │ ├── development.md │ ├── editor-component.md │ ├── writing-an-integration-test.md │ ├── webassembly-interface.md │ ├── intro.md │ ├── editor-basics.md │ ├── edit-server-binary.md │ ├── dokku.md │ ├── server-apis.md │ ├── glossary.md │ ├── SUMMARY.md │ └── intro-testing.md ├── theme │ └── source-commit └── index.html ├── edit-server ├── migrations │ ├── .gitkeep │ ├── 2018-06-12-235631_logging │ │ ├── down.sql │ │ └── up.sql │ └── 2018-03-02-223250_create_posts │ │ ├── down.sql │ │ └── up.sql ├── .gitignore ├── .env ├── src │ ├── graphql.rs │ ├── db.rs │ ├── db │ │ ├── schema.rs │ │ ├── types.rs │ │ └── conn.rs │ ├── lib.rs │ └── bin │ │ └── edit-server-logs.rs ├── diesel.toml └── Cargo.toml ├── dist └── deploy │ ├── CHECKS │ ├── Dockerfile │ └── nginx.conf ├── rust-toolchain ├── edit-frontend ├── .gitignore ├── .DS_Store ├── templates │ ├── favicon.ico │ ├── favicon.png │ ├── react.hbs │ └── client.hbs ├── static │ ├── texgyreheros-bold.otf │ ├── texgyreheros-italic.otf │ ├── texgyreheroscn-bold.otf │ ├── texgyreheros-regular.otf │ ├── texgyreheroscn-italic.otf │ ├── texgyreheroscn-regular.otf │ ├── texgyreheros-bolditalic.otf │ └── texgyreheroscn-bolditalic.otf ├── styles │ ├── edit.scss │ ├── multi.scss │ ├── footer.scss │ └── modal.scss ├── tsconfig.json ├── src │ ├── editor │ │ └── controller.ts │ ├── index.js │ └── app │ │ ├── route.ts │ │ └── proxy.ts ├── package.json └── webpack.config.js ├── rustfmt.toml ├── oatie ├── tests │ ├── transform │ │ ├── 1 │ │ ├── 3 │ │ ├── 4 │ │ ├── 5 │ │ ├── 6 │ │ ├── 7 │ │ ├── 8 │ │ ├── 9 │ │ ├── 10 │ │ ├── 11 │ │ ├── 12 │ │ ├── 13 │ │ ├── 14 │ │ ├── 17 │ │ ├── 18 │ │ ├── 19 │ │ ├── 20 │ │ ├── 21 │ │ ├── 25 │ │ ├── 26 │ │ ├── 30 │ │ ├── 31 │ │ ├── 34 │ │ ├── 36 │ │ ├── caret-3 │ │ ├── caret-5 │ │ ├── caret-4 │ │ ├── caret-1 │ │ ├── caret-9 │ │ ├── caret-7 │ │ ├── caret-6 │ │ ├── caret-8 │ │ ├── caret-10 │ │ ├── todo │ │ │ ├── 15 │ │ │ ├── 22 │ │ │ └── 35 │ │ ├── caret-2 │ │ ├── caret-11 │ │ ├── caret-46 │ │ ├── caret-60 │ │ ├── caret-53 │ │ ├── caret-51 │ │ ├── caret-56 │ │ ├── caret-41 │ │ ├── caret-57 │ │ ├── caret-54 │ │ ├── caret-55 │ │ ├── caret-42 │ │ ├── caret-30 │ │ ├── caret-59 │ │ ├── caret-17 │ │ ├── caret-15 │ │ ├── caret-37 │ │ ├── caret-40 │ │ ├── caret-39 │ │ ├── caret-25 │ │ ├── caret-18 │ │ ├── caret-50 │ │ └── caret-28 │ └── transform.rs ├── src │ ├── core.rs │ ├── wasm.rs │ ├── lib.rs │ └── core │ │ └── ot.rs ├── Cargo.toml └── etc │ └── why.rs ├── edit-common ├── src │ └── markdown │ │ └── mod.rs ├── tests │ ├── transform │ │ ├── 0 │ │ ├── 11 │ │ ├── 12 │ │ ├── 15 │ │ ├── 16 │ │ ├── 18 │ │ ├── 21 │ │ ├── 26 │ │ ├── 28 │ │ ├── 34 │ │ ├── 35 │ │ ├── 37 │ │ ├── 39 │ │ ├── 47 │ │ ├── 59 │ │ ├── 60 │ │ ├── 73 │ │ ├── 80 │ │ ├── 81 │ │ ├── 85 │ │ ├── 90 │ │ ├── 94 │ │ ├── 97 │ │ ├── 98 │ │ ├── 99 │ │ ├── 106 │ │ ├── 113 │ │ ├── 115 │ │ ├── 118 │ │ ├── 124 │ │ ├── 130 │ │ ├── 135 │ │ ├── 137 │ │ ├── 140 │ │ ├── 142 │ │ ├── 146 │ │ ├── 148 │ │ ├── 149 │ │ ├── 155 │ │ ├── 158 │ │ ├── 159 │ │ ├── 163 │ │ ├── 164 │ │ ├── 171 │ │ ├── 175 │ │ ├── 176 │ │ ├── 177 │ │ ├── 180 │ │ ├── 194 │ │ ├── 210 │ │ ├── 212 │ │ ├── 213 │ │ ├── 215 │ │ ├── 219 │ │ ├── 223 │ │ ├── 225 │ │ ├── 237 │ │ ├── 240 │ │ ├── 248 │ │ ├── 251 │ │ ├── 265 │ │ ├── 275 │ │ ├── 277 │ │ ├── 279 │ │ ├── 280 │ │ ├── 322 │ │ ├── 333 │ │ ├── 377 │ │ ├── 396 │ │ ├── 408 │ │ ├── 424 │ │ ├── 433 │ │ ├── 440 │ │ ├── 443 │ │ ├── 455 │ │ ├── 465 │ │ ├── 466 │ │ ├── 484 │ │ ├── 496 │ │ ├── 501 │ │ ├── 517 │ │ ├── 549 │ │ ├── 583 │ │ ├── 633 │ │ ├── 638 │ │ ├── 653 │ │ ├── 700 │ │ ├── 718 │ │ ├── 725 │ │ ├── 769 │ │ ├── 779 │ │ ├── 789 │ │ ├── 791 │ │ ├── 801 │ │ ├── 826 │ │ ├── 828 │ │ ├── 830 │ │ └── 845 │ └── transform.rs └── Cargo.toml ├── .gitignore ├── tools ├── tools.bat ├── Configure.toml ├── Cargo.toml ├── README.md ├── edit-client └── src │ └── lib.rs └── LICENSE.txt /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/src/#: -------------------------------------------------------------------------------- 1 | # Appendix 2 | -------------------------------------------------------------------------------- /docs/src/.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | -------------------------------------------------------------------------------- /edit-server/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dist/deploy/CHECKS: -------------------------------------------------------------------------------- 1 | /favicon.png 2 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2018-12-05 2 | -------------------------------------------------------------------------------- /edit-server/.gitignore: -------------------------------------------------------------------------------- 1 | backups 2 | 3 | -------------------------------------------------------------------------------- /edit-server/.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=edit.sqlite3 2 | -------------------------------------------------------------------------------- /edit-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src/bindgen/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | imports_layout = "Vertical" 2 | edition = "2018" 3 | -------------------------------------------------------------------------------- /edit-server/migrations/2018-06-12-235631_logging/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE logs -------------------------------------------------------------------------------- /docs/theme/source-commit: -------------------------------------------------------------------------------- 1 | https://github.com/rust-lang-nursery/mdBook@65198a7 -------------------------------------------------------------------------------- /edit-server/migrations/2018-03-02-223250_create_posts/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE posts -------------------------------------------------------------------------------- /edit-frontend/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/.DS_Store -------------------------------------------------------------------------------- /docs/src/appendix.md: -------------------------------------------------------------------------------- 1 | # Appendix 2 | 3 | Content that wasn't included in the rest of the docs. 4 | 5 | {{#toc}} 6 | -------------------------------------------------------------------------------- /edit-frontend/templates/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/templates/favicon.ico -------------------------------------------------------------------------------- /edit-frontend/templates/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/templates/favicon.png -------------------------------------------------------------------------------- /oatie/tests/transform/31: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([])])] 2 | [] 3 | 4 | [] 5 | [AddWithGroup([AddWithGroup([AddChars("hi")])])] -------------------------------------------------------------------------------- /oatie/tests/transform/caret-3: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "pre"}, [AddSkip(14)])] 3 | 4 | [DelGroup([DelSkip(13)])] 5 | [] 6 | -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheros-bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheros-bold.otf -------------------------------------------------------------------------------- /oatie/tests/transform/caret-5: -------------------------------------------------------------------------------- 1 | [] 2 | [AddWithGroup([AddChars("m oW ")])] 3 | 4 | [DelGroup([DelWithGroup([]), DelSkip(17)])] 5 | [] -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheros-italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheros-italic.otf -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheroscn-bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheroscn-bold.otf -------------------------------------------------------------------------------- /oatie/tests/transform/17: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddChars("hi"), AddSkip(6)])] 3 | 4 | [] 5 | [AddSkip(6), AddChars("a")] 6 | -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheros-regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheros-regular.otf -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheroscn-italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheroscn-italic.otf -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheroscn-regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheroscn-regular.otf -------------------------------------------------------------------------------- /edit-common/src/markdown/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod de; 2 | pub mod ser; 3 | 4 | pub use self::de::markdown_to_doc; 5 | pub use self::ser::doc_to_markdown; 6 | -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheros-bolditalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheros-bolditalic.otf -------------------------------------------------------------------------------- /oatie/tests/transform/6: -------------------------------------------------------------------------------- 1 | [] 2 | [AddSkip(1), AddChars("1")] 3 | 4 | [] 5 | [AddSkip(1), AddChars("2")] 6 | 7 | [] 8 | [AddSkip(1), AddChars("12")] -------------------------------------------------------------------------------- /edit-frontend/static/texgyreheroscn-bolditalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcr/edit-text/HEAD/edit-frontend/static/texgyreheroscn-bolditalic.otf -------------------------------------------------------------------------------- /edit-server/migrations/2018-03-02-223250_create_posts/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE posts ( 2 | id VARCHAR NOT NULL PRIMARY KEY, 3 | body TEXT NOT NULL 4 | ) -------------------------------------------------------------------------------- /oatie/tests/transform/caret-4: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "h1"}, [AddChars("qra "), AddSkip(13)])] 3 | 4 | [DelGroup([DelGroup([]), DelSkip(12)])] 5 | [] -------------------------------------------------------------------------------- /edit-server/src/graphql.rs: -------------------------------------------------------------------------------- 1 | //! GraphQL code. 2 | 3 | pub mod client; 4 | pub mod server; 5 | 6 | pub use self::client::*; 7 | pub use self::server::*; 8 | -------------------------------------------------------------------------------- /oatie/tests/transform/7: -------------------------------------------------------------------------------- 1 | [] 2 | [AddSkip(12), AddChars("_")] 3 | 4 | [] 5 | [AddSkip(5), AddChars("D")] 6 | 7 | [] 8 | [AddSkip(5), AddChars("D"), AddSkip(7), AddChars("_")] -------------------------------------------------------------------------------- /oatie/tests/transform/8: -------------------------------------------------------------------------------- 1 | [] 2 | [AddSkip(1), AddChars("a")] 3 | 4 | [] 5 | [AddSkip(2), AddChars("c")] 6 | 7 | [] 8 | [AddSkip(1), AddChars("a"), AddSkip(1), AddChars("c")] -------------------------------------------------------------------------------- /docs/src/rtf.md: -------------------------------------------------------------------------------- 1 | # Rich Text 2 | 3 | This section describes the Rich Text schema used by edit-text. This schema is 4 | designed to be Markdown-compatible. 5 | 6 | {{#toc}} 7 | -------------------------------------------------------------------------------- /edit-server/migrations/2018-06-12-235631_logging/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE logs ( 2 | rowid INTEGER NOT NULL PRIMARY KEY, 3 | source VARCHAR NOT NULL, 4 | body TEXT NOT NULL 5 | ) -------------------------------------------------------------------------------- /oatie/tests/transform/5: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(6)])] 3 | 4 | [] 5 | [AddGroup({"tag": "p"}, [AddSkip(6)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(6)])] -------------------------------------------------------------------------------- /edit-server/diesel.toml: -------------------------------------------------------------------------------- 1 | # For documentation on how to configure this file, 2 | # see diesel.rs/guides/configuring-diesel-cli 3 | 4 | [print_schema] 5 | file = "src/schema.rs" 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/12: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(30)])] 3 | 4 | [] 5 | [AddGroup({"tag": "h1"}, [AddSkip(30)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(30)])] -------------------------------------------------------------------------------- /oatie/tests/transform/19: -------------------------------------------------------------------------------- 1 | [] 2 | [AddWithGroup([AddWithGroup([AddWithGroup([AddSkip(6), AddChars("a")])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(6)])])])] 5 | [] -------------------------------------------------------------------------------- /docs/src/frontend.md: -------------------------------------------------------------------------------- 1 | # Frontend 2 | 3 | The Frontend is written in TypeScript and communicates with a WebAssembly 4 | component containing the Client and Controller. 5 | 6 | {{#toc}} 7 | -------------------------------------------------------------------------------- /docs/src/deploying.md: -------------------------------------------------------------------------------- 1 | # Deploying 2 | 3 | This section describes how you can compile a standalone edit-server binary, 4 | and deploy to a remote server or hosted service like Dokku. 5 | 6 | {{#toc}} 7 | -------------------------------------------------------------------------------- /docs/src/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Tim Ryan"] 3 | multilingual = false 4 | src = "." 5 | title = "edit-text internals" 6 | 7 | [build] 8 | build-dir = "../book" 9 | create-missing = false 10 | -------------------------------------------------------------------------------- /oatie/tests/transform/1: -------------------------------------------------------------------------------- 1 | [DelSkip(1)] 2 | [AddWithGroup([AddWithGroup([AddWithGroup([AddChars("1234"), AddSkip(6)])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelWithGroup([DelChars(4), DelSkip(2)])])])] 5 | [] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/18: -------------------------------------------------------------------------------- 1 | [DelSkip(1)] 2 | [AddWithGroup([AddWithGroup([AddWithGroup([AddChars("1234"), AddSkip(6)])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelWithGroup([DelChars(4), DelSkip(2)])])])] 5 | [] -------------------------------------------------------------------------------- /oatie/tests/transform/14: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "bullet"}, [AddSkip(15)])] 3 | 4 | [] 5 | [AddGroup({"tag": "p"}, [AddSkip(15)])] 6 | 7 | [] 8 | [AddGroup({"tag": "bullet"}, [AddGroup({"tag": "p"}, [AddSkip(15)])])] -------------------------------------------------------------------------------- /oatie/tests/transform/4: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(4)])] 3 | 4 | [] 5 | [AddGroup({"tag": "p"}, [AddSkip(6)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(4)]), AddGroup({"tag": "p"}, [AddSkip(2)])] -------------------------------------------------------------------------------- /docs/src/server.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | The server binary serves HTTP content, a GraphQL endpoint for performing 4 | page-level commands, and a WebSocket endpoint for synchronizing document 5 | content. 6 | 7 | {{#toc}} 8 | -------------------------------------------------------------------------------- /oatie/tests/transform/13: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(15)])] 3 | 4 | [] 5 | [AddGroup({"tag": "h1"}, [AddSkip(30)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(15)]), AddGroup({"tag": "h1"}, [AddSkip(15)])] -------------------------------------------------------------------------------- /edit-common/tests/transform/0: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hi"), 5 | ]) 6 | ] 7 | 8 | a_del: [ 9 | ] 10 | a_add: [ 11 | ] 12 | 13 | b_del: [ 14 | ] 15 | b_add: [ 16 | ] 17 | -------------------------------------------------------------------------------- /edit-common/tests/transform/277: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hi"), 5 | ]) 6 | ] 7 | 8 | a_del: [ 9 | ] 10 | a_add: [ 11 | ] 12 | 13 | b_del: [ 14 | ] 15 | b_add: [ 16 | ] 17 | -------------------------------------------------------------------------------- /oatie/tests/transform/11: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(5)])] 3 | 4 | [] 5 | [AddSkip(2), AddGroup({"tag": "p"}, [AddSkip(2)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(4)]), AddGroup({"tag": "p"}, [AddSkip(1)])] -------------------------------------------------------------------------------- /edit-server/src/db.rs: -------------------------------------------------------------------------------- 1 | //! Database connection management. 2 | 3 | pub mod conn; 4 | pub mod queries; 5 | pub mod schema; 6 | pub mod types; 7 | 8 | pub use self::conn::*; 9 | pub use self::queries::*; 10 | pub use self::types::*; 11 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Redirecting...

9 | 10 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-1: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([]), DelSkip(2)])] 2 | [AddWithGroup([AddSkip(1), AddGroup({"tag": "caret"}, [])])] 3 | 4 | [DelWithGroup([DelGroup([]), DelSkip(2)])] 5 | [AddWithGroup([AddSkip(1), AddGroup({"tag": "caret"}, [])])] -------------------------------------------------------------------------------- /oatie/tests/transform/30: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(6)])])])] 2 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "p"}, [AddChars("hi"), AddSkip(6)])])])] 3 | 4 | [] 5 | [AddWithGroup([AddWithGroup([AddWithGroup([AddSkip(6), AddChars("a")])])])] 6 | -------------------------------------------------------------------------------- /oatie/src/core.rs: -------------------------------------------------------------------------------- 1 | //! Essential crates for `oatie`. These are re-exported in oatie/src/lib.rs. 2 | 3 | pub mod apply; 4 | pub mod compose; 5 | pub mod doc; 6 | pub mod place; 7 | pub mod schema; 8 | pub mod transform; 9 | pub mod string; 10 | pub mod ot; 11 | -------------------------------------------------------------------------------- /oatie/tests/transform/9: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(5)]), AddGroup({"tag": "p"}, [AddSkip(5)])] 3 | 4 | [] 5 | [AddSkip(11), AddChars("_")] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(5)]), AddGroup({"tag": "p"}, [AddSkip(5)]), AddSkip(1), AddChars("_")] -------------------------------------------------------------------------------- /docs/src/storage.md: -------------------------------------------------------------------------------- 1 | # Storage 2 | 3 | edit-text uses a local SQLite database for storage. 4 | 5 | A file called `edit-server/edit.sqlite3` will be created when you first run `./tools server`. This file can be copied or deleted, and a new version will be cated for you. 6 | -------------------------------------------------------------------------------- /edit-frontend/styles/edit.scss: -------------------------------------------------------------------------------- 1 | @import 'toolbar'; 2 | @import 'footer'; 3 | @import 'modal'; 4 | @import 'debug'; 5 | @import 'layout'; 6 | @import 'multi'; 7 | .edit-text { @import "edit-text"; } 8 | 9 | // For sanity 10 | * { 11 | box-sizing: border-box; 12 | } 13 | -------------------------------------------------------------------------------- /oatie/tests/transform/34: -------------------------------------------------------------------------------- 1 | [] 2 | [AddWithGroup([AddGroup({"class": "italic", "tag": "span"}, [AddSkip(5)])])] 3 | 4 | [] 5 | [AddWithGroup([AddGroup({"class": "bold", "tag": "span"}, [AddSkip(5)])])] 6 | 7 | [] 8 | [AddWithGroup([AddGroup({"class": "bold italic", "tag": "span"}, [AddSkip(5)])])] -------------------------------------------------------------------------------- /docs/src/development.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | edit-text uses a build system written in Rust, `./tools`, which is a basic 4 | wrapper over `cargo` and `npm` commands and other essential project functionality. 5 | This is used to invoke tests as well as launch the edit-text server. 6 | 7 | {{#toc}} 8 | -------------------------------------------------------------------------------- /oatie/tests/transform/10: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "h1"}, [AddSkip(15)]), AddGroup({"tag": "p"}, [AddSkip(15)])] 3 | 4 | [] 5 | [AddGroup({"tag": "h1"}, [AddSkip(15)]), AddGroup({"tag": "p"}, [AddSkip(15)])] 6 | 7 | [] 8 | [AddGroup({"tag": "h1"}, [AddSkip(15)]), AddGroup({"tag": "p"}, [AddSkip(15)])] -------------------------------------------------------------------------------- /oatie/tests/transform/21: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(9)])])])] 2 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "h1"}, [AddSkip(9)])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(9)])])])] 5 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "h2"}, [AddSkip(9)])])])] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-9: -------------------------------------------------------------------------------- 1 | [DelGroup([DelSkip(14)])] 2 | [AddGroup({"tag": "h1"}, [AddChars(" i8 Cr")]), AddGroup({"tag": "p"}, [AddChars("64 R"), AddSkip(14)])] 3 | 4 | [DelGroup([DelWithGroup([]), DelSkip(13)])] 5 | [AddGroup({"tag": "h2"}, [AddWithGroup([]), AddChars("iX "), AddSkip(13)])] 6 | -------------------------------------------------------------------------------- /docs/src/editor-component.md: -------------------------------------------------------------------------------- 1 | # Editor Component 2 | 3 | The frontend is written in React, and the editor is a react component. 4 | 5 | ```javascript 6 | 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/src/writing-an-integration-test.md: -------------------------------------------------------------------------------- 1 | # Writing an integration test 2 | 3 | Integration tests use a browser driver like `geckodriver` or `chromedriver` to 4 | power a user agent that performs actual tests of the editor. 5 | 6 | Integration tests live in "build-tools/tests/integration.rs". 7 | 8 | 9 | -------------------------------------------------------------------------------- /oatie/tests/transform/25: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(17)])])])] 2 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "h1"}, [AddSkip(6)]), AddGroup({"tag": "p"}, [AddSkip(11)])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelWithGroup([DelSkip(6), DelChars(1), DelSkip(10)])])])] 5 | [] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-7: -------------------------------------------------------------------------------- 1 | [DelGroup([DelSkip(14)])] 2 | [AddGroup({"tag": "p"}, [AddChars("YkEB66"), AddSkip(14)])] 3 | 4 | [DelGroup([DelWithGroup([]), DelSkip(13)])] 5 | [AddGroup({"tag": "h1"}, [AddWithGroup([]), AddChars("S t g7ah3 3U7q HB T2mQ H4P")]), AddGroup({"tag": "p"}, [AddChars("K"), AddSkip(13)])] -------------------------------------------------------------------------------- /oatie/tests/transform/20: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(6)])])])] 2 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "p"}, [AddSkip(6)])])])] 3 | 4 | 5 | [DelSkip(1)] 6 | [AddWithGroup([AddWithGroup([AddWithGroup([AddSkip(2), AddChars("1"), AddSkip(2), AddChars("2"), AddSkip(2), AddChars("3")])])])] 7 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-6: -------------------------------------------------------------------------------- 1 | [DelGroup([DelSkip(38)])] 2 | [AddGroup({"tag": "h2"}, [AddSkip(5)]), AddGroup({"tag": "h2"}, [AddSkip(33)])] 3 | 4 | [DelGroup([DelSkip(5), DelWithGroup([]), DelSkip(32)])] 5 | [AddGroup({"tag": "h1"}, [AddSkip(5), AddWithGroup([]), AddSkip(19)]), AddGroup({"tag": "p"}, [AddSkip(13)])] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-8: -------------------------------------------------------------------------------- 1 | [DelGroup([DelSkip(14)])] 2 | [AddGroup({"tag": "h3"}, [AddChars(" 1o6hW A NM1 10ya A C0i")]), AddGroup({"tag": "p"}, [AddChars(" 3a"), AddSkip(14)])] 3 | 4 | [DelGroup([DelWithGroup([]), DelSkip(13)])] 5 | [AddGroup({"tag": "p"}, [AddWithGroup([]), AddChars(" d 5k"), AddSkip(13)])] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-10: -------------------------------------------------------------------------------- 1 | [DelGroup([DelSkip(14)])] 2 | [AddGroup({"tag": "pre"}, [AddChars(" x S J 33qa R")]), AddGroup({"tag": "h3"}, [AddChars("S40"), AddSkip(14)])] 3 | 4 | [DelGroup([DelWithGroup([]), DelSkip(13)])] 5 | [AddGroup({"tag": "h1"}, [AddWithGroup([]), AddChars("04")]), AddGroup({"tag": "p"}, [AddSkip(13)])] -------------------------------------------------------------------------------- /oatie/tests/transform/todo/22: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([DelSkip(2)])])] 2 | [AddWithGroup([AddGroup({"tag": "li"}, [AddSkip(1)]), AddGroup({"tag": "li"}, [AddSkip(1)])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelGroup([DelSkip(3)]), DelSkip(1)])])] 5 | [AddWithGroup([AddWithGroup([AddGroup({"tag": "h1"}, [AddSkip(3)]), AddSkip(1)])])] 6 | -------------------------------------------------------------------------------- /edit-server/src/db/schema.rs: -------------------------------------------------------------------------------- 1 | table! { 2 | logs (rowid) { 3 | rowid -> Integer, 4 | source -> Text, 5 | body -> Text, 6 | } 7 | } 8 | 9 | table! { 10 | posts (id) { 11 | id -> Text, 12 | body -> Text, 13 | } 14 | } 15 | 16 | allow_tables_to_appear_in_same_query!(logs, posts,); 17 | -------------------------------------------------------------------------------- /edit-frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "module": "commonjs", 5 | "target": "es6", 6 | "jsx": "react", 7 | "allowSyntheticDefaultImports": true, 8 | "allowJs": true, 9 | "strictNullChecks": true, 10 | "noImplicitAny": true, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /oatie/tests/transform/todo/15: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "p"}, [AddSkip(10)]), AddGroup({"tag": "p"}, [AddSkip(10)])] 3 | 4 | [] 5 | [AddSkip(5), AddGroup({"tag": "b"}, [AddSkip(10)])] 6 | 7 | [] 8 | [AddGroup({"tag": "p"}, [AddSkip(5), AddGroup({"tag": "b"}, [AddSkip(5)])]), AddGroup({"tag": "p"}, [AddGroup({"tag": "b"}, [AddSkip(5)]), AddSkip(5)])] -------------------------------------------------------------------------------- /oatie/tests/transform/caret-2: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([]), DelWithGroup([]), DelSkip(2)])] 2 | [AddWithGroup([AddWithGroup([]), AddSkip(1), AddGroup({"client": "left", "tag": "caret"}, [])])] 3 | 4 | [DelWithGroup([DelWithGroup([]), DelGroup([]), DelSkip(2)])] 5 | [AddWithGroup([AddWithGroup([]), AddSkip(1), AddGroup({"client": "right", "tag": "caret"}, [])])] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/26: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([DelSkip(7), DelGroup([DelSkip(6)]), DelSkip(3)])])] 2 | [AddWithGroup([AddGroup({"tag": "h1"}, [AddSkip(7), AddGroup({"tag": "b"}, [AddSkip(3)])]), AddGroup({"tag": "p"}, [AddGroup({"tag": "b"}, [AddSkip(3)]), AddSkip(3)])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelSkip(7), DelGroup([DelSkip(6)]), DelSkip(3)])])] 5 | [] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | target/ 3 | docs/book 4 | edit/test.txt 5 | edit/log 6 | edit/log2 7 | edit/in 8 | Vagrantfile 9 | .vagrant 10 | node_modules 11 | dist/deploy/edit-server 12 | dist/link 13 | *.sqlite3 14 | *.sqlite3-journal 15 | ubuntu*.log 16 | edit-frontend/dist/ 17 | .cargo 18 | x.d 19 | x.bash 20 | x.fish 21 | _x 22 | logs/* 23 | *.code-workspace 24 | -------------------------------------------------------------------------------- /docs/src/webassembly-interface.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Interface 2 | 3 | The frontend invokes the client over a `wasm-bindgen` bridge, exchanging JSON messages ("commands"). The frontend exposes an editor interface using React. The client instructs the frontend on what text styling options to expose, and responds to keypresses with updated HTML to render in the editor. 4 | 5 | -------------------------------------------------------------------------------- /oatie/tests/transform/3: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelGroup([DelSkip(7), DelGroup([DelSkip(6)]), DelSkip(3)])])] 2 | [AddWithGroup([AddGroup({"tag": "h1"}, [AddSkip(7), AddGroup({"tag": "b"}, [AddSkip(3)])]), AddGroup({"tag": "p"}, [AddGroup({"tag": "b"}, [AddSkip(3)]), AddSkip(3)])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelSkip(7), DelGroup([DelSkip(6)]), DelSkip(3)])])] 5 | [] 6 | -------------------------------------------------------------------------------- /oatie/tests/transform/todo/35: -------------------------------------------------------------------------------- 1 | [] 2 | [AddGroup({"tag": "span", "class": "bold"}, [AddSkip(16)])] 3 | 4 | [] 5 | [AddSkip(6), AddGroup({"tag": "span", "class": "italic"}, [AddSkip(18)])] 6 | 7 | [] 8 | [AddGroup({"tag": "span", "class": "bold"}, [AddSkip(6)]),AddGroup({"tag": "span", "class": "bold italic"}, [AddSkip(10)]),AddGroup({"tag": "span", "class": "italic"}, [AddSkip(8)])] 9 | -------------------------------------------------------------------------------- /tools: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Calling ./tools is equivalent to cargo run --bin build-tools -- . 4 | # This convenience script will build the tool binary if it does not yet exist; 5 | # otherwise it will quiety rebuild the binary and then run it with your arguments. 6 | 7 | if [ ! -e ./target/debug/build-tools ]; then cargo build --bin build-tools; fi 8 | exec cargo run --bin build-tools --quiet -- "$@" 9 | -------------------------------------------------------------------------------- /tools.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM Calling .\tools is equivalent to cargo run --bin build-tools -- . 4 | REM This convenience script will build the tool binary if it does not yet exist; 5 | REM otherwise it will quiety rebuild the binary and then run it with your arguments. 6 | 7 | if not exist .\target\debug\build-tools.exe cargo build --bin build-tools 8 | cargo run --bin build-tools --quiet -- %* 9 | -------------------------------------------------------------------------------- /oatie/tests/transform/36: -------------------------------------------------------------------------------- 1 | [DelWithGroup([DelWithGroup([DelSkip(1), DelWithGroup([DelSkip(24)])])])] 2 | [AddWithGroup([AddWithGroup([AddSkip(1), AddWithGroup([AddSkip(24), AddChars(" This is part of the goals of collaborative editing.")])])])] 3 | 4 | [DelWithGroup([DelWithGroup([DelSkip(1), DelWithGroup([DelSkip(6), DelChars(10)])])])] 5 | [AddWithGroup([AddWithGroup([AddSkip(1), AddWithGroup([AddSkip(6), AddChars("nouns")])])])] 6 | -------------------------------------------------------------------------------- /oatie/src/wasm.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[cfg(target_arch = "wasm32")] 4 | #[macro_export] 5 | macro_rules! console_log { 6 | ($($t:tt)*) => ($crate::wasm::log(&format!($($t)*))) 7 | } 8 | 9 | #[cfg(not(target_arch = "wasm32"))] 10 | macro_rules! console_log { 11 | ($($t:tt)*) => {}; 12 | } 13 | 14 | #[wasm_bindgen] 15 | extern "C" { 16 | #[wasm_bindgen(js_namespace = console)] 17 | pub fn log(msg: &str); 18 | } 19 | -------------------------------------------------------------------------------- /docs/src/intro.md: -------------------------------------------------------------------------------- 1 | # edit-text 2 | 3 | edit-text is a Markdown-compatible document editor that supports collaborative editing. Its server and client are written in Rust, and its frontend uses TypeScript and WebAssembly. 4 | 5 |
6 | 7 |
8 | 9 | For installation instructions, please read [**Getting Started**](getting-started.html). 10 | -------------------------------------------------------------------------------- /edit-frontend/src/editor/controller.ts: -------------------------------------------------------------------------------- 1 | // Interfaces from frontend (JS) to client (wasm or proxy) and server (wasm or empty). 2 | 3 | import 'react'; 4 | 5 | import { ControllerCommand } from '../bindgen/edit_client'; 6 | 7 | export interface ControllerImpl { 8 | onMessage: (msg: any) => void | null; 9 | onClose: () => void | null; 10 | onError: (error: any) => void | null; 11 | 12 | connect(): Promise; 13 | sendCommand(command: ControllerCommand): void; 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/editor-basics.md: -------------------------------------------------------------------------------- 1 | # Editor Basics 2 | 3 | This section describes the basics of how editors are stored and modified. 4 | The content of the editor is a "document" composed of text and 5 | groups (which can contain other text or groups). Operations are data types that 6 | can modify the document by adding or deleting content. These operations are 7 | composable, and also can occur concurrently—conflicts are resolved with the 8 | operational transform algorithm. 9 | 10 | {{#toc}} 11 | -------------------------------------------------------------------------------- /Configure.toml: -------------------------------------------------------------------------------- 1 | ## Crate-level features that ./tools enables in this workspace. 2 | ## After editing this file, restart any running ./tools processes. 3 | 4 | # Always send RenderFull instead of RenderDelta. 5 | full_client_updates = true 6 | 7 | # Use wee_alloc instead of dlalloc. 8 | use_wee_alloc = false 9 | 10 | # Perform a comparison to validate if generated bytecode is correct. 11 | validate_bytecode = true 12 | 13 | # Print out pretty logs to the console. 14 | console_command_log = false 15 | -------------------------------------------------------------------------------- /dist/deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile for running the edit-server 2 | 3 | FROM nginx 4 | 5 | RUN rm /etc/nginx/conf.d/default.conf || true 6 | RUN rm /etc/nginx/conf.d/examplessl.conf || true 7 | 8 | RUN apt-get update; apt-get install sqlite3 libsqlite3-dev -y 9 | 10 | ADD nginx.conf /etc/nginx/nginx.conf 11 | ADD . /app 12 | 13 | WORKDIR /app 14 | EXPOSE 80 15 | 16 | RUN mkdir -p edit/log; mkdir -p log; 17 | 18 | CMD service nginx restart; RUST_BACKTRACE=1 MERCUTIO_SYNC_LOG=0 ./edit-server 19 | -------------------------------------------------------------------------------- /docs/src/edit-server-binary.md: -------------------------------------------------------------------------------- 1 | # Running as a binary 2 | 3 | The `edit-server/` crate can export a binary that you can deploy to a remote 4 | server, containing the source code of the client and the ability to talk to 5 | a locally instantiated SQLite database. 6 | 7 | ``` 8 | ./tools server 9 | ``` 10 | 11 | To build a standalone binary that bundles client files statically: 12 | 13 | ``` 14 | cd edit-server 15 | cargo build --release --features standalone 16 | ../target/release/edit-server 17 | ``` 18 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-11: -------------------------------------------------------------------------------- 1 | [DelGroup([DelWithGroup([]), DelSkip(2)]), DelWithGroup([DelGroup([])])] 2 | [AddGroup({"tag": "h3"}, [AddWithGroup([]), AddSkip(1), AddChars("u")]), AddGroup({"tag": "p"}, [AddChars("7D")]), AddGroup({"tag": "p"}, [AddGroup({"tag": "caret", "client": "left"}, []), AddChars("2"), AddSkip(1)]), AddWithGroup([])] 3 | 4 | [DelGroup([DelGroup([]), DelSkip(2)])] 5 | [AddGroup({"tag": "h2"}, [AddSkip(1)]), AddGroup({"tag": "p"}, [AddGroup({"client": "right", "tag": "caret"}, []), AddSkip(1)])] 6 | -------------------------------------------------------------------------------- /edit-common/tests/transform/275: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("123"), 6 | ]) 7 | ]), 8 | ] 9 | 10 | a_del: [ 11 | DelWithGroup([ 12 | DelGroup([ 13 | DelSkip(2), 14 | DelChars(1), 15 | ]) 16 | ]), 17 | ] 18 | a_add: [ 19 | AddWithGroup([ 20 | AddGroup({"tag": "p"}, [ 21 | AddSkip(2), 22 | ]) 23 | ]), 24 | ] 25 | 26 | b_del: [ 27 | DelGroup([ 28 | DelSkip(1), 29 | ]) 30 | ] 31 | b_add: [ 32 | ] 33 | -------------------------------------------------------------------------------- /edit-common/tests/transform/280: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("123"), 6 | ]) 7 | ]), 8 | ] 9 | 10 | a_del: [ 11 | DelWithGroup([ 12 | DelGroup([ 13 | DelSkip(2), 14 | DelChars(1), 15 | ]) 16 | ]), 17 | ] 18 | a_add: [ 19 | AddWithGroup([ 20 | AddGroup({"tag": "p"}, [ 21 | AddSkip(2), 22 | ]) 23 | ]), 24 | ] 25 | 26 | b_del: [ 27 | DelGroup([ 28 | DelSkip(1), 29 | ]) 30 | ] 31 | b_add: [ 32 | ] 33 | -------------------------------------------------------------------------------- /edit-common/tests/transform/90: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "pre"}, [ 4 | DocGroup({"tag": "caret", "client": "c"}, []), 5 | DocChars("h"), 6 | DocGroup({"tag": "caret", "client": "d"}, []) 7 | ]), 8 | ] 9 | 10 | a_del: [ 11 | DelWithGroup([ 12 | DelGroup([]) 13 | ]), 14 | ] 15 | a_add: [ 16 | AddWithGroup([ 17 | AddSkip(1) 18 | ]), 19 | ] 20 | 21 | b_del: [ 22 | DelGroup([ 23 | DelSkip(2), 24 | DelGroup([]) 25 | ]) 26 | ] 27 | b_add: [ 28 | AddGroup({"tag": "p"}, [ 29 | AddSkip(2), 30 | ]) 31 | ] 32 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-46: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocGroup({"tag": "caret", "client": "c"}, []), 5 | DocGroup({"tag": "caret", "client": "d"}, []) 6 | ]), 7 | ] 8 | 9 | a_del: [ 10 | DelGroup([ 11 | DelGroup([]), 12 | DelWithGroup([]) 13 | ]), 14 | ] 15 | a_add: [ 16 | AddGroup({"tag": "p"}, [ 17 | AddWithGroup([]) 18 | ]), 19 | ] 20 | 21 | b_del: [ 22 | DelGroup([ 23 | DelWithGroup([]), 24 | DelGroup([]) 25 | ]), 26 | ] 27 | b_add: [ 28 | AddGroup({"tag": "h1"}, [ 29 | AddWithGroup([]), 30 | ]), 31 | ] 32 | -------------------------------------------------------------------------------- /edit-server/src/db/types.rs: -------------------------------------------------------------------------------- 1 | #[derive(Queryable, Debug)] 2 | pub struct Post { 3 | pub id: String, 4 | pub body: String, 5 | } 6 | 7 | use super::schema::posts; 8 | 9 | #[derive(Insertable)] 10 | #[table_name = "posts"] 11 | pub struct NewPost<'a> { 12 | pub id: &'a str, 13 | pub body: &'a str, 14 | } 15 | 16 | #[derive(Queryable, Debug, Serialize, Deserialize)] 17 | pub struct Log { 18 | pub rowid: i32, 19 | pub source: String, 20 | pub body: String, 21 | } 22 | 23 | use super::schema::logs; 24 | 25 | #[derive(Insertable)] 26 | #[table_name = "logs"] 27 | pub struct NewLog<'a> { 28 | pub source: &'a str, 29 | pub body: &'a str, 30 | } 31 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "build-tools", 4 | "oatie", 5 | "edit-common", 6 | "edit-server", 7 | "edit-client", 8 | ] 9 | 10 | [profile.dev] 11 | debug = true 12 | 13 | [profile.release] 14 | debug = true 15 | 16 | [patch.crates-io] 17 | wasm-bindgen = { git = "http://github.com/tcr/wasm-bindgen", rev = "90193ea" } 18 | wasm-bindgen-cli-support = { git = "http://github.com/tcr/wasm-bindgen", rev = "90193ea" } 19 | wasm-bindgen-shared = { git = "http://github.com/tcr/wasm-bindgen", rev = "90193ea" } 20 | web-sys = { git = "http://github.com/tcr/wasm-bindgen", rev = "90193ea" } 21 | js-sys = { git = "http://github.com/tcr/wasm-bindgen", rev = "90193ea" } 22 | -------------------------------------------------------------------------------- /edit-common/tests/transform/18: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("$") 5 | ]) 6 | ] 7 | 8 | a_del: [ 9 | DelGroup([ 10 | DelSkip(1) 11 | ]) 12 | ] 13 | a_add: [ 14 | AddGroup({"tag": "h2"}, [ 15 | AddGroup({"tag": "caret", "client": "a"}, []) 16 | ]), 17 | AddGroup({"tag": "bullet"}, [ 18 | AddGroup({"tag": "p"}, [ 19 | AddSkip(1) 20 | ]) 21 | ]) 22 | ] 23 | 24 | b_del: [ 25 | DelGroup([ 26 | DelSkip(1) 27 | ]) 28 | ] 29 | b_add: [ 30 | AddGroup({"tag": "bullet"}, [ 31 | AddGroup({"tag": "h1"}, [ 32 | AddSkip(1), 33 | ]) 34 | ]) 35 | ] 36 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-60: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("$") 5 | ]) 6 | ] 7 | 8 | a_del: [ 9 | DelGroup([ 10 | DelSkip(1) 11 | ]) 12 | ] 13 | a_add: [ 14 | AddGroup({"tag": "h2"}, [ 15 | AddGroup({"tag": "caret", "client": "a"}, []) 16 | ]), 17 | AddGroup({"tag": "bullet"}, [ 18 | AddGroup({"tag": "p"}, [ 19 | AddSkip(1) 20 | ]) 21 | ]) 22 | ] 23 | 24 | b_del: [ 25 | DelGroup([ 26 | DelSkip(1) 27 | ]) 28 | ] 29 | b_add: [ 30 | AddGroup({"tag": "bullet"}, [ 31 | AddGroup({"tag": "h1"}, [ 32 | AddSkip(1), 33 | ]) 34 | ]) 35 | ] 36 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-53: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars("12345") 5 | ]), 6 | DocGroup({"tag": "h3"}, [ 7 | DocChars("$") 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelWithGroup([ 13 | DelSkip(5) 14 | ]), 15 | DelWithGroup([ 16 | DelSkip(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddWithGroup([ 21 | AddSkip(5) 22 | ]), 23 | AddWithGroup([ 24 | AddChars("-"), 25 | AddSkip(1), 26 | ]), 27 | ] 28 | 29 | b_del: [ 30 | DelGroup([ 31 | DelSkip(5) 32 | ]), 33 | DelGroup([ 34 | DelChars(1), 35 | ]) 36 | ] 37 | b_add: [ 38 | AddGroup({"tag": "h3"}, [ 39 | AddSkip(5), 40 | ]) 41 | ] 42 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-51: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars("12345") 5 | ]), 6 | DocGroup({"tag": "h3"}, [ 7 | DocChars("$") 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(5) 14 | ]), 15 | DelWithGroup([ 16 | DelSkip(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h3"}, [ 21 | AddSkip(5) 22 | ]), 23 | AddWithGroup([ 24 | AddChars("-"), 25 | AddSkip(1), 26 | ]), 27 | ] 28 | 29 | b_del: [ 30 | DelGroup([ 31 | DelSkip(5) 32 | ]), 33 | DelGroup([ 34 | DelChars(1), 35 | ]) 36 | ] 37 | b_add: [ 38 | AddGroup({"tag": "h3"}, [ 39 | AddSkip(5), 40 | ]) 41 | ] 42 | -------------------------------------------------------------------------------- /edit-server/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(extern_in_paths, nll, plugin)] 2 | #![allow(proc_macro_derive_resolution_fallback)] 3 | 4 | #[macro_use] 5 | extern crate diesel; 6 | #[macro_use] 7 | extern crate failure; 8 | #[macro_use] 9 | extern crate lazy_static; 10 | #[macro_use] 11 | extern crate maplit; 12 | #[macro_use] 13 | extern crate oatie; 14 | #[macro_use] 15 | extern crate serde_derive; 16 | #[macro_use] 17 | extern crate serde_json; 18 | #[macro_use] 19 | extern crate taken; 20 | #[macro_use] 21 | extern crate rouille; 22 | #[macro_use] 23 | extern crate juniper; 24 | 25 | #[macro_use] 26 | pub mod log; 27 | 28 | // Macros can only be used after they are defined 29 | pub mod carets; 30 | pub mod db; 31 | pub mod graphql; 32 | pub mod state; 33 | pub mod sync; 34 | -------------------------------------------------------------------------------- /edit-common/tests/transform/279: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("a5"), 6 | DocGroup({"tag": "caret", "client": "e"}, []) 7 | ]) 8 | ]), 9 | DocGroup({"tag": "pre"}, [ 10 | DocChars("1") 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelWithGroup([ 16 | DelGroup([ 17 | DelSkip(2), 18 | DelWithGroup([]) 19 | ]) 20 | ]), 21 | ] 22 | a_add: [ 23 | AddWithGroup([ 24 | AddGroup({"tag": "p"}, [ 25 | AddSkip(3), 26 | ]) 27 | ]), 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelWithGroup([ 33 | DelChars(2) 34 | ]) 35 | ]) 36 | ] 37 | b_add: [ 38 | ] 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # edit-text 2 | 3 | ![Preview Image](https://user-images.githubusercontent.com/80639/42796912-9f2ae852-895a-11e8-9aae-9dede91296bf.png) 4 | 5 | edit-text is a collaborative text editor with Markdown import and export. Both the server and client are written in Rust, and its frontend is cross-compiled WebAssembly and TypeScript. 6 | 7 | [**✏️ Use edit-text online**](http://sandbox.edit.io/) in the [edit.io](http://edit.io) sandbox. 8 | 9 | [**📚 Read "Getting Started" instructions**](http://timryan.org/edit-text/getting-started.html) in the [edit-text documentation.](http://tcr.github.io/edit-text/) 10 | 11 | **Or clone this repo and run:** `./tools frontend-build && ./tools server --open` 12 | 13 | This is alpha-quality software. 14 | 15 | ## License 16 | 17 | Apache-2.0 18 | -------------------------------------------------------------------------------- /edit-common/tests/transform/80: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("1") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("$") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(1) 14 | ]), 15 | ] 16 | a_add: [ 17 | AddGroup({"tag": "p"}, [ 18 | AddSkip(1) 19 | ]), 20 | AddWithGroup([ 21 | AddChars("@") 22 | ]) 23 | ] 24 | 25 | b_del: [ 26 | DelGroup([ 27 | DelSkip(1) 28 | ]), 29 | DelGroup([ 30 | DelSkip(1) 31 | ]) 32 | ] 33 | b_add: [ 34 | AddGroup({"tag": "bullet"}, [ 35 | AddGroup({"tag": "h1"}, [ 36 | AddSkip(1) 37 | ]) 38 | ]), 39 | AddGroup({"tag": "h2"}, [ 40 | AddSkip(1) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-56: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "p"}, [ 4 | DocChars("1") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("1"), 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(1) 14 | ]), 15 | DelGroup([ 16 | DelSkip(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "p"}, [ 21 | AddSkip(1), 22 | AddGroup({"client": "e", "tag": "caret"}, []), 23 | AddSkip(1), 24 | ]), 25 | ] 26 | 27 | b_del: [ 28 | DelWithGroup([ 29 | DelSkip(1) 30 | ]), 31 | DelGroup([ 32 | DelSkip(1), 33 | ]) 34 | ] 35 | b_add: [ 36 | AddWithGroup([ 37 | AddSkip(1) 38 | ]), 39 | AddGroup({"tag": "p"}, [ 40 | AddSkip(1), 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/28: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "p"}, [ 5 | DocChars("f"), 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("1y3YlRworat's up with you?") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelWithGroup([ 15 | DelGroup([ 16 | DelSkip(1), 17 | ]), 18 | DelGroup([ 19 | DelSkip(26) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "p"}, [ 26 | AddSkip(27), 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([ 34 | DelChars(1), 35 | ]), 36 | DelWithGroup([]) 37 | ]) 38 | ] 39 | b_add: [ 40 | ] 41 | -------------------------------------------------------------------------------- /edit-common/tests/transform/94: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "p"}, [ 4 | DocChars("1"), 5 | ]), 6 | DocGroup({"tag": "h1"}, [ 7 | DocChars("$") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(1), 14 | ]), 15 | ] 16 | a_add: [ 17 | AddGroup({"tag": "bullet"}, [ 18 | AddGroup({"tag": "h3"}, [ 19 | AddSkip(1), 20 | ]) 21 | ]), 22 | AddWithGroup([ 23 | AddGroup({"tag": "caret", "client": "a"}, []) 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelGroup([ 29 | DelSkip(1), 30 | ]), 31 | DelGroup([ 32 | DelSkip(1) 33 | ]) 34 | ] 35 | b_add: [ 36 | AddGroup({"tag": "bullet"}, [ 37 | AddGroup({"tag": "h3"}, [ 38 | AddSkip(2) 39 | ]) 40 | ]) 41 | ] 42 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-41: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "p"}, [ 5 | DocChars(" 17 AshRD XmrskfCG62xajello worldm") 6 | ]) 7 | ]), 8 | ] 9 | 10 | a_del: [ 11 | DelWithGroup([ 12 | DelWithGroup([ 13 | DelSkip(35), 14 | ]) 15 | ]), 16 | ] 17 | a_add: [ 18 | AddWithGroup([ 19 | AddWithGroup([ 20 | AddSkip(35), 21 | AddChars("M"), 22 | ]) 23 | ]), 24 | ] 25 | 26 | b_del: [ 27 | DelWithGroup([ 28 | DelGroup([ 29 | DelSkip(35) 30 | ]) 31 | ]) 32 | ] 33 | b_add: [ 34 | AddWithGroup([ 35 | AddGroup({"tag": "p"}, []), 36 | AddGroup({"tag": "p"}, [ 37 | AddSkip(35) 38 | ]) 39 | ]) 40 | ] 41 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-57: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("12") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("1"), 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(2) 14 | ]), 15 | DelWithGroup([ 16 | DelChars(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h3"}, [ 21 | AddGroup({"tag": "caret", "client": "d"}, []), 22 | ]), 23 | AddGroup({"tag": "h3"}, [ 24 | AddSkip(2), 25 | ]), 26 | AddWithGroup([ 27 | AddChars("6"), 28 | ]), 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelSkip(2), 34 | ]), 35 | DelGroup([ 36 | DelSkip(1) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "h2"}, [ 41 | AddSkip(3) 42 | ]) 43 | ] 44 | -------------------------------------------------------------------------------- /edit-frontend/src/index.js: -------------------------------------------------------------------------------- 1 | // Global CSS 2 | import '../styles/edit.scss'; 3 | // import {booted} from './bindgen/edit_client_bg.wasm'; 4 | 5 | import Raven from 'raven-js'; 6 | 7 | // Workaround for webpack 8 | export function getWasmModule() { 9 | return import('./bindgen/edit_client'); 10 | } 11 | 12 | Raven.config('https://c221eba12d7b4e279b01764577063af1@sentry.io/1227661').install(); 13 | 14 | // Launch the application. 15 | import * as app from './app/app'; 16 | import DEBUG from './debug'; 17 | 18 | DEBUG.measureTime('wasm-request'); 19 | getWasmModule() 20 | .then(Module => { 21 | DEBUG.measureTime('wasm-ready'); 22 | }); 23 | 24 | Raven.context(() => { 25 | if (window.location.pathname.match(/^\/\$\/react/)) { 26 | app.start_standalone(); 27 | } else { 28 | app.start(); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /edit-client/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(nll)] 2 | 3 | #[macro_use] 4 | extern crate failure; 5 | #[macro_use] 6 | extern crate maplit; 7 | #[macro_use] 8 | extern crate oatie; 9 | #[macro_use] 10 | extern crate serde_derive; 11 | #[allow(unused)] 12 | #[macro_use] 13 | extern crate lazy_static; 14 | 15 | // Macros has to come first 16 | #[macro_use] 17 | pub mod log; 18 | 19 | #[cfg(target_arch = "wasm32")] 20 | #[macro_use] 21 | pub mod wasm; 22 | 23 | pub mod client; 24 | pub mod monkey; 25 | pub mod random; 26 | pub mod walkers; 27 | 28 | #[cfg(not(target_arch = "wasm32"))] 29 | pub mod proxy; 30 | 31 | pub use self::client::*; 32 | pub use self::random::*; 33 | 34 | // Use `wee_alloc` as the global allocator. 35 | #[cfg(all(target_arch = "wasm32", feature = "use_wee_alloc"))] 36 | #[global_allocator] 37 | static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 38 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-54: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("1") 5 | ]), 6 | DocGroup({"tag": "h2"}, [ 7 | DocChars("2"), 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelWithGroup([ 13 | DelSkip(1) 14 | ]), 15 | DelGroup([ 16 | DelSkip(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddWithGroup([ 21 | AddSkip(1) 22 | ]), 23 | AddGroup({"tag": "p"}, [ 24 | AddSkip(1), 25 | ]), 26 | ] 27 | 28 | b_del: [ 29 | DelGroup([ 30 | DelSkip(1) 31 | ]), 32 | DelGroup([ 33 | DelSkip(1) 34 | ]) 35 | ] 36 | b_add: [ 37 | AddGroup({"tag": "bullet"}, [ 38 | AddGroup({"tag": "h2"}, [ 39 | AddSkip(1), 40 | AddGroup({"client": "g", "tag": "caret"}, []), 41 | AddSkip(1) 42 | ]) 43 | ]) 44 | ] 45 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-55: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars("1") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("1"), 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(1), 14 | ]), 15 | DelGroup([ 16 | DelSkip(1), 17 | ]), 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h3"}, [ 22 | AddSkip(1), 23 | AddGroup({"tag": "caret", "client": "c"}, []), 24 | AddSkip(1), 25 | ]) 26 | ]), 27 | ] 28 | 29 | b_del: [ 30 | DelWithGroup([ 31 | DelSkip(1), 32 | ]), 33 | DelGroup([ 34 | DelSkip(1), 35 | ]) 36 | ] 37 | b_add: [ 38 | AddWithGroup([ 39 | AddSkip(1), 40 | ]), 41 | AddGroup({"tag": "p"}, [ 42 | AddSkip(1), 43 | ]) 44 | ] 45 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-42: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("1234") 5 | ]), 6 | DocGroup({"tag": "bullet"}, [ 7 | DocGroup({"tag": "h1"}, [ 8 | DocChars("1234") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelSkip(1), 15 | DelGroup([ 16 | DelGroup([ 17 | DelSkip(4) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "bullet"}, [ 23 | AddSkip(1), 24 | ]), 25 | AddGroup({"tag": "h1"}, [ 26 | AddSkip(4), 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelSkip(1), 32 | DelWithGroup([ 33 | DelWithGroup([ 34 | DelChars(1) 35 | ]) 36 | ]) 37 | ] 38 | b_add: [ 39 | AddSkip(1), 40 | AddWithGroup([ 41 | AddWithGroup([ 42 | AddChars("$"), 43 | ]) 44 | ]) 45 | ] 46 | -------------------------------------------------------------------------------- /edit-common/tests/transform/465: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []) 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocGroup({"client": "a", "tag": "caret"}, []), 9 | DocChars(" ") 10 | ]) 11 | ]), 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelWithGroup([ 17 | DelWithGroup([]) 18 | ]), 19 | DelWithGroup([ 20 | DelGroup([]) 21 | ]) 22 | ]) 23 | ] 24 | a_add: [ 25 | AddWithGroup([ 26 | AddGroup({"client": "a", "tag": "caret"}, []), 27 | AddWithGroup([]) 28 | ]), 29 | AddWithGroup([ 30 | AddSkip(1) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelWithGroup([ 36 | DelWithGroup([]) 37 | ]) 38 | ] 39 | b_add: [ 40 | ] 41 | -------------------------------------------------------------------------------- /edit-frontend/templates/react.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 23 | 24 | 25 | 26 | React Demo 27 | 28 | 29 | 30 |
31 |
32 | 33 | 34 | 37 | 38 | -------------------------------------------------------------------------------- /edit-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Tim Ryan "] 3 | name = "edit-common" 4 | version = "0.1.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | colored = "1.6.0" 9 | # dotenv = "0.11.0" 10 | env_logger = "0.4.3" 11 | failure = "0.1.1" 12 | htmlescape = "0.3.1" 13 | lazy_static = "1.0.0" 14 | maplit = "1.0.0" 15 | pulldown-cmark = "0.1.2" 16 | pulldown-cmark-to-cmark = "1.1.0" 17 | rand = "0.4" 18 | regex = "1" 19 | ron = "0.4" 20 | serde = "1.0.27" 21 | serde_derive = "1.0.27" 22 | serde_json = "1.0.6" 23 | take_mut = "0.2.0" 24 | taken = "0.1.1" 25 | wasm-bindgen = { version = "0.2", features = ["nightly"] } 26 | wasm-typescript-definition = "0.1" 27 | 28 | [dependencies.include-dir-macro] 29 | git = "https://github.com/jcdyer/include-dir-macro" 30 | 31 | [dependencies.oatie] 32 | path = "../oatie" 33 | 34 | [target."cfg(not(target_arch=\"wasm32\"))".dependencies] 35 | ws = "0.7.3" 36 | -------------------------------------------------------------------------------- /oatie/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Tim Cameron Ryan "] 3 | description = "Operational transform library." 4 | homepage = "https://github.com/tcr/edit-text" 5 | license = "MIT OR Apache-2.0" 6 | name = "oatie" 7 | repository = "https://github.com/tcr/edit-text" 8 | version = "0.3.0" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | either = "1.4.0" 13 | failure = "0.1.1" 14 | log = "0.3.1" 15 | maplit = "1.0.0" 16 | regex = "0.2.10" 17 | ron = "0.4" 18 | serde = "^1.0.82" 19 | serde_derive = "^1.0.82" 20 | serde_json = "1.0" 21 | term-painter = "0.2.2" 22 | yansi = "0.3.4" 23 | rental = "*" 24 | wasm-bindgen = "0.2" 25 | smallvec = "*" 26 | wasm-typescript-definition = "0.1.3" 27 | enumset = "0.3" 28 | 29 | backtrace = "=0.3.9" # 0.3.11 is buggy in wasm 30 | 31 | [dev-dependencies] 32 | env_logger = "0.3" 33 | 34 | [lib] 35 | name = "oatie" 36 | 37 | [features] 38 | validate_bytecode = [] 39 | -------------------------------------------------------------------------------- /edit-frontend/styles/multi.scss: -------------------------------------------------------------------------------- 1 | 2 | // Multi client 3 | 4 | #parent { 5 | background: #eee; 6 | } 7 | 8 | #client { 9 | background: white; 10 | cursor: text; 11 | } 12 | 13 | body#multi { 14 | width: 100%; 15 | height: 100%; 16 | padding: 0 !important; 17 | 18 | display: flex; 19 | flex-direction: column; 20 | 21 | iframe { 22 | border: none; 23 | width: 100%; 24 | height: 100%; 25 | display: block; 26 | } 27 | 28 | #clients, #clients tbody, #clients tr, #clients td { 29 | display: block; 30 | } 31 | 32 | #clients, #clients tbody { 33 | display: flex; 34 | flex-direction: column; 35 | flex: 1; 36 | } 37 | 38 | #clients tr { 39 | flex: 1; 40 | display: flex; 41 | flex-direction: row; 42 | } 43 | 44 | #clients td { 45 | border: 2px solid black; 46 | box-sizing: border-box; 47 | flex: 1; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docs/src/dokku.md: -------------------------------------------------------------------------------- 1 | # Deploying to Dokku 2 | 3 | [macOS Instructions] To deploy to a Dokku instance, you'll have to install a linux cross-compiler. This will cross-compile the Linux binary locally and then package it in a Docker container for distribution. 4 | 5 | First, to install the cross compiler: 6 | 7 | ``` 8 | brew install qinyao-he/homebrew-gcc_cross_compilers/x64-elf-gcc 9 | ``` 10 | 11 | Then add a new Rust target: 12 | 13 | ``` 14 | rustup target add x86_64-unknown-linux-gnu 15 | ``` 16 | 17 | You can deploy edit-text to a Dokku server using `./tools deploy`. 18 | 19 | ``` 20 | ./tools deploy 21 | ``` 22 | 23 | * This first cross-compiles the edit-server binary using a local Docker image. 24 | * It then uploads the binary using the `dokku tar:in` command on a remote server (not the Git endpoint). 25 | * You can configure the dokku URL using the `EDIT_DEPLOY_URL` environment variable. 26 | * You can configure the dokku application name using the `EDIT_DOKKU_NAME` environment variable. 27 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-30: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "h3"}, [ 3 | DocChars("ka6jj 654fi 4835t V J piPgC4 5y60D 7I7QU6"), 4 | DocGroup({"client": "right", "tag": "caret"}, []), 5 | DocChars("gDo n2ox0bP WF 2n6X i"), 6 | DocGroup({"tag": "caret", "client": "left"}, []), 7 | DocChars("2Nr"), 8 | DocGroup({"client": "middle", "tag": "caret"}, []), 9 | DocChars("8bG8 by c mkvwSYkQtNY4o yLat's up with you?") 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelWithGroup([ 15 | DelSkip(65), DelChars(1) 16 | ]) 17 | ] 18 | a_add: [ 19 | AddGroup({"tag": "bullet"}, [ 20 | AddWithGroup([ 21 | AddSkip(65) 22 | ]) 23 | ]) 24 | ] 25 | 26 | b_del: [ 27 | DelGroup([ 28 | DelSkip(41), DelChars(1), DelSkip(74) 29 | ]) 30 | ] 31 | b_add: [ 32 | AddGroup({"tag": "h3"}, [ 33 | AddSkip(41) 34 | ]), 35 | AddGroup({"tag": "p"}, [ 36 | AddSkip(74) 37 | ]) 38 | ] 39 | -------------------------------------------------------------------------------- /edit-common/tests/transform/60: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars("1"), 5 | ]), 6 | DocGroup({"tag": "h1"}, [ 7 | DocChars("12") 8 | ]), 9 | ] 10 | 11 | a_del: [ 12 | DelWithGroup([ 13 | DelSkip(1), 14 | ]), 15 | DelGroup([ 16 | DelChars(1), 17 | DelSkip(1) 18 | ]), 19 | ] 20 | a_add: [ 21 | AddGroup({"tag": "bullet"}, [ 22 | AddWithGroup([ 23 | AddSkip(1), 24 | ]) 25 | ]), 26 | AddGroup({"tag": "pre"}, [ 27 | AddSkip(1), 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelSkip(1), 34 | ]), 35 | DelGroup([ 36 | DelSkip(2), 37 | ]), 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h3"}, [ 42 | AddSkip(2), 43 | ]), 44 | AddGroup({"tag": "p"}, [ 45 | AddGroup({"client": "b", "tag": "caret"}, []), 46 | AddSkip(1) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-frontend/src/app/route.ts: -------------------------------------------------------------------------------- 1 | export function pageId(): string { 2 | return window.location.pathname.match(/^\/?([^\/]+)/)![1] || ''; 3 | } 4 | 5 | export function clientProxyUrl(): string { 6 | return '' + 7 | (window.location.protocol.match(/^https/) ? 'wss://' : 'ws://') + 8 | window.location.host.replace(/\:\d+/, ':8002') + 9 | '/' + 10 | pageId(); 11 | } 12 | 13 | export function serverUrl(): string { 14 | return '' + 15 | (window.location.protocol.match(/^https/) ? 'wss://' : 'ws://') + 16 | (window.location.host.match(/localhost|0.0.0.0/) ? 17 | window.location.host.replace(/:\d+$|$/, ':8001') + '/$/ws/' + pageId() : 18 | window.location.host + '/$/ws/' + pageId()); 19 | } 20 | 21 | export function graphqlUrl(): string { 22 | return '' + 23 | window.location.protocol + '//' + 24 | (window.location.host.match(/localhost|0.0.0.0/) ? 25 | window.location.host.replace(/:\d+$|$/, ':8003') + '/graphql/' : 26 | window.location.host + '/$/graphql/'); 27 | } 28 | -------------------------------------------------------------------------------- /edit-common/tests/transform/81: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("jello worldD123"), 5 | ]), 6 | DocGroup({"tag": "bullet"}, [ 7 | DocGroup({"tag": "h1"}, [ 8 | DocChars("hat's up with you") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelSkip(15), 16 | ]), 17 | DelGroup([ 18 | DelWithGroup([ 19 | DelChars(1) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddGroup({"tag": "h1"}, [ 25 | AddSkip(15), 26 | ]), 27 | AddWithGroup([ 28 | AddChars(" "), 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelSkip(15), 35 | ]), 36 | DelWithGroup([ 37 | DelGroup([ 38 | DelSkip(17) 39 | ]) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "h1"}, [ 44 | AddSkip(15), 45 | ]), 46 | AddWithGroup([ 47 | AddGroup({"tag": "h2"}, [ 48 | AddSkip(17) 49 | ]) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-59: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("jello worldD123"), 5 | ]), 6 | DocGroup({"tag": "bullet"}, [ 7 | DocGroup({"tag": "h1"}, [ 8 | DocChars("hat's up with you") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelSkip(15), 16 | ]), 17 | DelGroup([ 18 | DelWithGroup([ 19 | DelChars(1) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddGroup({"tag": "h1"}, [ 25 | AddSkip(15), 26 | ]), 27 | AddWithGroup([ 28 | AddChars(" "), 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelSkip(15), 35 | ]), 36 | DelWithGroup([ 37 | DelGroup([ 38 | DelSkip(17) 39 | ]) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "h1"}, [ 44 | AddSkip(15), 45 | ]), 46 | AddWithGroup([ 47 | AddGroup({"tag": "h2"}, [ 48 | AddSkip(17) 49 | ]) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /docs/src/server-apis.md: -------------------------------------------------------------------------------- 1 | # Server APIs 2 | 3 | The server performs document synchronization. It is the "server" component that orchestrates simultaneous document modifications which happen on several Users. 4 | 5 | | Port | Path Mapping | Description 6 | |------|------|------------- 7 | | 8000 | / | HTML Server 8 | | 8002 | /$/ws | WebSocket 9 | | 8003 | /$/graphql | GraphQL 10 | 11 | HTML is served from `/`. Static versions of each page are available before scripting is fully downloaded. 12 | 13 | When the client-side script connects the WebSocket, the server recognizes it as a new synchronization client and reloads the content of the page. Editing is then enabled. Each edit made by the client is sent to the server as an operation, and the server computes and pushes push new deltas to the client. 14 | 15 | There is an additional API exposed as GraphQL for non-synchronization tasks. This exposes mutations like updating a page with Markdown, downloading and renaming pages, and other page-editing features.# Server APIs 16 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-17: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "h2"}, [ 3 | DocChars(" Cl43"), DocGroup({"tag": "caret", "client": "left"}, []), 4 | DocChars("K"), DocGroup({"client": "right", "tag": "caret"}, []), 5 | DocChars("e uJ r ") 6 | ]), 7 | DocGroup({"tag": "h3"}, [ 8 | DocChars(" 7GxDE c3 SdIHello world!is0y 7QNsLhat\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelSkip(4), DelChars(1), DelGroup([]) 15 | ]) 16 | ] 17 | a_add: [ 18 | AddWithGroup([ 19 | AddSkip(3), AddChars("H"), AddGroup({"tag": "caret", "client": "left"}, []), 20 | AddSkip(1) 21 | ]) 22 | ] 23 | 24 | b_del: [ 25 | DelWithGroup([ 26 | DelSkip(4), DelChars(1), DelWithGroup([]), 27 | DelSkip(1), DelGroup([]) 28 | ]) 29 | ] 30 | b_add: [ 31 | AddWithGroup([ 32 | AddSkip(4), AddChars("w"), AddGroup({"tag": "caret", "client": "right"}, []), 33 | AddWithGroup([]), 34 | AddSkip(1) 35 | ]) 36 | ] -------------------------------------------------------------------------------- /dist/deploy/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | } 3 | 4 | http { 5 | map $http_upgrade $connection_upgrade { 6 | default upgrade; 7 | '' close; 8 | } 9 | 10 | upstream websocket { 11 | server 127.0.0.1:8001; 12 | } 13 | 14 | server { 15 | gzip off; 16 | listen 80; 17 | 18 | location /$/ws/ { 19 | proxy_pass http://websocket; 20 | proxy_http_version 1.1; 21 | proxy_set_header Upgrade $http_upgrade; 22 | proxy_set_header Connection $connection_upgrade; 23 | } 24 | 25 | location /$/graphql/ { 26 | proxy_set_header X-Real-IP $remote_addr; 27 | proxy_set_header Host $http_host; 28 | proxy_pass http://127.0.0.1:8003/graphql/; 29 | } 30 | 31 | location / { 32 | proxy_set_header X-Real-IP $remote_addr; 33 | proxy_set_header Host $http_host; 34 | proxy_pass http://127.0.0.1:8000; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /oatie/tests/transform/caret-15: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "h1"}, [ 3 | DocGroup({"client": "left", "tag": "caret"}, []), 4 | DocGroup({"tag": "caret", "client": "right"}, []), 5 | DocChars("Hello world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelGroup([]), 15 | DelSkip(13) 16 | ]) 17 | ] 18 | a_add: [ 19 | AddGroup({"tag": "h1"}, [ 20 | AddChars("c c11j"), AddGroup({"tag": "caret", "client": "left"}, []), 21 | AddChars("820h"), AddSkip(13) 22 | ]) 23 | ] 24 | 25 | b_del: [ 26 | DelGroup([ 27 | DelWithGroup([]), 28 | DelGroup([]), 29 | DelSkip(12) 30 | ]), 31 | DelSkip(1) 32 | ] 33 | b_add: [ 34 | AddGroup({"tag": "h1"}, [ 35 | AddChars("fn7g017824"), AddWithGroup([]), 36 | AddChars("V "), AddSkip(12) 37 | ]), 38 | AddWithGroup([ 39 | AddGroup({"client": "right", "tag": "caret"}, []) 40 | ]) 41 | ] -------------------------------------------------------------------------------- /edit-common/tests/transform/98: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(1), DelSkip(6), DelChars(5) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h1"}, [ 22 | AddChars("1"), AddGroup({"tag": "caret", "client": "a"}, []), 23 | AddChars("v"), AddSkip(6), AddChars(" "), AddSkip(18) 24 | ]) 25 | ]) 26 | ] 27 | 28 | b_del: [ 29 | DelWithGroup([ 30 | DelSkip(11), DelChars(1) 31 | ]), 32 | DelWithGroup([]) 33 | ] 34 | b_add: [ 35 | AddGroup({"tag": "bullet"}, [ 36 | AddWithGroup([ 37 | AddChars(" i"), AddSkip(11), AddChars("x") 38 | ]) 39 | ]), 40 | AddWithGroup([ 41 | AddGroup({"client": "b", "tag": "caret"}, []) 42 | ]) 43 | ] 44 | -------------------------------------------------------------------------------- /edit-common/tests/transform/583: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []) 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("6B"), DocGroup({"tag": "caret", "client": "a"}, []), 9 | DocChars(" 6sN hIllo world!j 7W t\'s up with you?") 10 | ]) 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelWithGroup([ 17 | DelWithGroup([]) 18 | ]), 19 | DelWithGroup([ 20 | DelSkip(1), DelChars(1), DelGroup([]) 21 | ]) 22 | ]) 23 | ] 24 | a_add: [ 25 | AddWithGroup([ 26 | AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddWithGroup([]) 28 | ]), 29 | AddWithGroup([ 30 | AddSkip(1) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelWithGroup([ 36 | DelWithGroup([]) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddWithGroup([ 41 | AddWithGroup([ 42 | AddChars("I") 43 | ]) 44 | ]) 45 | ] 46 | -------------------------------------------------------------------------------- /docs/src/glossary.md: -------------------------------------------------------------------------------- 1 | # Glossary 2 | 3 | * *client* — A client can connect to a server and synchronize its document 4 | content. It sends client-side modifications (in the form of operations) to the 5 | server, and receives updated content (in the form of operations) from the server 6 | after any client submits an update. 7 | 8 | * *controller* — Receives UI-level event updates from the frontend 9 | and converts it into operations on the client document. 10 | 11 | * *cursor* — All positions in which a Text or Group element can be 12 | inserted into a document can be represented by a cursor object. 13 | 14 | * *frontend* — The editor UI. The current document is rendered 15 | as a component inside the frontend, and interactions with this component are 16 | forwarded to the controller. The frontend also manages the toolbar, 17 | notifications, and dialog boxes. 18 | 19 | * *server* — Serves HTTP content, a GraphQL endpoint for performing 20 | page-level commands, and a WebSocket endpoint for synchronizing document 21 | content. 22 | -------------------------------------------------------------------------------- /edit-common/tests/transform/248: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars("3H 0"), DocGroup({"tag": "caret", "client": "a"}, []), 7 | DocChars("lYmhat\'s up with you?") 8 | ]) 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelGroup([ 15 | DelWithGroup([]), 16 | DelSkip(1), DelChars(2), DelSkip(1), DelGroup([]), 17 | DelSkip(21) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddGroup({"tag": "p"}, [ 24 | AddWithGroup([]), 25 | AddSkip(1), AddGroup({"client": "a", "tag": "caret"}, []), 26 | AddChars(" "), AddSkip(22) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([ 34 | DelGroup([]) 35 | ]) 36 | ]) 37 | ] 38 | b_add: [ 39 | AddWithGroup([ 40 | AddChars(" "), AddGroup({"client": "b", "tag": "caret"}, []) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/115: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("3 Q"), DocGroup({"tag": "caret", "client": "a"}, []), 7 | DocChars("mHello worlqWhat\'s up with you?") 8 | ]) 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelGroup([ 15 | DelWithGroup([]), 16 | DelSkip(2), DelChars(2), DelGroup([]), 17 | DelSkip(31) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddGroup({"tag": "h3"}, [ 24 | AddGroup({"client": "a", "tag": "caret"}, []), 25 | AddWithGroup([]), 26 | AddSkip(2), AddChars("s"), AddSkip(31) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([ 34 | DelGroup([]), 35 | DelChars(1) 36 | ]) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddWithGroup([ 41 | AddGroup({"client": "b", "tag": "caret"}, []) 42 | ]) 43 | ] 44 | -------------------------------------------------------------------------------- /edit-common/tests/transform/12: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(9), DelChars(3) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "p"}, [ 21 | AddChars(" "), AddSkip(9), AddChars("JS ") 22 | ]), 23 | AddGroup({"tag": "bullet"}, [ 24 | AddGroup({"tag": "p"}, [ 25 | AddChars(" "), AddGroup({"tag": "caret", "client": "a"}, []), 26 | AddSkip(18) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelSkip(9), DelChars(3) 34 | ]), 35 | DelGroup([ 36 | DelChars(1), DelSkip(18) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h1"}, [ 42 | AddChars("o"), AddGroup({"client": "b", "tag": "caret"}, []), 43 | AddSkip(27) 44 | ]) 45 | ]) 46 | ] 47 | -------------------------------------------------------------------------------- /edit-common/tests/transform/517: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("i l mS4VE2"), DocGroup({"client": "c", "tag": "caret"}, []) 6 | ]), 7 | DocGroup({"tag": "h2"}, [ 8 | DocChars(" "), DocGroup({"tag": "caret", "client": "a"}, []), 9 | DocChars(" "), DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars(" 7 5QQ 7!0 hat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelSkip(10), DelWithGroup([]) 19 | ]), 20 | DelWithGroup([ 21 | DelChars(1) 22 | ]) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddWithGroup([ 27 | AddSkip(10), AddWithGroup([]) 28 | ]), 29 | AddWithGroup([]) 30 | ] 31 | 32 | b_del: [ 33 | DelWithGroup([ 34 | DelWithGroup([ 35 | DelSkip(10) 36 | ]) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddWithGroup([ 41 | AddWithGroup([ 42 | AddSkip(10) 43 | ]) 44 | ]) 45 | ] 46 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-37: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "p"}, [ 3 | DocChars("12345") 4 | ]), 5 | DocGroup({"tag": "p"}, [ 6 | DocGroup({"client": "e", "tag": "caret"}, []), 7 | DocChars("5") 8 | ]), 9 | DocGroup({"tag": "p"}, [ 10 | DocChars("u"), 11 | DocGroup({"client": "j", "tag": "caret"}, []), 12 | DocChars("A") 13 | ]), 14 | ] 15 | 16 | a_del: [ 17 | DelGroup([ 18 | DelSkip(5), 19 | ]), 20 | DelGroup([ 21 | DelGroup([]), 22 | DelSkip(1) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "p"}, [ 28 | AddSkip(5), 29 | AddChars("123") 30 | ]) 31 | ]), 32 | AddGroup({"tag": "p"}, [ 33 | AddSkip(1) 34 | ]) 35 | ] 36 | 37 | b_del: [ 38 | DelSkip(1), 39 | DelGroup([ 40 | DelSkip(2) 41 | ]), 42 | DelGroup([ 43 | DelChars(1), 44 | DelSkip(2) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddSkip(1), 49 | AddGroup({"tag": "p"}, [ 50 | AddSkip(4) 51 | ]) 52 | ] -------------------------------------------------------------------------------- /oatie/tests/transform/caret-40: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("3edY1V1"), 5 | ]), 6 | DocGroup({"tag": "h2"}, [ 7 | DocChars("PNo world!") 8 | ]), 9 | DocGroup({"tag": "p"}, [ 10 | DocChars(" What\'s up with you?") 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelSkip(7), 17 | ]), 18 | DelGroup([ 19 | DelSkip(10) 20 | ]), 21 | DelGroup([ 22 | DelSkip(20) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "h2"}, [ 28 | AddSkip(17), 29 | ]) 30 | ]), 31 | AddGroup({"tag": "p"}, [ 32 | AddSkip(20) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelSkip(7), 39 | ]), 40 | DelGroup([ 41 | DelSkip(10) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "h1"}, [ 46 | AddSkip(1), 47 | AddChars(" j") 48 | ]), 49 | AddGroup({"tag": "bullet"}, [ 50 | AddGroup({"tag": "p"}, [ 51 | AddSkip(16) 52 | ]) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-39: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("ja"), DocGroup({"client": "b", "tag": "caret"}, []), 5 | DocChars(" ") 6 | ]), 7 | DocGroup({"tag": "pre"}, [ 8 | DocChars("vj5 B"), DocGroup({"client": "a", "tag": "caret"}, []), 9 | DocChars("4k ello w5h3 8What\'s up with you?") 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelWithGroup([ 15 | DelSkip(2), DelWithGroup([]), 16 | DelSkip(1) 17 | ]), 18 | DelWithGroup([ 19 | DelSkip(5), DelGroup([]) 20 | ]) 21 | ] 22 | a_add: [ 23 | AddWithGroup([ 24 | AddSkip(2), AddWithGroup([]), 25 | AddSkip(1) 26 | ]), 27 | AddGroup({"tag": "bullet"}, [ 28 | AddWithGroup([ 29 | AddSkip(5), AddGroup({"tag": "caret", "client": "a"}, []), 30 | AddChars("o") 31 | ]) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelSkip(1), DelChars(1), DelSkip(2) 38 | ]) 39 | ] 40 | b_add: [ 41 | AddGroup({"tag": "p"}, [ 42 | AddSkip(1), AddChars(" "), AddSkip(2) 43 | ]) 44 | ] 45 | -------------------------------------------------------------------------------- /edit-common/tests/transform/135: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("aejlo wor"), DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("!What\'s up with you?") 6 | ]) 7 | ] 8 | 9 | a_del: [ 10 | DelGroup([ 11 | DelSkip(1), DelChars(5), DelSkip(2), DelChars(1), DelGroup([]), 12 | DelSkip(20) 13 | ]) 14 | ] 15 | a_add: [ 16 | AddGroup({"tag": "h1"}, [ 17 | AddChars("l"), AddGroup({"tag": "caret", "client": "a"}, []), 18 | AddSkip(1), AddChars(" "), AddSkip(2) 19 | ]), 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h3"}, [ 22 | AddSkip(20) 23 | ]) 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelGroup([ 29 | DelChars(1), DelSkip(1), DelChars(1), DelSkip(27) 30 | ]) 31 | ] 32 | b_add: [ 33 | AddGroup({"tag": "bullet"}, [ 34 | AddGroup({"tag": "pre"}, [ 35 | AddChars("A"), AddSkip(1) 36 | ]), 37 | AddGroup({"tag": "p"}, [ 38 | AddGroup({"client": "b", "tag": "caret"}, []), 39 | AddSkip(27) 40 | ]) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/225: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(2), DelSkip(1), DelChars(1), DelSkip(8) 14 | ]), 15 | DelWithGroup([ 16 | DelChars(1) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h1"}, [ 22 | AddGroup({"tag": "caret", "client": "b"}, []), 23 | AddChars("C"), AddSkip(1), AddChars("h"), AddSkip(8), AddChars(" ") 24 | ]) 25 | ]), 26 | AddWithGroup([ 27 | AddGroup({"client": "a", "tag": "caret"}, []) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelSkip(11), DelChars(1) 34 | ]), 35 | DelGroup([ 36 | DelSkip(19) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h1"}, [ 42 | AddChars(" H"), AddGroup({"client": "c", "tag": "caret"}, []), 43 | AddSkip(30) 44 | ]) 45 | ]) 46 | ] 47 | -------------------------------------------------------------------------------- /docs/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [edit-text](./intro.md) 4 | - [Getting Started](./getting-started.md) 5 | - [Development](./development.md) 6 | - [System Overview](./intro-system.md) 7 | - [Build with ./tools](./intro-x.md) 8 | - [Tests](./intro-testing.md) 9 | - [Writing an integration test](./writing-an-integration-test.md) 10 | - [Editor Basics](./editor-basics.md) 11 | - [Documents](./working-with-documents.md) 12 | - [Operations](./working-with-operations.md) 13 | - [Operational Transform](./rtf-ot.md) 14 | - [Rich Text](./rtf.md) 15 | - [Markdown](./markdown.md) 16 | - [Carets](./diary-carets.md) 17 | - [Server](./server.md) 18 | - [HTTP APIs](./server-apis.md) 19 | - [Storage](./storage.md) 20 | - [Frontend](./frontend.md) 21 | - [Editor Component](./editor-component.md) 22 | - [WebAssembly Interface](./webassembly-interface.md) 23 | - [Deploying](./deploying.md) 24 | - [Running as a binary](./edit-server-binary.md) 25 | - [Dokku](./dokku.md) 26 | - [Hosted Sandbox](#) 27 | - [npm module](#) 28 | - [Appendix](./appendix.md) 29 | - [Delall Hack](./diary-delall.md) 30 | - [Glossary](./glossary.md) 31 | -------------------------------------------------------------------------------- /docs/src/intro-testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | There are two types of tests, integration tests and unit tests. 4 | 5 | ## Unit Tests 6 | 7 | To run unit tests, run `./tools test unit`. 8 | 9 | ## Integration Tests 10 | 11 | Integration tests use a "headless" browser to run 12 | 13 | Run `./tools test integration` to run the test suite with integrated tests. Run `./tools test all` to run unit tests and integration tests. 14 | 15 | This runs simulated tests using headless browsers running concurrent editing operation. You should install a WebDriver implementation such as `geckodriver`: 16 | 17 | * macOS: `brew install geckodriver` 18 | * Ubuntu: `npm install -g geckodriver` 19 | * Windows: `choco install selenium-gecko-driver` 20 | 21 | 47 | -------------------------------------------------------------------------------- /edit-common/tests/transform/15: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(11), DelChars(1) 14 | ]), 15 | DelGroup([ 16 | DelSkip(19) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h1"}, [ 21 | AddSkip(11), AddChars("C") 22 | ]), 23 | AddGroup({"tag": "bullet"}, [ 24 | AddGroup({"tag": "p"}, [ 25 | AddGroup({"tag": "caret", "client": "a"}, []), 26 | AddChars("7") 27 | ]) 28 | ]), 29 | AddGroup({"tag": "p"}, [ 30 | AddChars("or"), AddSkip(19) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelGroup([ 36 | DelSkip(6), DelChars(6) 37 | ]), 38 | DelGroup([ 39 | DelSkip(19) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "bullet"}, [ 44 | AddGroup({"tag": "h1"}, [ 45 | AddSkip(6), AddChars("ta"), AddGroup({"client": "b", "tag": "caret"}, []), 46 | AddSkip(19) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-common/tests/transform/443: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []) 6 | ]), 7 | DocGroup({"tag": "h2"}, [ 8 | DocChars("1a "), DocGroup({"tag": "caret", "client": "a"}, []), 9 | DocChars("2OHello world!What\'s up with you?") 10 | ]) 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelWithGroup([ 17 | DelWithGroup([]) 18 | ]), 19 | DelWithGroup([ 20 | DelSkip(3), DelGroup([]), 21 | DelChars(1) 22 | ]) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddWithGroup([ 27 | AddWithGroup([]) 28 | ]), 29 | AddWithGroup([ 30 | AddSkip(3), AddGroup({"client": "a", "tag": "caret"}, []) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelWithGroup([ 36 | DelWithGroup([ 37 | DelGroup([]) 38 | ]) 39 | ]) 40 | ] 41 | b_add: [ 42 | AddWithGroup([ 43 | AddWithGroup([ 44 | AddChars("Y"), AddGroup({"client": "b", "tag": "caret"}, []) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edit-frontend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "awesome-typescript-loader": "^5.2.1", 13 | "css-loader": "^1.0.0", 14 | "extract-text-webpack-plugin": "^4.0.0-beta", 15 | "file-loader": "^2.0.0", 16 | "installed-check": "^2.2.0", 17 | "node-sass": "^4.9.3", 18 | "optimize-css-assets-webpack-plugin": "^5.0.1", 19 | "sass-loader": "^7.1.0", 20 | "style-loader": "^0.23.1", 21 | "ts-loader": "^5.2.2", 22 | "typescript": "^3.1.3", 23 | "webpack": "^4.20.2", 24 | "webpack-cli": "^3.1.2" 25 | }, 26 | "dependencies": { 27 | "@sentry/webpack-plugin": "^1.6.1", 28 | "@types/raven-js": "^3.10.0", 29 | "@types/react": "^16.4.16", 30 | "@types/react-dom": "^16.0.9", 31 | "axios": "^0.18.0", 32 | "raven-js": "^3.27.0", 33 | "react": "^16.5.2", 34 | "react-dom": "^16.5.2", 35 | "request": "^2.88.0", 36 | "uuid": "^3.3.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /edit-server/src/db/conn.rs: -------------------------------------------------------------------------------- 1 | //! Methods for creating a database connection and connection pool. 2 | 3 | use diesel::{ 4 | prelude::*, 5 | sqlite::SqliteConnection, 6 | }; 7 | use dotenv::dotenv; 8 | use r2d2; 9 | use r2d2_diesel::ConnectionManager; 10 | use std::env; 11 | 12 | pub type DbPool = r2d2::Pool>; 13 | 14 | pub fn db_pool_create() -> DbPool { 15 | dotenv().ok(); 16 | 17 | let mut database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 18 | database_url = format!("../{}", database_url); 19 | 20 | let manager = ConnectionManager::::new(database_url.clone()); 21 | r2d2::Pool::builder() 22 | .build(manager) 23 | .expect(&format!("Error connecting to {}", database_url)) 24 | } 25 | 26 | pub fn db_connection() -> SqliteConnection { 27 | dotenv().ok(); 28 | 29 | let mut database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 30 | database_url = format!("../{}", database_url); 31 | 32 | SqliteConnection::establish(&database_url) 33 | .expect(&format!("Error connecting to {}", database_url)) 34 | } 35 | -------------------------------------------------------------------------------- /edit-common/tests/transform/164: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(1), DelSkip(4), DelChars(7) 14 | ]), 15 | DelGroup([ 16 | DelSkip(19) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h1"}, [ 21 | AddChars("X ") 22 | ]), 23 | AddGroup({"tag": "bullet"}, [ 24 | AddGroup({"tag": "h3"}, [ 25 | AddChars("D"), AddSkip(4), AddGroup({"client": "b", "tag": "caret"}, []), 26 | AddChars("VS3"), AddGroup({"client": "a", "tag": "caret"}, []), 27 | AddChars("c"), AddSkip(19) 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelWithGroup([ 34 | DelChars(1), DelSkip(11) 35 | ]), 36 | DelSkip(1) 37 | ] 38 | b_add: [ 39 | AddGroup({"tag": "bullet"}, [ 40 | AddWithGroup([ 41 | AddChars("88"), AddSkip(11) 42 | ]) 43 | ]), 44 | AddWithGroup([ 45 | AddGroup({"client": "c", "tag": "caret"}, []) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/73: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelWithGroup([ 13 | DelChars(2), DelSkip(10) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddWithGroup([ 22 | AddGroup({"tag": "caret", "client": "a"}, []), 23 | AddChars("3"), AddSkip(10) 24 | ]) 25 | ]), 26 | AddGroup({"tag": "p"}, [ 27 | AddChars("m "), AddSkip(18) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelChars(1), DelSkip(4), DelChars(7) 34 | ]), 35 | DelGroup([ 36 | DelChars(1), DelSkip(18) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h1"}, [ 42 | AddSkip(4) 43 | ]), 44 | AddGroup({"tag": "p"}, [ 45 | AddChars("g"), AddGroup({"client": "b", "tag": "caret"}, []), 46 | AddSkip(18) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-common/tests/transform/124: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars("V"), DocGroup({"tag": "caret", "client": "b"}, []), 7 | DocChars("Djell1 F") 8 | ]) 9 | ]), 10 | DocGroup({"tag": "h2"}, [ 11 | DocChars("6\'s up with you?") 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelGroup([]), 19 | DelChars(1) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddChars("vA"), AddGroup({"tag": "caret", "client": "a"}, []) 26 | ]) 27 | ] 28 | 29 | b_del: [ 30 | DelWithGroup([ 31 | DelGroup([ 32 | DelWithGroup([]), 33 | DelSkip(1), DelGroup([]), 34 | DelSkip(1), DelChars(1), DelSkip(6) 35 | ]) 36 | ]) 37 | ] 38 | b_add: [ 39 | AddWithGroup([ 40 | AddGroup({"tag": "h2"}, [ 41 | AddGroup({"client": "b", "tag": "caret"}, []), 42 | AddWithGroup([]), 43 | AddSkip(2), AddChars(" "), AddSkip(6) 44 | ]) 45 | ]) 46 | ] 47 | -------------------------------------------------------------------------------- /edit-common/tests/transform/219: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("mHl"), DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("ello world!W"), DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("at\'s up with you?") 7 | ]) 8 | ] 9 | 10 | a_del: [ 11 | DelGroup([ 12 | DelSkip(1), DelChars(2), DelGroup([]), 13 | DelSkip(30) 14 | ]) 15 | ] 16 | a_add: [ 17 | AddGroup({"tag": "h1"}, [ 18 | AddChars("W"), AddGroup({"tag": "caret", "client": "a"}, []) 19 | ]), 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "p"}, [ 22 | AddChars("s"), AddSkip(31) 23 | ]) 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelGroup([ 29 | DelSkip(3), DelWithGroup([]), 30 | DelSkip(8), DelChars(4), DelGroup([]), 31 | DelSkip(17) 32 | ]) 33 | ] 34 | b_add: [ 35 | AddGroup({"tag": "bullet"}, [ 36 | AddGroup({"tag": "h3"}, [ 37 | AddChars(" s"), AddGroup({"client": "b", "tag": "caret"}, []), 38 | AddSkip(3), AddWithGroup([]), 39 | AddSkip(8), AddChars("JN"), AddSkip(17) 40 | ]) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/99: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars(" "), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("llo world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(1), DelGroup([]), 15 | DelChars(2), DelSkip(8) 16 | ]), 17 | DelWithGroup([]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h2"}, [ 22 | AddChars("7"), AddSkip(8) 23 | ]) 24 | ]), 25 | AddWithGroup([ 26 | AddGroup({"tag": "caret", "client": "a"}, []) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelSkip(1), DelWithGroup([]), 33 | DelSkip(8), DelChars(2) 34 | ]), 35 | DelGroup([ 36 | DelChars(1), DelSkip(18) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "p"}, [ 42 | AddChars(" v"), AddSkip(1), AddWithGroup([]), 43 | AddSkip(8), AddGroup({"tag": "caret", "client": "b"}, []), 44 | AddSkip(18) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/155: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(1), DelSkip(11) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "p"}, [ 21 | AddChars("w"), AddGroup({"tag": "caret", "client": "a"}, []), 22 | AddChars("4 "), AddSkip(1), AddChars(" 0"), AddSkip(10) 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "p"}, [ 26 | AddChars(" "), AddGroup({"tag": "caret", "client": "b"}, []), 27 | AddChars("4f"), AddSkip(18) 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelSkip(6), DelChars(6) 35 | ]), 36 | DelGroup([ 37 | DelSkip(19) 38 | ]) 39 | ] 40 | b_add: [ 41 | AddGroup({"tag": "bullet"}, [ 42 | AddGroup({"tag": "h3"}, [ 43 | AddSkip(6), AddChars("I3"), AddGroup({"tag": "caret", "client": "c"}, []), 44 | AddSkip(19) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /oatie/tests/transform.rs: -------------------------------------------------------------------------------- 1 | use oatie::transform_test::*; 2 | use std::fs; 3 | 4 | #[test] 5 | fn main() { 6 | let root_path = &::std::env::current_exe() 7 | .unwrap() 8 | .parent() 9 | .unwrap() 10 | .parent() 11 | .unwrap() 12 | .parent() 13 | .unwrap() 14 | .parent() 15 | .unwrap() 16 | .join("oatie/tests/transform/"); 17 | 18 | // eprintln!("HELP: {:?}", root_path); 19 | let paths = fs::read_dir(&root_path).unwrap(); 20 | 21 | for entry in paths { 22 | // println!("Name: {}", path.unwrap().path().display() 23 | 24 | if let Ok(entry) = entry { 25 | if entry.metadata().unwrap().is_file() { 26 | let value = fs::read_to_string(entry.path()).unwrap(); 27 | match run_transform_test(&value) { 28 | Ok(..) => { 29 | println!("all set!"); 30 | } 31 | Err(err) => { 32 | eprintln!("transform test error: {:?}", err); 33 | ::std::process::exit(1); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /edit-common/tests/transform/159: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars(" e") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocGroup({"client": "a", "tag": "caret"}, []), 8 | DocChars("0e world!") 9 | ]), 10 | DocGroup({"tag": "p"}, [ 11 | DocChars("What\'s up with you?") 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelChars(2) 18 | ]), 19 | DelGroup([ 20 | DelGroup([]), 21 | DelChars(1), DelSkip(8) 22 | ]) 23 | ] 24 | a_add: [ 25 | AddGroup({"tag": "bullet"}, [ 26 | AddGroup({"tag": "h2"}, [ 27 | AddGroup({"tag": "caret", "client": "a"}, []), 28 | AddChars(" 6 k"), AddSkip(8) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelSkip(1), DelChars(1) 36 | ]), 37 | DelWithGroup([]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "p"}, [ 42 | AddSkip(1), AddChars("1") 43 | ]), 44 | AddGroup({"tag": "p"}, [ 45 | AddChars("2") 46 | ]) 47 | ]), 48 | AddWithGroup([ 49 | AddGroup({"tag": "caret", "client": "b"}, []) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-25: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "pre"}, [ 3 | DocChars("7"), DocGroup({"client": "right", "tag": "caret"}, []), 4 | DocChars("a ca qcyv FP C4 l 5xR Ewx vx n2ME0OkL hnKX3HSNr2 F76I15m6T4Y il L") 5 | ]), 6 | DocGroup({"tag": "h1"}, [ 7 | DocGroup({"tag": "caret", "client": "left"}, []), 8 | DocChars("o7C5 k H DmA6 m rdmYx U 6A I dgx 6 qiWAV1edWk7 73 t7j1T60 V6 wEP 5a 65GB1P71 u f vs7Y5 WLdw8 Yg lPXQ pLv7d6 6k 3u1 04qXTFpB562Dk illo world!fF I bbat\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelSkip(1), DelWithGroup([]), 15 | DelSkip(68) 16 | ]), 17 | DelWithGroup([ 18 | DelGroup([]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddSkip(1), AddWithGroup([]), 24 | AddSkip(68), AddGroup({"client": "left", "tag": "caret"}, []) 25 | ]), 26 | AddWithGroup([]) 27 | ] 28 | 29 | b_del: [ 30 | DelGroup([ 31 | DelSkip(1), DelGroup([]), 32 | DelSkip(68) 33 | ]) 34 | ] 35 | b_add: [ 36 | AddGroup({"tag": "pre"}, [ 37 | AddSkip(2), AddGroup({"client": "right", "tag": "caret"}, []), 38 | AddSkip(67) 39 | ]) 40 | ] -------------------------------------------------------------------------------- /edit-common/tests/transform/130: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("dWhat\'s up with you?") 6 | ]) 7 | ] 8 | 9 | a_del: [ 10 | DelGroup([ 11 | DelGroup([]), 12 | DelChars(1), DelSkip(19) 13 | ]) 14 | ] 15 | a_add: [ 16 | AddGroup({"tag": "bullet"}, [ 17 | AddGroup({"tag": "h3"}, [ 18 | AddGroup({"client": "c", "tag": "caret"}, []), 19 | AddChars(" 0 bF"), AddGroup({"client": "b", "tag": "caret"}, []), 20 | AddChars(" jj Nl"), AddGroup({"client": "d", "tag": "caret"}, []), 21 | AddChars(" ") 22 | ]), 23 | AddGroup({"tag": "p"}, [ 24 | AddGroup({"client": "a", "tag": "caret"}, []), 25 | AddSkip(19) 26 | ]) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelSkip(21) 33 | ]) 34 | ] 35 | b_add: [ 36 | AddGroup({"tag": "bullet"}, [ 37 | AddGroup({"tag": "pre"}, [ 38 | AddChars("HC"), AddGroup({"tag": "caret", "client": "e"}, []), 39 | AddChars("r1v") 40 | ]) 41 | ]), 42 | AddGroup({"tag": "p"}, [ 43 | AddSkip(21) 44 | ]) 45 | ] 46 | -------------------------------------------------------------------------------- /oatie/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Defines types for using operational tranform to modify HTML-like documents. 2 | //! 3 | //! See the book for more details: http://tcr.github.io/edit-text/ 4 | 5 | #![feature(nll, range_is_empty)] 6 | 7 | #[macro_use] 8 | extern crate log; 9 | #[macro_use] 10 | extern crate maplit; 11 | #[macro_use] 12 | extern crate serde_derive; 13 | #[macro_use] 14 | extern crate failure; 15 | #[macro_use] 16 | extern crate wasm_typescript_definition; 17 | 18 | /* logging */ 19 | 20 | // Macros can only be used after they are defined 21 | 22 | macro_rules! log_transform { 23 | ($($x:expr),* $(,)*) => { 24 | // println!( $( $x ),* ); 25 | }; 26 | } 27 | 28 | macro_rules! log_compose { 29 | ($($x:expr),* $(,)*) => { 30 | // println!( $( $x ),* ); 31 | }; 32 | } 33 | 34 | /* /logging */ 35 | 36 | // First enable macros. 37 | #[macro_use] 38 | pub mod macros; 39 | #[macro_use] 40 | pub mod wasm; 41 | 42 | // Then import & re-export core items. 43 | mod core; 44 | mod parse; 45 | pub mod deserialize; 46 | pub mod normalize; 47 | pub mod rtf; 48 | pub mod stepper; 49 | pub mod transform_test; 50 | pub mod validate; 51 | pub mod writer; 52 | 53 | // Re-export core items. 54 | pub use self::core::*; 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/106: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "pre"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars("dlkSV4"), DocGroup({"tag": "caret", "client": "b"}, []), 7 | DocChars("lo worl !What\'s up with you?") 8 | ]) 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelWithGroup([ 15 | DelGroup([]), 16 | DelChars(1) 17 | ]) 18 | ]) 19 | ] 20 | a_add: [ 21 | AddWithGroup([ 22 | AddChars("3"), AddGroup({"client": "a", "tag": "caret"}, []), 23 | AddChars("K") 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelWithGroup([ 29 | DelGroup([ 30 | DelWithGroup([]), 31 | DelSkip(1), DelChars(5), DelGroup([]), 32 | DelSkip(28) 33 | ]) 34 | ]) 35 | ] 36 | b_add: [ 37 | AddWithGroup([ 38 | AddGroup({"tag": "pre"}, [ 39 | AddChars("Y"), AddGroup({"client": "b", "tag": "caret"}, []), 40 | AddWithGroup([]), 41 | AddSkip(1) 42 | ]), 43 | AddGroup({"tag": "p"}, [ 44 | AddChars("x1c"), AddSkip(28) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/149: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("3D Hello wor7at\'s up with you?") 6 | ]) 7 | ] 8 | 9 | a_del: [ 10 | DelGroup([ 11 | DelGroup([]), 12 | DelSkip(1), DelChars(6), DelSkip(23) 13 | ]) 14 | ] 15 | a_add: [ 16 | AddGroup({"tag": "h2"}, [ 17 | AddChars("aE"), AddGroup({"client": "b", "tag": "caret"}, []), 18 | AddChars("X "), AddSkip(1), AddChars("qp O"), AddGroup({"tag": "caret", "client": "c"}, []) 19 | ]), 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h3"}, [ 22 | AddChars("Q "), AddGroup({"tag": "caret", "client": "a"}, []), 23 | AddChars("bc"), AddSkip(23) 24 | ]) 25 | ]) 26 | ] 27 | 28 | b_del: [ 29 | DelGroup([ 30 | DelWithGroup([]), 31 | DelSkip(1), DelChars(2), DelSkip(27) 32 | ]) 33 | ] 34 | b_add: [ 35 | AddGroup({"tag": "bullet"}, [ 36 | AddGroup({"tag": "h3"}, [ 37 | AddChars(" 4"), AddWithGroup([]), 38 | AddSkip(1), AddChars("Y3He"), AddGroup({"client": "d", "tag": "caret"}, []), 39 | AddSkip(27) 40 | ]) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/333: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "p"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars(" ") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("6W MN"), DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars("hM 43q SguYello Cgn DKt\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelWithGroup([ 18 | DelGroup([]) 19 | ]) 20 | ]) 21 | ] 22 | a_add: [ 23 | AddWithGroup([ 24 | AddWithGroup([ 25 | AddChars("C"), AddGroup({"tag": "caret", "client": "a"}, []) 26 | ]) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelWithGroup([ 33 | DelWithGroup([]), 34 | DelSkip(1) 35 | ]), 36 | DelWithGroup([ 37 | DelSkip(1), DelChars(4), DelGroup([]) 38 | ]) 39 | ]) 40 | ] 41 | b_add: [ 42 | AddWithGroup([ 43 | AddGroup({"tag": "caret", "client": "b"}, []), 44 | AddWithGroup([]), 45 | AddSkip(1) 46 | ]), 47 | AddWithGroup([ 48 | AddSkip(1) 49 | ]) 50 | ] 51 | -------------------------------------------------------------------------------- /edit-common/tests/transform/59: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars(" X wohWhat\'s up with you?") 7 | ]) 8 | ] 9 | 10 | a_del: [ 11 | DelGroup([ 12 | DelGroup([]), 13 | DelWithGroup([]), 14 | DelSkip(26) 15 | ]) 16 | ] 17 | a_add: [ 18 | AddGroup({"tag": "h3"}, [ 19 | AddWithGroup([]), 20 | AddSkip(1), AddChars("L5lX") 21 | ]), 22 | AddGroup({"tag": "bullet"}, [ 23 | AddGroup({"tag": "h2"}, [ 24 | AddChars("3"), AddGroup({"tag": "caret", "client": "a"}, []), 25 | AddChars("7n"), AddSkip(25) 26 | ]) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelWithGroup([]), 33 | DelGroup([]), 34 | DelSkip(1), DelChars(2), DelSkip(23) 35 | ]) 36 | ] 37 | b_add: [ 38 | AddGroup({"tag": "bullet"}, [ 39 | AddGroup({"tag": "h1"}, [ 40 | AddChars(" "), AddWithGroup([]), 41 | AddChars(" "), AddSkip(1), AddChars("G7j"), AddGroup({"tag": "caret", "client": "b"}, []), 42 | AddChars("d"), AddSkip(23) 43 | ]) 44 | ]) 45 | ] 46 | -------------------------------------------------------------------------------- /edit-common/tests/transform.rs: -------------------------------------------------------------------------------- 1 | use oatie::transform_test::*; 2 | use std::fs; 3 | 4 | #[test] 5 | fn main() { 6 | let root_path = &::std::env::current_exe() 7 | .unwrap() 8 | .parent() 9 | .unwrap() 10 | .parent() 11 | .unwrap() 12 | .parent() 13 | .unwrap() 14 | .parent() 15 | .unwrap() 16 | .join("edit-common/tests/transform/"); 17 | 18 | eprintln!("root_path: {:?}", root_path); 19 | 20 | let mut tests = vec![]; 21 | for entry in fs::read_dir(&root_path).unwrap() { 22 | if let Ok(entry) = entry { 23 | if entry.metadata().unwrap().is_file() { 24 | tests.push(entry.path()); 25 | } 26 | } 27 | } 28 | 29 | tests.sort(); 30 | for file in tests { 31 | let value = fs::read_to_string(&file).unwrap(); 32 | println!(); 33 | println!("[{:?}]", file); 34 | match run_transform_test(&value) { 35 | Ok(..) => { 36 | println!("all set!"); 37 | } 38 | Err(err) => { 39 | eprintln!("transform test error: {:?}", err); 40 | ::std::process::exit(1); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /edit-common/tests/transform/39: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars(" "), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("k MelloBA What\'s up with you?") 6 | ]) 7 | ] 8 | 9 | a_del: [ 10 | DelGroup([ 11 | DelChars(1), DelGroup([]), 12 | DelSkip(1), DelChars(1), DelSkip(1), DelChars(2), DelSkip(24) 13 | ]) 14 | ] 15 | a_add: [ 16 | AddGroup({"tag": "h2"}, [ 17 | AddGroup({"client": "a", "tag": "caret"}, []), 18 | AddGroup({"client": "c", "tag": "caret"}, []), 19 | AddChars("K6 "), AddGroup({"client": "b", "tag": "caret"}, []), 20 | AddChars(" 4") 21 | ]), 22 | AddGroup({"tag": "bullet"}, [ 23 | AddGroup({"tag": "h2"}, [ 24 | AddChars(" "), AddSkip(1), AddChars("6"), AddSkip(1), AddChars("0"), AddGroup({"tag": "caret", "client": "d"}, []), 25 | AddSkip(24) 26 | ]) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelGroup([ 32 | DelSkip(31) 33 | ]) 34 | ] 35 | b_add: [ 36 | AddGroup({"tag": "bullet"}, [ 37 | AddGroup({"tag": "h3"}, [ 38 | AddChars("M"), AddGroup({"tag": "caret", "client": "e"}, []), 39 | AddSkip(31) 40 | ]) 41 | ]) 42 | ] 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/158: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(1), DelSkip(7), DelChars(4) 14 | ]), 15 | DelGroup([ 16 | DelChars(3), DelSkip(16) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h3"}, [ 22 | AddChars("1 "), AddSkip(7), AddGroup({"client": "a", "tag": "caret"}, []), 23 | AddChars("H 5"), AddGroup({"tag": "caret", "client": "b"}, []) 24 | ]) 25 | ]), 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "h3"}, [ 28 | AddSkip(16) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelChars(1), DelSkip(10), DelChars(1) 36 | ]), 37 | DelGroup([ 38 | DelSkip(19) 39 | ]) 40 | ] 41 | b_add: [ 42 | AddGroup({"tag": "bullet"}, [ 43 | AddGroup({"tag": "h1"}, [ 44 | AddChars("C"), AddGroup({"tag": "caret", "client": "c"}, []), 45 | AddChars("2"), AddSkip(10), AddChars("O"), AddSkip(19) 46 | ]) 47 | ]) 48 | ] 49 | -------------------------------------------------------------------------------- /edit-common/tests/transform/433: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("4"), DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars(" ") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("CS"), DocGroup({"client": "a", "tag": "caret"}, []), 10 | DocChars(" cllo world!") 11 | ]) 12 | ]), 13 | DocGroup({"tag": "p"}, [ 14 | DocChars("What\'s up with you?") 15 | ]) 16 | ] 17 | 18 | a_del: [ 19 | DelGroup([ 20 | DelWithGroup([ 21 | DelSkip(1), DelWithGroup([]), 22 | DelSkip(1) 23 | ]), 24 | DelWithGroup([ 25 | DelChars(2) 26 | ]) 27 | ]) 28 | ] 29 | a_add: [ 30 | AddWithGroup([ 31 | AddSkip(1), AddWithGroup([]), 32 | AddSkip(1) 33 | ]), 34 | AddWithGroup([ 35 | AddChars("C") 36 | ]) 37 | ] 38 | 39 | b_del: [ 40 | DelWithGroup([ 41 | DelWithGroup([ 42 | DelChars(1), DelGroup([]) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddWithGroup([ 49 | AddGroup({"tag": "caret", "client": "b"}, []) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-frontend/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 3 | 4 | module.exports = { 5 | output: { 6 | publicPath: '/$/', 7 | }, 8 | devtool: 'source-map', 9 | plugins: [ 10 | // new webpack.ProvidePlugin({ 11 | // $: 'jquery', 12 | // jQuery: 'jquery', 13 | // 'window.jQuery': 'jquery', 14 | // }), 15 | new ExtractTextPlugin("edit.css"), 16 | ], 17 | resolve: { 18 | extensions: ['.ts', '.tsx', '.js', '.jsx', '.wasm'] 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.scss$/, 24 | use: ExtractTextPlugin.extract({ 25 | fallback: "style-loader", 26 | use: ['css-loader', 'sass-loader'], 27 | }) 28 | }, 29 | { 30 | test: /\.css$/, use: [ 31 | { loader: "style-loader" }, 32 | { loader: "css-loader" } 33 | ] 34 | }, 35 | { 36 | test: /\.(ttf|eot|svg|woff2?)(\?[a-z0-9]+)?$/, 37 | use: [{ loader: 'file-loader' }], 38 | }, 39 | { 40 | test: /\.tsx?$/, 41 | use: [ 42 | {loader: 'ts-loader' } 43 | ], 44 | exclude: /node_modules/ 45 | }, 46 | ] 47 | }, 48 | }; -------------------------------------------------------------------------------- /edit-frontend/styles/footer.scss: -------------------------------------------------------------------------------- 1 | #footer { 2 | position: fixed; 3 | bottom: 0; 4 | left: 0; 5 | right: 0; 6 | pointer-events: none; 7 | z-index: 2000; 8 | 9 | .footer-bar { 10 | box-sizing: border-box; 11 | border-top: 1px solid #cb9; 12 | background: #fff3bb; 13 | padding: 7px 10px 8px; 14 | z-index: 100; 15 | padding-left: 34px; 16 | position: relative; 17 | pointer-events: auto; 18 | 19 | // Close button 20 | span { 21 | opacity: 0.3; 22 | position: absolute; 23 | top: 2px; 24 | left: 12px; 25 | font-size: 20px; 26 | cursor: pointer; 27 | user-select: none; 28 | 29 | &:hover { 30 | opacity: 1.0; 31 | } 32 | } 33 | 34 | button { 35 | font: inherit; 36 | } 37 | 38 | text-shadow: none; 39 | 40 | &.error { 41 | border-top-color: #a55; 42 | background: #cc3333; 43 | color: white; 44 | text-shadow: 1px 1px 0px rgba(0.0, 0.0, 0.0, 0.3); 45 | 46 | span { 47 | opacity: 0.5; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-18: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "h1"}, [ 3 | DocChars("5j 5 1V11"), DocGroup({"client": "right", "tag": "caret"}, []) 4 | ]), 5 | DocGroup({"tag": "p"}, [ 6 | DocChars("8ic ubC6 4f L N VYT 6e8 E V3g 5r3wE lc bNP 1"), DocGroup({"tag": "caret", "client": "left"}, []), 7 | DocChars("lC71kOl36UW8 m465l1V 4L71y5arK8f ao xy7rA Jko86t eW y8w4KYK8R BR 8N6ExKeq 3s72 vwdsH8Q t 3 4 Ll S n8E3PWBi1XG2sH0 P S ello world! 5 W bWhat\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelWithGroup([ 13 | DelSkip(10), DelWithGroup([]) 14 | ]), 15 | DelGroup([ 16 | DelSkip(48), DelChars(1), DelGroup([]), 17 | DelSkip(160) 18 | ]) 19 | ] 20 | a_add: [ 21 | AddWithGroup([ 22 | AddSkip(10), AddWithGroup([]) 23 | ]), 24 | AddGroup({"tag": "h2"}, [ 25 | AddSkip(50), AddGroup({"tag": "caret", "client": "left"}, []), 26 | AddSkip(158) 27 | ]) 28 | ] 29 | 30 | b_del: [ 31 | DelWithGroup([ 32 | DelSkip(10), DelGroup([]) 33 | ]), 34 | DelSkip(1) 35 | ] 36 | b_add: [ 37 | AddWithGroup([ 38 | AddSkip(10) 39 | ]), 40 | AddWithGroup([ 41 | AddGroup({"client": "right", "tag": "caret"}, []) 42 | ]) 43 | ] -------------------------------------------------------------------------------- /edit-server/src/bin/edit-server-logs.rs: -------------------------------------------------------------------------------- 1 | use diesel::connection::Connection; 2 | use edit_server::db::*; 3 | use failure::*; 4 | use serde_json; 5 | use structopt::*; 6 | 7 | #[derive(Debug, StructOpt)] 8 | enum Cli { 9 | #[structopt(name = "list")] 10 | List { 11 | #[structopt(long = "source")] 12 | source: Option, 13 | }, 14 | 15 | #[structopt(name = "clear")] 16 | Clear, 17 | } 18 | 19 | fn main() -> Result<(), Error> { 20 | let args = Cli::from_args(); 21 | 22 | let db = db_connection(); 23 | 24 | match args { 25 | Cli::Clear => { 26 | clear_all_logs(&db)?; 27 | db.execute("VACUUM").unwrap(); 28 | eprintln!("cleared logs."); 29 | } 30 | Cli::List { source } => { 31 | let logs = if let Some(source) = source { 32 | eprintln!("Filter by source: {}", source); 33 | select_logs(&db, &source)? 34 | } else { 35 | all_logs(&db)? 36 | }; 37 | 38 | eprintln!("Printing {} logs...", logs.len()); 39 | 40 | for log in logs { 41 | println!("{}", serde_json::to_string(&log).unwrap()); 42 | } 43 | } 44 | } 45 | 46 | Ok(()) 47 | } 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/215: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "pre"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("v"), DocGroup({"client": "b", "tag": "caret"}, []), 7 | DocChars("3j"), DocGroup({"client": "c", "tag": "caret"}, []), 8 | DocChars("3Ulo world!5What\'s up with you?") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelWithGroup([ 16 | DelGroup([]), 17 | DelChars(1) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddChars(" "), AddGroup({"tag": "caret", "client": "a"}, []) 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelWithGroup([ 29 | DelGroup([ 30 | DelWithGroup([]), 31 | DelSkip(1), DelGroup([]), 32 | DelSkip(34) 33 | ]) 34 | ]) 35 | ] 36 | b_add: [ 37 | AddWithGroup([ 38 | AddGroup({"tag": "pre"}, [ 39 | AddGroup({"client": "b", "tag": "caret"}, []), 40 | AddChars("r"), AddWithGroup([]), 41 | AddSkip(1), AddChars("3") 42 | ]), 43 | AddGroup({"tag": "p"}, [ 44 | AddChars("P"), AddSkip(34) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/148: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "p"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars("lello wor ty\'"), DocGroup({"client": "c", "tag": "caret"}, []), 7 | DocChars("s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelGroup([]), 14 | DelWithGroup([]), 15 | DelSkip(28) 16 | ]) 17 | ] 18 | a_add: [ 19 | AddGroup({"tag": "h2"}, [ 20 | AddChars(" "), AddGroup({"tag": "caret", "client": "a"}, []), 21 | AddChars("2"), AddWithGroup([]), 22 | AddSkip(1), AddChars("N") 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "h2"}, [ 26 | AddSkip(1), AddChars("7"), AddSkip(26) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([]), 34 | DelGroup([]), 35 | DelChars(1), DelSkip(27) 36 | ]) 37 | ] 38 | b_add: [ 39 | AddGroup({"tag": "bullet"}, [ 40 | AddGroup({"tag": "pre"}, [ 41 | AddChars("32"), AddGroup({"tag": "caret", "client": "b"}, []), 42 | AddWithGroup([]), 43 | AddChars("m8"), AddSkip(27) 44 | ]) 45 | ]) 46 | ] 47 | -------------------------------------------------------------------------------- /edit-common/tests/transform/830: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "pre"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars(" g") 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocChars(" OK "), DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars("lokWhat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelGroup([ 18 | DelGroup([]), 19 | DelChars(2) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "h3"}, [ 26 | AddChars(" "), AddGroup({"tag": "caret", "client": "a"}, []) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([ 34 | DelWithGroup([]), 35 | DelSkip(2) 36 | ]), 37 | DelWithGroup([ 38 | DelSkip(1), DelChars(3), DelGroup([]) 39 | ]) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddWithGroup([ 44 | AddWithGroup([]), 45 | AddSkip(2) 46 | ]), 47 | AddWithGroup([ 48 | AddSkip(1), AddChars("x"), AddGroup({"client": "b", "tag": "caret"}, []), 49 | AddChars("2") 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /edit-common/tests/transform/725: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocChars("X"), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("5") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocGroup({"tag": "caret", "client": "b"}, []) 9 | ]), 10 | DocGroup({"tag": "h3"}, [ 11 | DocChars("3 n K ") 12 | ]), 13 | DocGroup({"tag": "p"}, [ 14 | DocChars("G l8a53KHxel owWhat\'s up with you?") 15 | ]) 16 | ] 17 | 18 | a_del: [ 19 | DelWithGroup([ 20 | DelChars(1), DelGroup([]), 21 | DelChars(1) 22 | ]), 23 | DelSkip(1) 24 | ] 25 | a_add: [ 26 | AddWithGroup([ 27 | AddChars(" ") 28 | ]), 29 | AddWithGroup([ 30 | AddGroup({"client": "a", "tag": "caret"}, []) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelWithGroup([ 36 | DelSkip(1), DelWithGroup([]), 37 | DelSkip(1) 38 | ]), 39 | DelGroup([ 40 | DelGroup([]) 41 | ]), 42 | DelGroup([ 43 | DelSkip(6) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddSkip(1), AddWithGroup([]), 49 | AddSkip(1) 50 | ]), 51 | AddGroup({"tag": "p"}, [ 52 | AddChars("H"), AddGroup({"client": "b", "tag": "caret"}, []), 53 | AddSkip(6) 54 | ]) 55 | ] 56 | -------------------------------------------------------------------------------- /edit-common/tests/transform/113: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(2), DelSkip(8), DelChars(2) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h2"}, [ 21 | AddChars(" 2 f5") 22 | ]), 23 | AddGroup({"tag": "bullet"}, [ 24 | AddGroup({"tag": "h1"}, [ 25 | AddGroup({"tag": "caret", "client": "b"}, []), 26 | AddChars("Q"), AddSkip(8), AddChars("l"), AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddChars("7"), AddGroup({"tag": "caret", "client": "c"}, []) 28 | ]) 29 | ]), 30 | AddGroup({"tag": "h1"}, [ 31 | AddSkip(18) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelSkip(10), DelChars(2) 38 | ]), 39 | DelGroup([ 40 | DelSkip(19) 41 | ]) 42 | ] 43 | b_add: [ 44 | AddGroup({"tag": "bullet"}, [ 45 | AddGroup({"tag": "h1"}, [ 46 | AddChars("d"), AddSkip(9), AddChars("b"), AddGroup({"client": "d", "tag": "caret"}, []), 47 | AddSkip(20) 48 | ]) 49 | ]) 50 | ] 51 | -------------------------------------------------------------------------------- /edit-common/tests/transform/213: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocGroup({"client": "c", "tag": "caret"}, []), 6 | DocChars(" ello world!W"), DocGroup({"client": "b", "tag": "caret"}, []), 7 | DocChars("hat\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelGroup([]), 14 | DelSkip(33) 15 | ]) 16 | ] 17 | a_add: [ 18 | AddGroup({"tag": "h2"}, []), 19 | AddGroup({"tag": "bullet"}, [ 20 | AddGroup({"tag": "h1"}, [ 21 | AddGroup({"tag": "caret", "client": "a"}, []), 22 | AddChars(" "), AddSkip(33) 23 | ]) 24 | ]) 25 | ] 26 | 27 | b_del: [ 28 | DelGroup([ 29 | DelWithGroup([]), 30 | DelWithGroup([]), 31 | DelSkip(1), DelChars(1), DelSkip(7), DelChars(2), DelSkip(1), DelChars(1), DelGroup([]), 32 | DelChars(1), DelSkip(17) 33 | ]) 34 | ] 35 | b_add: [ 36 | AddGroup({"tag": "bullet"}, [ 37 | AddGroup({"tag": "p"}, [ 38 | AddWithGroup([]), 39 | AddWithGroup([]), 40 | AddSkip(1), AddChars("R"), AddGroup({"client": "b", "tag": "caret"}, []), 41 | AddChars(" "), AddSkip(7), AddChars("b "), AddSkip(18) 42 | ]) 43 | ]) 44 | ] 45 | -------------------------------------------------------------------------------- /edit-common/tests/transform/638: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("f") 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars("ulc245"), DocGroup({"client": "a", "tag": "caret"}, []), 10 | DocChars("oSFo worl!What\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelWithGroup([]), 19 | DelSkip(1) 20 | ]), 21 | DelWithGroup([ 22 | DelSkip(3), DelChars(1), DelSkip(1), DelChars(1), DelGroup([]), 23 | DelChars(1) 24 | ]) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddWithGroup([ 29 | AddWithGroup([]), 30 | AddSkip(1) 31 | ]), 32 | AddWithGroup([ 33 | AddSkip(3), AddGroup({"tag": "caret", "client": "a"}, []), 34 | AddSkip(1) 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelWithGroup([ 40 | DelWithGroup([ 41 | DelGroup([]) 42 | ]) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddWithGroup([ 47 | AddWithGroup([ 48 | AddGroup({"client": "b", "tag": "caret"}, []), 49 | AddChars("q") 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/251: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("fello world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelGroup([]), 15 | DelSkip(12) 16 | ]), 17 | DelGroup([ 18 | DelChars(2), DelSkip(17) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddChars(" J"), AddSkip(12) 24 | ]), 25 | AddGroup({"tag": "p"}, []), 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "p"}, [ 28 | AddChars("Y"), AddGroup({"tag": "caret", "client": "a"}, []), 29 | AddSkip(17) 30 | ]) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelWithGroup([ 36 | DelWithGroup([]), 37 | DelSkip(10), DelChars(2) 38 | ]), 39 | DelGroup([ 40 | DelSkip(19) 41 | ]) 42 | ] 43 | b_add: [ 44 | AddWithGroup([ 45 | AddChars("FA"), AddWithGroup([]), 46 | AddSkip(10), AddChars("2") 47 | ]), 48 | AddGroup({"tag": "bullet"}, [ 49 | AddGroup({"tag": "h3"}, [ 50 | AddGroup({"tag": "caret", "client": "b"}, []), 51 | AddSkip(19) 52 | ]) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/322: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("W7G"), DocGroup({"client": "c", "tag": "caret"}, []), 7 | DocChars(" 8Bd") 8 | ]), 9 | DocGroup({"tag": "h2"}, [ 10 | DocGroup({"tag": "caret", "client": "a"}, []), 11 | DocChars("er6loWhat\'s up with you?") 12 | ]) 13 | ]) 14 | ] 15 | 16 | a_del: [ 17 | DelGroup([ 18 | DelWithGroup([ 19 | DelWithGroup([]), 20 | DelSkip(3), DelWithGroup([]), 21 | DelSkip(2), DelChars(2) 22 | ]), 23 | DelWithGroup([ 24 | DelGroup([]) 25 | ]) 26 | ]) 27 | ] 28 | a_add: [ 29 | AddWithGroup([ 30 | AddWithGroup([]), 31 | AddSkip(3), AddWithGroup([]), 32 | AddSkip(2), AddChars("n"), AddGroup({"tag": "caret", "client": "a"}, []) 33 | ]), 34 | AddWithGroup([]) 35 | ] 36 | 37 | b_del: [ 38 | DelWithGroup([ 39 | DelWithGroup([ 40 | DelGroup([]) 41 | ]) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddWithGroup([ 46 | AddWithGroup([ 47 | AddGroup({"client": "b", "tag": "caret"}, []) 48 | ]) 49 | ]) 50 | ] 51 | -------------------------------------------------------------------------------- /oatie/src/core/ot.rs: -------------------------------------------------------------------------------- 1 | /// A type that can have operational transform applied to it. 2 | /// The `OT` trait is implemented on an operation object, and its 3 | /// associated type `Doc` is what the operation should operate on. 4 | pub trait OT 5 | where 6 | Self: Sized, 7 | { 8 | type Doc; 9 | 10 | /// Applies an operation to a `Self::Doc`, returning the modified `Self::Doc`. 11 | fn apply(doc: &Self::Doc, op: &Self) -> Self::Doc; 12 | 13 | /// Returns an empty operation. 14 | fn empty() -> Self; 15 | 16 | /// Composes two operations, returning a single operation encapsulating them 17 | /// both. 18 | fn compose(a: &Self, b: &Self) -> Self; 19 | 20 | /// Composes an iterator of operations into a single operation. 21 | /// If no operations are returned from the iterator, the Op::empty() should be 22 | /// returned. 23 | fn compose_iter<'a, I>(iter: I) -> Self 24 | where 25 | I: Iterator, 26 | Self: 'a; 27 | 28 | /// Transform a document given the corresponding Schema trait. 29 | fn transform(a: &Self, b: &Self) -> (Self, Self); 30 | 31 | /// Utility function to transform an operation against a competing one, 32 | /// returning the results of composing them both. 33 | fn transform_advance(a: &Self, b: &Self) -> Self; 34 | } 35 | -------------------------------------------------------------------------------- /edit-common/tests/transform/633: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("kM5BIp") 7 | ]), 8 | DocGroup({"tag": "pre"}, [ 9 | DocChars("8"), DocGroup({"client": "a", "tag": "caret"}, []), 10 | DocChars("o woat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelWithGroup([]), 19 | DelSkip(6) 20 | ]), 21 | DelWithGroup([ 22 | DelChars(1), DelGroup([]), 23 | DelChars(2) 24 | ]) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddWithGroup([ 29 | AddGroup({"tag": "caret", "client": "a"}, []), 30 | AddWithGroup([]), 31 | AddSkip(6) 32 | ]), 33 | AddWithGroup([ 34 | AddChars("5") 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelWithGroup([ 40 | DelGroup([ 41 | DelGroup([]), 42 | DelChars(4), DelSkip(2) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddGroup({"tag": "h1"}, [ 49 | AddGroup({"tag": "caret", "client": "b"}, []), 50 | AddChars("M "), AddSkip(2) 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/769: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars(" ") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocGroup({"client": "b", "tag": "caret"}, []), 10 | DocChars("lo wlWhat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelGroup([ 18 | DelGroup([]), 19 | DelChars(1), DelSkip(1) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "h3"}, [ 26 | AddChars("A"), AddGroup({"client": "a", "tag": "caret"}, []) 27 | ]), 28 | AddGroup({"tag": "p"}, [ 29 | AddSkip(1) 30 | ]) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelGroup([ 36 | DelWithGroup([ 37 | DelWithGroup([]), 38 | DelSkip(2) 39 | ]), 40 | DelWithGroup([ 41 | DelGroup([]), 42 | DelChars(1) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddWithGroup([]), 49 | AddSkip(2) 50 | ]), 51 | AddWithGroup([ 52 | AddChars(" "), AddGroup({"client": "b", "tag": "caret"}, []) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/163: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("l3el8WW"), DocGroup({"tag": "caret", "client": "a"}, []), 7 | DocChars("hat\'s up with you?") 8 | ]) 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelGroup([ 15 | DelWithGroup([]), 16 | DelSkip(1), DelChars(1), DelSkip(4), DelChars(1), DelGroup([]), 17 | DelChars(1), DelSkip(17) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddGroup({"tag": "h1"}, [ 24 | AddChars("6"), AddWithGroup([]), 25 | AddSkip(1), AddGroup({"tag": "caret", "client": "a"}, []), 26 | AddChars(" "), AddSkip(4), AddChars(" ") 27 | ]), 28 | AddGroup({"tag": "pre"}, [ 29 | AddChars("n "), AddSkip(17) 30 | ]) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelGroup([ 36 | DelWithGroup([ 37 | DelGroup([]), 38 | DelChars(1) 39 | ]) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "bullet"}, [ 44 | AddWithGroup([ 45 | AddChars("2"), AddGroup({"tag": "caret", "client": "b"}, []) 46 | ]) 47 | ]) 48 | ] 49 | -------------------------------------------------------------------------------- /edit-common/tests/transform/142: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocGroup({"client": "b", "tag": "caret"}, []), 7 | DocChars("KK"), DocGroup({"tag": "caret", "client": "c"}, []), 8 | DocChars("TY7FU qf 3r4YqF1H e What\'s up with you?") 9 | ]) 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelWithGroup([ 15 | DelGroup([ 16 | DelGroup([]), 17 | DelWithGroup([]), 18 | DelSkip(1), DelChars(1), DelSkip(40) 19 | ]) 20 | ]) 21 | ] 22 | a_add: [ 23 | AddWithGroup([ 24 | AddGroup({"tag": "h1"}, [ 25 | AddChars("4"), AddGroup({"client": "a", "tag": "caret"}, []), 26 | AddChars(" ") 27 | ]), 28 | AddGroup({"tag": "p"}, [ 29 | AddWithGroup([]), 30 | AddSkip(1), AddChars("f"), AddSkip(40) 31 | ]) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelWithGroup([ 38 | DelWithGroup([]), 39 | DelGroup([]) 40 | ]) 41 | ]) 42 | ] 43 | b_add: [ 44 | AddWithGroup([ 45 | AddGroup({"tag": "caret", "client": "b"}, []), 46 | AddChars("3"), AddWithGroup([]), 47 | AddChars("P") 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-common/tests/transform/265: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("V"), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("flo world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelSkip(1), DelGroup([]), 15 | DelSkip(7), DelChars(3) 16 | ]), 17 | DelGroup([ 18 | DelChars(4), DelSkip(15) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "h2"}, [ 23 | AddSkip(8) 24 | ]), 25 | AddGroup({"tag": "bullet"}, [ 26 | AddGroup({"tag": "p"}, [ 27 | AddChars("C"), AddGroup({"tag": "caret", "client": "a"}, []), 28 | AddSkip(15) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelChars(1), DelWithGroup([]), 36 | DelSkip(3), DelChars(3), DelSkip(2), DelChars(2) 37 | ]), 38 | DelGroup([ 39 | DelSkip(19) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "bullet"}, [ 44 | AddGroup({"tag": "h1"}, [ 45 | AddWithGroup([]), 46 | AddSkip(3), AddChars("5"), AddSkip(1), AddChars("3"), AddSkip(1), AddChars("C"), AddSkip(1), AddGroup({"tag": "caret", "client": "b"}, []), 47 | AddSkip(18) 48 | ]) 49 | ]) 50 | ] 51 | -------------------------------------------------------------------------------- /edit-common/tests/transform/237: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(2), DelSkip(6), DelChars(4) 14 | ]), 15 | DelGroup([ 16 | DelChars(3), DelSkip(16) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h3"}, [ 21 | AddGroup({"client": "a", "tag": "caret"}, []), 22 | AddChars(" "), AddGroup({"client": "b", "tag": "caret"}, []), 23 | AddChars("j"), AddGroup({"client": "c", "tag": "caret"}, []), 24 | AddChars(" ") 25 | ]), 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "h3"}, [ 28 | AddChars(" "), AddSkip(6), AddChars(" 5") 29 | ]), 30 | AddGroup({"tag": "h3"}, [ 31 | AddSkip(16) 32 | ]) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelSkip(12) 39 | ]), 40 | DelGroup([ 41 | DelSkip(19) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "h1"}, [ 47 | AddChars(" "), AddGroup({"tag": "caret", "client": "d"}, []), 48 | AddChars("L"), AddSkip(12), AddChars("0n"), AddSkip(19) 49 | ]) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /edit-common/tests/transform/175: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("haJo world"), DocGroup({"client": "a", "tag": "caret"}, []) 5 | ]), 6 | DocGroup({"tag": "h1"}, [ 7 | DocChars("36Y"), DocGroup({"tag": "caret", "client": "b"}, []), 8 | DocChars("at\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelSkip(6), DelChars(1), DelSkip(2), DelChars(1), DelGroup([]) 15 | ]), 16 | DelGroup([ 17 | DelSkip(21) 18 | ]) 19 | ] 20 | a_add: [ 21 | AddGroup({"tag": "h2"}, [ 22 | AddChars("C 5D"), AddSkip(6) 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "p"}, [ 26 | AddChars("8"), AddGroup({"client": "a", "tag": "caret"}, []), 27 | AddChars("Dl"), AddSkip(23) 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelSkip(9), DelChars(1), DelWithGroup([]) 35 | ]), 36 | DelGroup([ 37 | DelChars(3), DelGroup([]), 38 | DelChars(2), DelSkip(15) 39 | ]) 40 | ] 41 | b_add: [ 42 | AddGroup({"tag": "bullet"}, [ 43 | AddGroup({"tag": "h1"}, [ 44 | AddSkip(9), AddWithGroup([]), 45 | AddChars(" "), AddGroup({"tag": "caret", "client": "b"}, []), 46 | AddSkip(15) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-common/tests/transform/85: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars(" Wnllo world!") 5 | ]), 6 | DocGroup({"tag": "h2"}, [ 7 | DocChars(" "), DocGroup({"tag": "caret", "client": "a"}, []), 8 | DocChars("4t\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(3), DelSkip(1), DelChars(9) 15 | ]), 16 | DelGroup([ 17 | DelChars(1), DelGroup([]), 18 | DelSkip(17) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "p"}, [ 23 | AddChars("IF"), AddSkip(1), AddGroup({"tag": "caret", "client": "a"}, []), 24 | AddChars(" "), AddGroup({"client": "c", "tag": "caret"}, []) 25 | ]), 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "p"}, [ 28 | AddChars("c"), AddGroup({"tag": "caret", "client": "b"}, []), 29 | AddChars(" "), AddSkip(17) 30 | ]) 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelGroup([ 36 | DelChars(1), DelSkip(8), DelChars(4) 37 | ]), 38 | DelGroup([ 39 | DelSkip(19) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddGroup({"tag": "bullet"}, [ 44 | AddGroup({"tag": "pre"}, [ 45 | AddChars("q"), AddSkip(8), AddGroup({"client": "d", "tag": "caret"}, []), 46 | AddChars(" 3"), AddSkip(19) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /edit-common/tests/transform/21: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(2), DelSkip(3), DelChars(1), DelSkip(1), DelChars(2), DelSkip(1), DelChars(2) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h2"}, [ 21 | AddChars("W") 22 | ]), 23 | AddGroup({"tag": "bullet"}, [ 24 | AddGroup({"tag": "pre"}, [ 25 | AddChars("445"), AddSkip(2), AddChars("2"), AddGroup({"tag": "caret", "client": "a"}, []), 26 | AddSkip(3), AddChars("3 "), AddGroup({"tag": "caret", "client": "b"}, []), 27 | AddChars("T "), AddGroup({"tag": "caret", "client": "c"}, []), 28 | AddSkip(18) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelChars(2), DelSkip(10) 36 | ]), 37 | DelGroup([ 38 | DelChars(2), DelSkip(17) 39 | ]) 40 | ] 41 | b_add: [ 42 | AddGroup({"tag": "bullet"}, [ 43 | AddGroup({"tag": "h1"}, [ 44 | AddChars("6 "), AddSkip(10), AddChars("507 "), AddGroup({"tag": "caret", "client": "d"}, []), 45 | AddSkip(17) 46 | ]) 47 | ]) 48 | ] 49 | -------------------------------------------------------------------------------- /edit-common/tests/transform/146: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("M "), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars(" world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(2), DelGroup([]), 15 | DelSkip(1), DelChars(6) 16 | ]), 17 | DelGroup([ 18 | DelChars(1), DelSkip(18) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "bullet"}, [ 23 | AddGroup({"tag": "p"}, [ 24 | AddChars(" Ce") 25 | ]) 26 | ]), 27 | AddGroup({"tag": "bullet"}, [ 28 | AddGroup({"tag": "p"}, [ 29 | AddGroup({"client": "c", "tag": "caret"}, []), 30 | AddChars("7"), AddSkip(1), AddGroup({"client": "b", "tag": "caret"}, []), 31 | AddChars("i") 32 | ]) 33 | ]), 34 | AddGroup({"tag": "h2"}, [ 35 | AddGroup({"client": "a", "tag": "caret"}, []), 36 | AddSkip(18) 37 | ]) 38 | ] 39 | 40 | b_del: [ 41 | DelGroup([ 42 | DelChars(1), DelSkip(9) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddGroup({"tag": "bullet"}, [ 47 | AddGroup({"tag": "h2"}, [ 48 | AddGroup({"client": "d", "tag": "caret"}, []), 49 | AddSkip(9) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/35: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars(" ") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("Hello worldat\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelWithGroup([ 14 | DelGroup([]), 15 | DelSkip(1) 16 | ]), 17 | DelGroup([ 18 | DelChars(2), DelSkip(26) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddChars(" 67"), AddSkip(1) 24 | ]), 25 | AddGroup({"tag": "bullet"}, [ 26 | AddGroup({"tag": "pre"}, [ 27 | AddSkip(1) 28 | ]), 29 | AddGroup({"tag": "p"}, [ 30 | AddChars(" "), AddGroup({"tag": "caret", "client": "a"}, []), 31 | AddSkip(25) 32 | ]) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelWithGroup([]), 39 | DelSkip(1) 40 | ]), 41 | DelGroup([ 42 | DelChars(3), DelSkip(25) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddGroup({"tag": "bullet"}, [ 47 | AddGroup({"tag": "h1"}, [ 48 | AddChars("k"), AddGroup({"tag": "caret", "client": "b"}, []), 49 | AddWithGroup([]), 50 | AddSkip(1), AddChars("2") 51 | ]) 52 | ]), 53 | AddGroup({"tag": "h3"}, [ 54 | AddSkip(25) 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /edit-common/tests/transform/137: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"client": "b", "tag": "caret"}, []), 5 | DocChars("E2 "), DocGroup({"client": "c", "tag": "caret"}, []), 6 | DocChars("Hell "), DocGroup({"tag": "caret", "client": "a"}, []), 7 | DocChars(" 3V4at\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelWithGroup([]), 14 | DelSkip(1), DelChars(3), DelWithGroup([]), 15 | DelSkip(3), DelChars(3), DelGroup([]), 16 | DelChars(1), DelSkip(20) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "h3"}, [ 21 | AddGroup({"client": "a", "tag": "caret"}, []), 22 | AddChars(" ") 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "p"}, [ 26 | AddChars("1Q"), AddWithGroup([]), 27 | AddSkip(1), AddChars("A"), AddWithGroup([]), 28 | AddSkip(3), AddChars(" 2"), AddSkip(20) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelGroup([]), 36 | DelChars(2), DelSkip(31) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h2"}, [ 42 | AddChars("u"), AddGroup({"tag": "caret", "client": "b"}, []), 43 | AddSkip(1), AddChars("f"), AddSkip(30) 44 | ]) 45 | ]) 46 | ] 47 | -------------------------------------------------------------------------------- /edit-common/tests/transform/16: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars("8ello world!") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("What\'s up with you?") 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelGroup([]), 16 | DelWithGroup([]), 17 | DelSkip(1), DelChars(1), DelSkip(8), DelChars(2) 18 | ]), 19 | DelWithGroup([]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "h2"}, [ 23 | AddWithGroup([]), 24 | AddSkip(1), AddChars("SS") 25 | ]), 26 | AddGroup({"tag": "bullet"}, [ 27 | AddGroup({"tag": "p"}, [ 28 | AddChars("W"), AddSkip(8), AddGroup({"tag": "caret", "client": "a"}, []), 29 | AddChars("c") 30 | ]) 31 | ]), 32 | AddWithGroup([ 33 | AddChars(" ") 34 | ]) 35 | ] 36 | 37 | b_del: [ 38 | DelGroup([ 39 | DelWithGroup([]), 40 | DelGroup([]), 41 | DelSkip(1), DelChars(2), DelSkip(9) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "p"}, [ 47 | AddWithGroup([]), 48 | AddSkip(1), AddGroup({"client": "b", "tag": "caret"}, []), 49 | AddSkip(9) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/47: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocGroup({"tag": "caret", "client": "d"}, []), 7 | DocGroup({"client": "c", "tag": "caret"}, []), 8 | DocChars("C 5a"), DocGroup({"client": "b", "tag": "caret"}, []), 9 | DocChars("Cu4 l lo world!hat\'s up with you?") 10 | ]) 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelWithGroup([ 17 | DelGroup([]) 18 | ]) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddWithGroup([ 23 | AddChars("5"), AddGroup({"tag": "caret", "client": "a"}, []), 24 | AddChars("b ") 25 | ]) 26 | ] 27 | 28 | b_del: [ 29 | DelWithGroup([ 30 | DelGroup([ 31 | DelWithGroup([]), 32 | DelWithGroup([]), 33 | DelWithGroup([]), 34 | DelSkip(2), DelChars(2), DelGroup([]), 35 | DelSkip(34) 36 | ]) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddWithGroup([ 41 | AddGroup({"tag": "h2"}, [ 42 | AddWithGroup([]), 43 | AddWithGroup([]), 44 | AddWithGroup([]), 45 | AddSkip(2), AddChars("B"), AddGroup({"client": "b", "tag": "caret"}, []), 46 | AddSkip(34) 47 | ]) 48 | ]) 49 | ] 50 | -------------------------------------------------------------------------------- /oatie/etc/why.rs: -------------------------------------------------------------------------------- 1 | // cargo-deps: quicli = "0.2" maplit="*" ron="*" serde="*" 2 | 3 | #[macro_use] extern crate quicli; 4 | #[macro_use] extern crate maplit; 5 | extern crate ron; 6 | #[macro_use] extern crate serde; 7 | 8 | use quicli::prelude::*; 9 | use ron::ser::to_string; 10 | 11 | // Add cool slogan for your app here, e.g.: 12 | /// Get first n lines of a file 13 | #[derive(Debug, StructOpt)] 14 | struct Cli { 15 | // Add a CLI argument `--count`/-n` that defaults to 3, and has this help text: 16 | // How many lines to get 17 | // #[structopt(long = "count", short = "n", default_value = "3")] 18 | // count: usize, 19 | // // Add a positional argument that the user has to supply: 20 | // /// The file to read 21 | // file: String, 22 | // /// Pass many times for more log output 23 | // #[structopt(long = "verbose", short = "v", parse(from_occurrences))] 24 | // verbosity: u8, 25 | } 26 | 27 | #[derive(Debug, Serialize)] 28 | enum DocElem { 29 | DocGroup(::std::collections::HashMap, Vec), 30 | DocText(String), 31 | } 32 | 33 | main!(|args: Cli| { 34 | println!("hey {:?}", args); 35 | 36 | let d = DocElem::DocGroup(hashmap!{ 37 | "alpha".into() => "beta".into(), 38 | }, vec![DocElem::DocText("hi\ntim".to_string())]); 39 | 40 | println!("ron: {}", to_string(&d).unwrap()); 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /edit-common/tests/transform/396: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("a"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("68o") 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars("kH"), DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars("ellv l!What\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelGroup([ 18 | DelChars(1), DelGroup([]), 19 | DelSkip(3) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "h1"}, [ 26 | AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddSkip(1) 28 | ]), 29 | AddGroup({"tag": "p"}, [ 30 | AddSkip(2) 31 | ]) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelGroup([ 38 | DelSkip(1), DelWithGroup([]), 39 | DelSkip(3) 40 | ]), 41 | DelWithGroup([ 42 | DelChars(2), DelGroup([]) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddGroup({"tag": "h2"}, [ 48 | AddGroup({"client": "b", "tag": "caret"}, []), 49 | AddChars("H"), AddSkip(1), AddWithGroup([]), 50 | AddSkip(3) 51 | ]), 52 | AddWithGroup([]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/455: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "p"}, [ 5 | DocChars("Q"), DocGroup({"tag": "caret", "client": "c"}, []), 6 | DocChars("5") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars("F1"), DocGroup({"tag": "caret", "client": "a"}, []), 11 | DocChars("t\'s up with you?") 12 | ]) 13 | ]) 14 | ] 15 | 16 | a_del: [ 17 | DelGroup([ 18 | DelWithGroup([ 19 | DelSkip(1), DelWithGroup([]), 20 | DelSkip(1) 21 | ]), 22 | DelWithGroup([ 23 | DelGroup([]), 24 | DelSkip(1), DelChars(1), DelGroup([]) 25 | ]) 26 | ]) 27 | ] 28 | a_add: [ 29 | AddWithGroup([ 30 | AddGroup({"tag": "caret", "client": "a"}, []), 31 | AddChars("f"), AddSkip(1), AddWithGroup([]), 32 | AddSkip(1), AddGroup({"client": "b", "tag": "caret"}, []) 33 | ]), 34 | AddWithGroup([ 35 | AddSkip(1), AddChars(" ") 36 | ]) 37 | ] 38 | 39 | b_del: [ 40 | DelWithGroup([ 41 | DelGroup([ 42 | DelChars(1), DelSkip(2) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddGroup({"tag": "h2"}, [ 49 | AddSkip(2) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/501: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "p"}, [ 5 | DocChars("m "), DocGroup({"client": "a", "tag": "caret"}, []) 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("s"), DocGroup({"client": "c", "tag": "caret"}, []), 9 | DocChars("4"), DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars(" 7 wrbtoywl w50X1 up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelWithGroup([ 18 | DelSkip(1), DelChars(2), DelGroup([]) 19 | ]) 20 | ]) 21 | ] 22 | a_add: [ 23 | AddWithGroup([ 24 | AddWithGroup([ 25 | AddSkip(1), AddGroup({"client": "a", "tag": "caret"}, []), 26 | AddChars("j") 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([ 34 | DelSkip(3), DelWithGroup([]) 35 | ]), 36 | DelWithGroup([ 37 | DelSkip(1), DelWithGroup([]), 38 | DelSkip(1), DelGroup([]) 39 | ]) 40 | ]) 41 | ] 42 | b_add: [ 43 | AddWithGroup([ 44 | AddSkip(3), AddWithGroup([]) 45 | ]), 46 | AddWithGroup([ 47 | AddSkip(1), AddGroup({"client": "b", "tag": "caret"}, []), 48 | AddWithGroup([]), 49 | AddSkip(1) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /edit-common/tests/transform/718: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "pre"}, [ 5 | DocChars(" "), DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars(" e") 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars("XdW"), DocGroup({"client": "b", "tag": "caret"}, []), 10 | DocChars("hat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelGroup([ 18 | DelChars(1), DelGroup([]), 19 | DelSkip(3) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "h3"}, [ 26 | AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddChars("e"), AddSkip(3) 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelWithGroup([ 35 | DelSkip(1), DelWithGroup([]), 36 | DelSkip(3) 37 | ]), 38 | DelWithGroup([ 39 | DelSkip(1), DelChars(2), DelGroup([]), 40 | DelChars(1), DelSkip(1) 41 | ]) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddWithGroup([ 46 | AddSkip(1), AddWithGroup([]), 47 | AddSkip(3) 48 | ]), 49 | AddWithGroup([ 50 | AddSkip(1), AddChars(" "), AddSkip(1), AddGroup({"client": "b", "tag": "caret"}, []) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/377: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("5i"), DocGroup({"tag": "caret", "client": "a"}, []) 6 | ]), 7 | DocGroup({"tag": "h2"}, [ 8 | DocGroup({"tag": "caret", "client": "b"}, []), 9 | DocChars("T") 10 | ]), 11 | DocGroup({"tag": "h2"}, [ 12 | DocChars("E prld CWhat\'s up with you?") 13 | ]) 14 | ]) 15 | ] 16 | 17 | a_del: [ 18 | DelWithGroup([ 19 | DelGroup([ 20 | DelChars(1), DelSkip(1), DelGroup([]) 21 | ]), 22 | DelSkip(1) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddWithGroup([ 27 | AddGroup({"tag": "pre"}, [ 28 | AddChars("3"), AddSkip(1) 29 | ]), 30 | AddWithGroup([ 31 | AddGroup({"client": "a", "tag": "caret"}, []) 32 | ]) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelWithGroup([ 38 | DelGroup([ 39 | DelSkip(2), DelWithGroup([]) 40 | ]), 41 | DelGroup([ 42 | DelGroup([]), 43 | DelChars(1) 44 | ]) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddWithGroup([ 49 | AddGroup({"tag": "h2"}, [ 50 | AddSkip(2), AddWithGroup([]), 51 | AddChars("6"), AddGroup({"client": "b", "tag": "caret"}, []) 52 | ]) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-frontend/src/app/proxy.ts: -------------------------------------------------------------------------------- 1 | // Proxy controller. 2 | 3 | import * as route from './route'; 4 | import { ControllerImpl } from '../editor/controller'; 5 | import { ControllerCommand } from '../bindgen/edit_client'; 6 | 7 | declare var CONFIG: any; 8 | 9 | export class ProxyController implements ControllerImpl { 10 | onMessage: (msg: any) => void | null; 11 | onClose: () => void | null; 12 | onError: (error: any) => void | null; 13 | 14 | private socket: WebSocket; 15 | 16 | sendCommand(command: ControllerCommand) { 17 | if (CONFIG.console_command_log) { 18 | console.groupCollapsed('[controller]', command.tag); 19 | console.debug(command); 20 | console.groupEnd(); 21 | } 22 | 23 | this.socket.send(JSON.stringify(command)); 24 | } 25 | 26 | connect(): Promise { 27 | let network = this; 28 | return Promise.resolve() 29 | .then(() => { 30 | this.socket = new WebSocket( 31 | route.clientProxyUrl() 32 | ); 33 | this.socket.onopen = function (event) { 34 | console.debug('client-proxy socket opened.'); 35 | }; 36 | this.socket.onmessage = function (event) { 37 | let parse = JSON.parse(event.data); 38 | if (network.onMessage !== null) { 39 | network.onMessage(parse); 40 | } 41 | }; 42 | this.socket.onclose = network.onClose; 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /edit-common/tests/transform/466: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocChars(" "), DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("pFfFG 7QjF") 7 | ]), 8 | DocGroup({"tag": "h1"}, [ 9 | DocChars("0"), DocGroup({"tag": "caret", "client": "a"}, []), 10 | DocChars("Hello CG What\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelSkip(1), DelWithGroup([]), 19 | DelSkip(10) 20 | ]), 21 | DelWithGroup([ 22 | DelChars(1), DelGroup([]), 23 | DelChars(2) 24 | ]) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddWithGroup([ 29 | AddSkip(1), AddWithGroup([]), 30 | AddSkip(10) 31 | ]), 32 | AddWithGroup([ 33 | AddChars("O"), AddGroup({"tag": "caret", "client": "a"}, []), 34 | AddChars("p") 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelWithGroup([ 40 | DelGroup([ 41 | DelSkip(1), DelGroup([]), 42 | DelSkip(10) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddGroup({"tag": "p"}, [ 49 | AddChars("r"), AddGroup({"tag": "caret", "client": "b"}, []), 50 | AddChars("1"), AddSkip(11) 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/700: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars(" "), DocGroup({"tag": "caret", "client": "c"}, []), 7 | DocChars("B ") 8 | ]), 9 | DocGroup({"tag": "h3"}, [ 10 | DocChars("H"), DocGroup({"client": "d", "tag": "caret"}, []), 11 | DocChars("sVDJ pjG "), DocGroup({"tag": "caret", "client": "a"}, []), 12 | DocChars("Upj X4b Rhat\'s up with you?") 13 | ]) 14 | ]) 15 | ] 16 | 17 | a_del: [ 18 | DelGroup([ 19 | DelWithGroup([ 20 | DelWithGroup([]), 21 | DelSkip(1), DelWithGroup([]), 22 | DelSkip(2) 23 | ]), 24 | DelWithGroup([ 25 | DelSkip(1), DelWithGroup([]), 26 | DelSkip(7), DelChars(2) 27 | ]) 28 | ]) 29 | ] 30 | a_add: [ 31 | AddWithGroup([ 32 | AddWithGroup([]), 33 | AddSkip(1), AddWithGroup([]), 34 | AddSkip(2) 35 | ]), 36 | AddWithGroup([ 37 | AddSkip(1), AddWithGroup([]), 38 | AddSkip(7) 39 | ]) 40 | ] 41 | 42 | b_del: [ 43 | DelWithGroup([ 44 | DelWithGroup([]) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddWithGroup([ 49 | AddWithGroup([ 50 | AddChars(" ") 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/779: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocChars("k MD"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("Y") 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocGroup({"tag": "caret", "client": "b"}, []), 10 | DocChars("r N") 11 | ]), 12 | DocGroup({"tag": "h3"}, [ 13 | DocChars(" U3 b0 worl4 H31hat\'s up with you?") 14 | ]) 15 | ]) 16 | ] 17 | 18 | a_del: [ 19 | DelWithGroup([ 20 | DelGroup([ 21 | DelChars(5), DelGroup([]), 22 | DelChars(1) 23 | ]) 24 | ]) 25 | ] 26 | a_add: [ 27 | AddWithGroup([ 28 | AddGroup({"tag": "pre"}, [ 29 | AddGroup({"client": "a", "tag": "caret"}, []), 30 | AddChars(" I") 31 | ]) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelGroup([ 38 | DelSkip(5), DelWithGroup([]), 39 | DelSkip(1) 40 | ]), 41 | DelWithGroup([ 42 | DelGroup([]) 43 | ]), 44 | DelSkip(1) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddGroup({"tag": "h3"}, [ 49 | AddGroup({"client": "b", "tag": "caret"}, []), 50 | AddChars("3w"), AddSkip(5), AddWithGroup([]), 51 | AddSkip(1) 52 | ]), 53 | AddWithGroup([]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-frontend/templates/client.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 23 | 24 | 25 | 26 | {{id}} | {{title}} 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 | 38 |
39 |
40 |
41 |
{{{body}}}
42 |
43 |
44 |
45 |
46 |
47 | 48 | 49 | 52 | 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/180: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocChars("Hello wo"), DocGroup({"client": "a", "tag": "caret"}, []) 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("4hat\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(4), DelSkip(3), DelChars(1), DelGroup([]) 14 | ]), 15 | DelGroup([ 16 | DelSkip(19) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h2"}, [ 22 | AddGroup({"client": "a", "tag": "caret"}, []) 23 | ]), 24 | AddGroup({"tag": "h2"}, [ 25 | AddGroup({"tag": "caret", "client": "b"}, []), 26 | AddChars("1"), AddSkip(3), AddChars("o") 27 | ]) 28 | ]), 29 | AddGroup({"tag": "bullet"}, [ 30 | AddGroup({"tag": "h2"}, [ 31 | AddChars("L"), AddSkip(19) 32 | ]) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelChars(2), DelSkip(5), DelChars(1), DelWithGroup([]) 39 | ]), 40 | DelGroup([ 41 | DelSkip(19) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "h2"}, [ 47 | AddGroup({"tag": "caret", "client": "c"}, []), 48 | AddChars("60"), AddSkip(5), AddWithGroup([]), 49 | AddChars("Q4"), AddSkip(19) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/118: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "p"}, [ 4 | DocChars("dKL"), DocGroup({"client": "c", "tag": "caret"}, []), 5 | DocChars("804el0"), DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars("Ng4"), DocGroup({"client": "b", "tag": "caret"}, []), 7 | DocChars("at\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelSkip(3), DelWithGroup([]), 14 | DelSkip(4), DelChars(2), DelGroup([]), 15 | DelChars(3), DelGroup([]), 16 | DelChars(1), DelSkip(16) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "pre"}, [ 21 | AddChars("jV"), AddGroup({"client": "a", "tag": "caret"}, []), 22 | AddSkip(3), AddWithGroup([]), 23 | AddSkip(4), AddChars("5Gr") 24 | ]), 25 | AddGroup({"tag": "bullet"}, [ 26 | AddGroup({"tag": "pre"}, [ 27 | AddChars(" "), AddGroup({"tag": "caret", "client": "b"}, []), 28 | AddSkip(16) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelSkip(1), DelChars(2), DelGroup([]), 36 | DelSkip(28) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "h1"}, []), 42 | AddGroup({"tag": "p"}, [ 43 | AddGroup({"tag": "caret", "client": "c"}, []), 44 | AddChars("76"), AddSkip(29) 45 | ]) 46 | ]) 47 | ] 48 | -------------------------------------------------------------------------------- /edit-common/tests/transform/240: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h3"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("Klo world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelGroup([]), 15 | DelSkip(10) 16 | ]), 17 | DelWithGroup([ 18 | DelSkip(1) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "pre"}, [ 23 | AddGroup({"tag": "caret", "client": "c"}, []), 24 | AddChars("F"), AddGroup({"client": "a", "tag": "caret"}, []), 25 | AddChars("Bi U"), AddSkip(2) 26 | ]), 27 | AddGroup({"tag": "bullet"}, [ 28 | AddGroup({"tag": "pre"}, [ 29 | AddSkip(1), AddGroup({"tag": "caret", "client": "b"}, []), 30 | AddSkip(7) 31 | ]) 32 | ]), 33 | AddWithGroup([ 34 | AddSkip(1) 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelGroup([ 40 | DelWithGroup([]), 41 | DelSkip(10) 42 | ]), 43 | DelWithGroup([]) 44 | ] 45 | b_add: [ 46 | AddGroup({"tag": "bullet"}, [ 47 | AddGroup({"tag": "h3"}, [ 48 | AddWithGroup([]), 49 | AddSkip(1), AddChars("b"), AddSkip(9) 50 | ]) 51 | ]), 52 | AddWithGroup([ 53 | AddGroup({"tag": "caret", "client": "d"}, []), 54 | AddChars("S") 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /edit-common/tests/transform/34: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars(" "), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("o"), DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("ello world!") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("What\'s up with you?") 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelChars(1), DelGroup([]), 16 | DelChars(1), DelWithGroup([]), 17 | DelSkip(11) 18 | ]), 19 | DelWithGroup([]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "bullet"}, [ 23 | AddGroup({"tag": "pre"}, [ 24 | AddChars("4 Ai 6"), AddWithGroup([]), 25 | AddSkip(11) 26 | ]) 27 | ]), 28 | AddWithGroup([ 29 | AddGroup({"tag": "caret", "client": "a"}, []), 30 | AddChars("2") 31 | ]) 32 | ] 33 | 34 | b_del: [ 35 | DelGroup([ 36 | DelChars(1), DelWithGroup([]), 37 | DelSkip(1), DelGroup([]), 38 | DelSkip(6), DelChars(1), DelSkip(1), DelChars(3) 39 | ]), 40 | DelGroup([ 41 | DelSkip(19) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "h1"}, [ 47 | AddGroup({"client": "b", "tag": "caret"}, []), 48 | AddChars("m"), AddWithGroup([]), 49 | AddSkip(7), AddChars("8"), AddSkip(20) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/177: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars(" H ello world"), DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocGroup({"client": "c", "tag": "caret"}, []), 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelGroup([]), 14 | DelChars(2), DelSkip(10), DelChars(3), DelGroup([]), 15 | DelSkip(20) 16 | ]) 17 | ] 18 | a_add: [ 19 | AddGroup({"tag": "h3"}, [ 20 | AddGroup({"tag": "caret", "client": "a"}, []), 21 | AddGroup({"tag": "caret", "client": "b"}, []), 22 | AddChars("F") 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "h3"}, [ 26 | AddChars("26"), AddSkip(10), AddChars("5"), AddSkip(20) 27 | ]) 28 | ]) 29 | ] 30 | 31 | b_del: [ 32 | DelGroup([ 33 | DelWithGroup([]), 34 | DelSkip(14), DelChars(1), DelWithGroup([]), 35 | DelGroup([]), 36 | DelSkip(19) 37 | ]) 38 | ] 39 | b_add: [ 40 | AddGroup({"tag": "bullet"}, [ 41 | AddGroup({"tag": "pre"}, [ 42 | AddGroup({"client": "c", "tag": "caret"}, []), 43 | AddChars("8"), AddWithGroup([]), 44 | AddSkip(14), AddChars(" "), AddWithGroup([]), 45 | AddChars("K"), AddSkip(19) 46 | ]) 47 | ]) 48 | ] 49 | -------------------------------------------------------------------------------- /edit-common/tests/transform/549: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars(" "), DocGroup({"tag": "caret", "client": "b"}, []) 6 | ]), 7 | DocGroup({"tag": "h2"}, [ 8 | DocChars("7"), DocGroup({"client": "c", "tag": "caret"}, []), 9 | DocChars("nkHCht2"), DocGroup({"client": "a", "tag": "caret"}, []) 10 | ]) 11 | ]), 12 | DocGroup({"tag": "p"}, [ 13 | DocChars("5 o What\'s up with you?") 14 | ]) 15 | ] 16 | 17 | a_del: [ 18 | DelGroup([ 19 | DelWithGroup([ 20 | DelSkip(1), DelWithGroup([]) 21 | ]), 22 | DelWithGroup([ 23 | DelSkip(1), DelWithGroup([]), 24 | DelSkip(5), DelChars(2), DelGroup([]) 25 | ]) 26 | ]) 27 | ] 28 | a_add: [ 29 | AddWithGroup([ 30 | AddSkip(1), AddWithGroup([]) 31 | ]), 32 | AddWithGroup([ 33 | AddSkip(1), AddWithGroup([]), 34 | AddSkip(5), AddGroup({"tag": "caret", "client": "a"}, []), 35 | AddChars("E") 36 | ]) 37 | ] 38 | 39 | b_del: [ 40 | DelWithGroup([ 41 | DelWithGroup([ 42 | DelChars(1), DelGroup([]) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddWithGroup([ 49 | AddGroup({"client": "b", "tag": "caret"}, []), 50 | AddChars("r") 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/653: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("G1"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("7 "), DocGroup({"client": "b", "tag": "caret"}, []) 7 | ]), 8 | DocGroup({"tag": "h1"}, [ 9 | DocGroup({"client": "c", "tag": "caret"}, []), 10 | DocChars("867 6wErm!What\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelGroup([ 18 | DelChars(2), DelWithGroup([]), 19 | DelSkip(1), DelChars(1), DelGroup([]) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "h2"}, [ 26 | AddGroup({"client": "b", "tag": "caret"}, []), 27 | AddChars("w "), AddWithGroup([]), 28 | AddSkip(1) 29 | ]) 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelGroup([ 35 | DelWithGroup([ 36 | DelSkip(2), DelWithGroup([]), 37 | DelSkip(2), DelWithGroup([]) 38 | ]), 39 | DelWithGroup([ 40 | DelGroup([]) 41 | ]) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddWithGroup([ 46 | AddChars(" "), AddGroup({"client": "c", "tag": "caret"}, []), 47 | AddSkip(2), AddWithGroup([]), 48 | AddSkip(2), AddWithGroup([]) 49 | ]), 50 | AddWithGroup([]) 51 | ] 52 | -------------------------------------------------------------------------------- /edit-frontend/styles/modal.scss: -------------------------------------------------------------------------------- 1 | #modal { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | bottom: 0; 7 | display: flex; 8 | align-content: center; 9 | justify-content: center; 10 | background: rgba(0, 0, 0, 0.4); 11 | z-index: 10000; 12 | flex-direction: column; 13 | cursor: pointer; 14 | 15 | h1 { 16 | font-size: 22px; 17 | margin: 0; 18 | } 19 | } 20 | 21 | #modal-dialog { 22 | width: 50%; 23 | box-shadow: 4px 4px 4px #333; 24 | padding: 10px 20px; 25 | background: white; 26 | border: 1px solid #ddd; 27 | align-self: center; 28 | cursor: auto; 29 | } 30 | 31 | #modal-dialog textarea { 32 | display: block; 33 | width: 100%; 34 | box-sizing: border-box; 35 | min-height: 30em; 36 | margin: 10px 0; 37 | padding: 8px 15px; 38 | border: 1px solid #555; 39 | font-family: 'Courier New', Courier, monospace; 40 | font-size: 14px; 41 | font-weight: 500; 42 | background: #ffe; 43 | } 44 | 45 | #modal-dialog button { 46 | border: 1px solid #999; 47 | cursor: pointer; 48 | 49 | &.load { 50 | background-color: #093; 51 | color: white; 52 | } 53 | } 54 | 55 | .modal-active { 56 | pointer-events: none; 57 | } 58 | 59 | .modal-buttons { 60 | display: flex; 61 | 62 | button { 63 | font-size: 18px; 64 | padding: 5px 10px; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /edit-common/tests/transform/176: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("62"), DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("llo world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(2), DelGroup([]), 15 | DelChars(1), DelSkip(8), DelChars(1) 16 | ]), 17 | DelGroup([ 18 | DelSkip(19) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "h1"}, [ 23 | AddChars("oh "), AddGroup({"client": "b", "tag": "caret"}, []) 24 | ]), 25 | AddGroup({"tag": "bullet"}, [ 26 | AddGroup({"tag": "pre"}, [ 27 | AddChars(" 2"), AddGroup({"tag": "caret", "client": "a"}, []), 28 | AddSkip(8), AddChars(" gC") 29 | ]) 30 | ]), 31 | AddGroup({"tag": "pre"}, [ 32 | AddSkip(19) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelChars(1), DelSkip(1), DelWithGroup([]), 39 | DelSkip(9), DelChars(1) 40 | ]), 41 | DelGroup([ 42 | DelSkip(19) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddGroup({"tag": "bullet"}, [ 47 | AddGroup({"tag": "h2"}, [ 48 | AddChars("11"), AddSkip(1), AddGroup({"tag": "caret", "client": "c"}, []), 49 | AddWithGroup([]), 50 | AddSkip(9), AddChars(" "), AddSkip(19) 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/845: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars("TN"), DocGroup({"client": "a", "tag": "caret"}, []) 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars(" 3") 10 | ]), 11 | DocGroup({"tag": "h2"}, [ 12 | DocChars(" 3nello worldi5A6 at\'s up with you?") 13 | ]) 14 | ]) 15 | ] 16 | 17 | a_del: [ 18 | DelWithGroup([ 19 | DelGroup([ 20 | DelWithGroup([]), 21 | DelSkip(1), DelChars(1), DelGroup([]) 22 | ]) 23 | ]) 24 | ] 25 | a_add: [ 26 | AddWithGroup([ 27 | AddGroup({"tag": "h3"}, [ 28 | AddChars("p"), AddGroup({"client": "a", "tag": "caret"}, []), 29 | AddWithGroup([]), 30 | AddSkip(1) 31 | ]) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelGroup([ 38 | DelGroup([]), 39 | DelChars(2), DelWithGroup([]) 40 | ]), 41 | DelGroup([ 42 | DelSkip(2) 43 | ]), 44 | DelWithGroup([]) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddGroup({"tag": "p"}, [ 49 | AddWithGroup([]), 50 | AddChars("5"), AddSkip(2) 51 | ]), 52 | AddWithGroup([ 53 | AddChars("6"), AddGroup({"tag": "caret", "client": "b"}, []) 54 | ]) 55 | ] 56 | -------------------------------------------------------------------------------- /edit-common/tests/transform/496: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars("X") 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars("3"), DocGroup({"client": "c", "tag": "caret"}, []), 10 | DocChars("j Nb1"), DocGroup({"client": "b", "tag": "caret"}, []), 11 | DocChars("1fc ilo woul 4e t\'s up with you?") 12 | ]) 13 | ]) 14 | ] 15 | 16 | a_del: [ 17 | DelWithGroup([ 18 | DelWithGroup([ 19 | DelGroup([]) 20 | ]) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddWithGroup([ 26 | AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddChars("3") 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelWithGroup([ 35 | DelWithGroup([]), 36 | DelSkip(1) 37 | ]), 38 | DelWithGroup([ 39 | DelSkip(1), DelWithGroup([]), 40 | DelSkip(2), DelChars(3), DelGroup([]), 41 | DelChars(1) 42 | ]) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddWithGroup([ 47 | AddWithGroup([]), 48 | AddSkip(1) 49 | ]), 50 | AddWithGroup([ 51 | AddSkip(1), AddWithGroup([]), 52 | AddSkip(2), AddChars("T2"), AddGroup({"client": "b", "tag": "caret"}, []) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/37: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("V6H"), DocGroup({"client": "c", "tag": "caret"}, []), 6 | DocChars("llo w"), DocGroup({"tag": "caret", "client": "b"}, []), 7 | DocChars("o") 8 | ]), 9 | DocGroup({"tag": "p"}, [ 10 | DocChars("What\'s up with you?") 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelGroup([]), 17 | DelChars(2), DelSkip(9) 18 | ]) 19 | ] 20 | a_add: [ 21 | AddGroup({"tag": "p"}, [ 22 | AddChars("X") 23 | ]), 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "p"}, [ 26 | AddSkip(1), AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddSkip(8) 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelWithGroup([]), 35 | DelSkip(2), DelChars(1), DelWithGroup([]), 36 | DelSkip(1), DelChars(4), DelGroup([]), 37 | DelChars(1) 38 | ]), 39 | DelGroup([ 40 | DelChars(1), DelSkip(18) 41 | ]) 42 | ] 43 | b_add: [ 44 | AddGroup({"tag": "bullet"}, [ 45 | AddGroup({"tag": "h1"}, [ 46 | AddWithGroup([]), 47 | AddSkip(2), AddGroup({"client": "b", "tag": "caret"}, []), 48 | AddChars("J"), AddWithGroup([]), 49 | AddSkip(1), AddChars("0 "), AddSkip(18) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-common/tests/transform/424: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocGroup({"tag": "caret", "client": "c"}, []) 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocChars("u 6E"), DocGroup({"client": "a", "tag": "caret"}, []), 10 | DocChars("k 2q5Y ello wo") 11 | ]) 12 | ]), 13 | DocGroup({"tag": "bullet"}, [ 14 | DocGroup({"tag": "h2"}, [ 15 | DocChars(" at\'s up with you?") 16 | ]) 17 | ]) 18 | ] 19 | 20 | a_del: [ 21 | DelGroup([ 22 | DelWithGroup([ 23 | DelWithGroup([]), 24 | DelWithGroup([]) 25 | ]), 26 | DelWithGroup([ 27 | DelSkip(1), DelChars(3), DelGroup([]), 28 | DelChars(1) 29 | ]) 30 | ]) 31 | ] 32 | a_add: [ 33 | AddWithGroup([ 34 | AddWithGroup([]), 35 | AddWithGroup([]) 36 | ]), 37 | AddWithGroup([ 38 | AddSkip(1), AddGroup({"tag": "caret", "client": "a"}, []), 39 | AddChars("5") 40 | ]) 41 | ] 42 | 43 | b_del: [ 44 | DelWithGroup([ 45 | DelWithGroup([ 46 | DelGroup([]) 47 | ]) 48 | ]) 49 | ] 50 | b_add: [ 51 | AddWithGroup([ 52 | AddWithGroup([ 53 | AddChars("B"), AddGroup({"tag": "caret", "client": "b"}, []) 54 | ]) 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /edit-common/tests/transform/440: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("7U"), DocGroup({"tag": "caret", "client": "b"}, []) 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocChars(" II") 10 | ]), 11 | DocGroup({"tag": "p"}, [ 12 | DocChars("HelM d S") 13 | ]), 14 | DocGroup({"tag": "h2"}, [ 15 | DocChars("4s p with you?") 16 | ]) 17 | ]) 18 | ] 19 | 20 | a_del: [ 21 | DelGroup([ 22 | DelGroup([ 23 | DelGroup([]), 24 | DelChars(2), DelSkip(1) 25 | ]), 26 | DelSkip(3) 27 | ]) 28 | ] 29 | a_add: [ 30 | AddGroup({"tag": "h2"}, [ 31 | AddGroup({"client": "a", "tag": "caret"}, []), 32 | AddSkip(1) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelWithGroup([ 38 | DelWithGroup([ 39 | DelWithGroup([]), 40 | DelSkip(1), DelChars(1), DelGroup([]) 41 | ]), 42 | DelGroup([ 43 | DelChars(3) 44 | ]) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddWithGroup([ 49 | AddWithGroup([ 50 | AddWithGroup([]), 51 | AddSkip(1) 52 | ]), 53 | AddGroup({"tag": "h3"}, [ 54 | AddChars("5k"), AddGroup({"tag": "caret", "client": "b"}, []) 55 | ]) 56 | ]) 57 | ] 58 | -------------------------------------------------------------------------------- /edit-common/tests/transform/826: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocGroup({"tag": "caret", "client": "c"}, []) 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocChars("U "), DocGroup({"tag": "caret", "client": "a"}, []), 10 | DocChars("okyNAr24W4 s3Hat\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelWithGroup([ 18 | DelGroup([]), 19 | DelWithGroup([]) 20 | ]), 21 | DelWithGroup([ 22 | DelSkip(1), DelChars(1), DelGroup([]), 23 | DelChars(1) 24 | ]) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddWithGroup([ 29 | AddGroup({"client": "b", "tag": "caret"}, []), 30 | AddChars("6"), AddGroup({"client": "a", "tag": "caret"}, []), 31 | AddWithGroup([]) 32 | ]), 33 | AddWithGroup([ 34 | AddSkip(1), AddChars("2") 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelWithGroup([ 40 | DelWithGroup([ 41 | DelWithGroup([]), 42 | DelGroup([]) 43 | ]) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddWithGroup([ 48 | AddWithGroup([ 49 | AddWithGroup([]), 50 | AddChars("5F"), AddGroup({"tag": "caret", "client": "c"}, []), 51 | AddChars(" ") 52 | ]) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/801: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocGroup({"client": "b", "tag": "caret"}, []), 6 | DocChars("K") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("T"), DocGroup({"client": "d", "tag": "caret"}, []), 10 | DocChars("IO 0"), DocGroup({"tag": "caret", "client": "a"}, []), 11 | DocChars("884 4 te16llo world!") 12 | ]) 13 | ]), 14 | DocGroup({"tag": "h1"}, [ 15 | DocGroup({"tag": "caret", "client": "e"}, []), 16 | DocChars("4"), DocGroup({"client": "c", "tag": "caret"}, []), 17 | DocChars(" 2hnat\'s up with you?") 18 | ]) 19 | ] 20 | 21 | a_del: [ 22 | DelGroup([ 23 | DelWithGroup([ 24 | DelWithGroup([]), 25 | DelSkip(1) 26 | ]), 27 | DelWithGroup([ 28 | DelSkip(1), DelWithGroup([]), 29 | DelSkip(4), DelGroup([]) 30 | ]) 31 | ]) 32 | ] 33 | a_add: [ 34 | AddWithGroup([ 35 | AddGroup({"tag": "caret", "client": "a"}, []), 36 | AddWithGroup([]), 37 | AddSkip(1) 38 | ]), 39 | AddWithGroup([ 40 | AddSkip(1), AddWithGroup([]), 41 | AddSkip(4) 42 | ]) 43 | ] 44 | 45 | b_del: [ 46 | DelWithGroup([ 47 | DelWithGroup([]) 48 | ]) 49 | ] 50 | b_add: [ 51 | AddWithGroup([ 52 | AddWithGroup([]) 53 | ]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/789: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("3ib"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars(" ") 7 | ]), 8 | DocGroup({"tag": "h1"}, [ 9 | DocChars(" dl "), DocGroup({"client": "d", "tag": "caret"}, []), 10 | DocGroup({"tag": "caret", "client": "c"}, []), 11 | DocChars("Ew5"), DocGroup({"tag": "caret", "client": "b"}, []), 12 | DocChars(" 5H 875 37S63Cg at\'s up with you?") 13 | ]) 14 | ]) 15 | ] 16 | 17 | a_del: [ 18 | DelWithGroup([ 19 | DelWithGroup([ 20 | DelSkip(1), DelChars(2) 21 | ]) 22 | ]) 23 | ] 24 | a_add: [ 25 | AddWithGroup([ 26 | AddWithGroup([ 27 | AddSkip(1), AddChars("2") 28 | ]) 29 | ]) 30 | ] 31 | 32 | b_del: [ 33 | DelGroup([ 34 | DelWithGroup([ 35 | DelSkip(3), DelWithGroup([]), 36 | DelSkip(2) 37 | ]), 38 | DelWithGroup([ 39 | DelSkip(5), DelWithGroup([]), 40 | DelWithGroup([]), 41 | DelSkip(2), DelChars(1) 42 | ]) 43 | ]) 44 | ] 45 | b_add: [ 46 | AddWithGroup([ 47 | AddSkip(3), AddWithGroup([]), 48 | AddSkip(2) 49 | ]), 50 | AddWithGroup([ 51 | AddSkip(5), AddWithGroup([]), 52 | AddWithGroup([]), 53 | AddSkip(2) 54 | ]) 55 | ] 56 | -------------------------------------------------------------------------------- /edit-common/tests/transform/97: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "pre"}, [ 4 | DocChars(" X"), DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars(" world!") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocChars("What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(2), DelGroup([]), 15 | DelSkip(5), DelChars(2) 16 | ]), 17 | DelGroup([ 18 | DelChars(1), DelSkip(18) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "pre"}, [ 23 | AddGroup({"client": "d", "tag": "caret"}, []), 24 | AddChars(" "), AddGroup({"client": "a", "tag": "caret"}, []), 25 | AddChars("vQV2XN "), AddGroup({"tag": "caret", "client": "e"}, []) 26 | ]), 27 | AddGroup({"tag": "bullet"}, [ 28 | AddGroup({"tag": "p"}, [ 29 | AddChars("PY5N"), AddSkip(4), AddGroup({"client": "b", "tag": "caret"}, []), 30 | AddSkip(1), AddChars("W "), AddGroup({"tag": "caret", "client": "c"}, []), 31 | AddChars("n") 32 | ]) 33 | ]), 34 | AddGroup({"tag": "p"}, [ 35 | AddSkip(18) 36 | ]) 37 | ] 38 | 39 | b_del: [ 40 | DelGroup([ 41 | DelChars(1), DelSkip(9) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "h2"}, [ 47 | AddGroup({"tag": "caret", "client": "f"}, []), 48 | AddChars("xK"), AddSkip(9) 49 | ]) 50 | ]) 51 | ] 52 | -------------------------------------------------------------------------------- /edit-common/tests/transform/194: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "b"}, []), 5 | DocChars("7 lW"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("lo w") 7 | ]), 8 | DocGroup({"tag": "p"}, [ 9 | DocChars("What\'s up with you?") 10 | ]) 11 | ] 12 | 13 | a_del: [ 14 | DelGroup([ 15 | DelWithGroup([]), 16 | DelSkip(1), DelChars(4), DelGroup([]), 17 | DelChars(4) 18 | ]), 19 | DelGroup([ 20 | DelChars(2), DelSkip(17) 21 | ]) 22 | ] 23 | a_add: [ 24 | AddGroup({"tag": "bullet"}, [ 25 | AddGroup({"tag": "h1"}, [ 26 | AddWithGroup([]), 27 | AddSkip(1), AddChars("3") 28 | ]) 29 | ]), 30 | AddGroup({"tag": "h1"}, [ 31 | AddGroup({"tag": "caret", "client": "a"}, []), 32 | AddChars("G3"), AddSkip(17) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelGroup([ 38 | DelGroup([]), 39 | DelChars(2), DelSkip(3), DelWithGroup([]), 40 | DelSkip(3), DelChars(1) 41 | ]), 42 | DelWithGroup([]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "pre"}, [ 47 | AddChars("i"), AddGroup({"client": "b", "tag": "caret"}, []), 48 | AddChars("1x"), AddSkip(3), AddWithGroup([]), 49 | AddSkip(3) 50 | ]), 51 | AddGroup({"tag": "p"}, []) 52 | ]), 53 | AddWithGroup([]) 54 | ] 55 | -------------------------------------------------------------------------------- /edit-common/tests/transform/11: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("Hello world!") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelGroup([ 13 | DelChars(3), DelSkip(4), DelChars(5) 14 | ]), 15 | DelGroup([ 16 | DelChars(1), DelSkip(18) 17 | ]) 18 | ] 19 | a_add: [ 20 | AddGroup({"tag": "bullet"}, [ 21 | AddGroup({"tag": "h1"}, [ 22 | AddChars("7"), AddGroup({"client": "b", "tag": "caret"}, []), 23 | AddChars("66"), AddGroup({"tag": "caret", "client": "e"}, []) 24 | ]), 25 | AddGroup({"tag": "h1"}, [ 26 | AddGroup({"tag": "caret", "client": "a"}, []), 27 | AddChars("Aku"), AddSkip(4), AddGroup({"client": "c", "tag": "caret"}, []), 28 | AddChars("Ly 31h6"), AddGroup({"tag": "caret", "client": "d"}, []) 29 | ]) 30 | ]), 31 | AddGroup({"tag": "bullet"}, [ 32 | AddGroup({"tag": "h1"}, [ 33 | AddSkip(18) 34 | ]) 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelGroup([ 40 | DelChars(1), DelSkip(11) 41 | ]), 42 | DelGroup([ 43 | DelSkip(19) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddGroup({"tag": "bullet"}, [ 48 | AddGroup({"tag": "h1"}, [ 49 | AddChars(" "), AddSkip(11), AddGroup({"client": "f", "tag": "caret"}, []), 50 | AddSkip(19) 51 | ]) 52 | ]) 53 | ] 54 | -------------------------------------------------------------------------------- /edit-common/tests/transform/791: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"client": "a", "tag": "caret"}, []), 6 | DocChars("K5J") 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocChars("V") 10 | ]) 11 | ]), 12 | DocGroup({"tag": "p"}, [ 13 | DocGroup({"client": "b", "tag": "caret"}, []), 14 | DocChars(" q 121jb4o up with you?") 15 | ]) 16 | ] 17 | 18 | a_del: [ 19 | DelGroup([ 20 | DelGroup([ 21 | DelGroup([]), 22 | DelChars(1), DelSkip(1), DelChars(1) 23 | ]), 24 | DelSkip(1) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddGroup({"tag": "h3"}, [ 29 | AddSkip(1), AddChars("3 ") 30 | ]), 31 | AddWithGroup([ 32 | AddGroup({"client": "a", "tag": "caret"}, []) 33 | ]) 34 | ] 35 | 36 | b_del: [ 37 | DelWithGroup([ 38 | DelGroup([ 39 | DelWithGroup([]), 40 | DelSkip(1), DelChars(2) 41 | ]), 42 | DelGroup([ 43 | DelChars(1) 44 | ]) 45 | ]), 46 | DelWithGroup([ 47 | DelGroup([]) 48 | ]) 49 | ] 50 | b_add: [ 51 | AddWithGroup([ 52 | AddGroup({"tag": "h3"}, []), 53 | AddGroup({"tag": "p"}, [ 54 | AddWithGroup([]), 55 | AddSkip(1) 56 | ]) 57 | ]), 58 | AddWithGroup([ 59 | AddGroup({"tag": "caret", "client": "b"}, []) 60 | ]) 61 | ] 62 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-50: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h2"}, [ 5 | DocChars("1"), 6 | ]), 7 | DocGroup({"tag": "h2"}, [ 8 | DocChars("1"), 9 | ]), 10 | ]), 11 | ] 12 | 13 | a_del: [ 14 | DelWithGroup([ 15 | DelGroup([ 16 | DelSkip(1), 17 | ]), 18 | DelWithGroup([ 19 | DelSkip(1), 20 | ]), 21 | ]), 22 | ] 23 | a_add: [ 24 | AddWithGroup([ 25 | AddGroup({"tag": "pre"}, [ 26 | AddChars("L"), AddGroup({"tag": "caret", "client": "e"}, []), 27 | AddChars(" "), AddSkip(1), AddGroup({"tag": "caret", "client": "d"}, []), 28 | AddChars(" "), AddGroup({"client": "c", "tag": "caret"}, []), 29 | AddGroup({"client": "f", "tag": "caret"}, []), 30 | ]), 31 | AddWithGroup([ 32 | AddGroup({"client": "a", "tag": "caret"}, []), 33 | AddSkip(1), 34 | ]), 35 | ]), 36 | ] 37 | 38 | b_del: [ 39 | DelWithGroup([ 40 | DelWithGroup([ 41 | DelSkip(1), 42 | ]), 43 | DelGroup([ 44 | DelChars(1) 45 | ]) 46 | ]) 47 | ] 48 | b_add: [ 49 | AddWithGroup([ 50 | AddWithGroup([ 51 | AddSkip(1), 52 | ]), 53 | AddGroup({"tag": "h2"}, [ 54 | AddChars(" "), 55 | AddGroup({"tag": "caret", "client": "h"}, []) 56 | ]) 57 | ]) 58 | ] 59 | -------------------------------------------------------------------------------- /edit-common/tests/transform/212: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("0") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocGroup({"client": "a", "tag": "caret"}, []), 8 | DocChars("8ello world!") 9 | ]), 10 | DocGroup({"tag": "p"}, [ 11 | DocChars("What\'s up with you?") 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelWithGroup([ 17 | DelSkip(1) 18 | ]), 19 | DelGroup([ 20 | DelGroup([]), 21 | DelSkip(8), DelChars(2), DelSkip(1), DelChars(1) 22 | ]), 23 | DelGroup([ 24 | DelSkip(19) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddWithGroup([ 29 | AddGroup({"client": "a", "tag": "caret"}, []), 30 | AddSkip(1) 31 | ]), 32 | AddGroup({"tag": "bullet"}, [ 33 | AddGroup({"tag": "pre"}, [ 34 | AddSkip(8), AddChars("I"), AddSkip(1), AddChars("Y"), AddSkip(19) 35 | ]) 36 | ]) 37 | ] 38 | 39 | b_del: [ 40 | DelGroup([ 41 | DelSkip(1) 42 | ]), 43 | DelGroup([ 44 | DelWithGroup([]), 45 | DelSkip(12) 46 | ]), 47 | DelGroup([ 48 | DelSkip(19) 49 | ]) 50 | ] 51 | b_add: [ 52 | AddGroup({"tag": "bullet"}, [ 53 | AddGroup({"tag": "h1"}, [ 54 | AddGroup({"tag": "caret", "client": "b"}, []), 55 | AddChars("8 "), AddSkip(1), AddChars("W"), AddWithGroup([]), 56 | AddSkip(1), AddChars("2"), AddSkip(11), AddChars(" "), AddSkip(19) 57 | ]) 58 | ]) 59 | ] 60 | -------------------------------------------------------------------------------- /edit-common/tests/transform/223: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "p"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("7fkin h c3 Dworl") 6 | ]), 7 | DocGroup({"tag": "h3"}, [ 8 | DocGroup({"tag": "caret", "client": "b"}, []), 9 | DocChars("W"), DocGroup({"client": "c", "tag": "caret"}, []), 10 | DocChars("hat\'s up with you?") 11 | ]) 12 | ] 13 | 14 | a_del: [ 15 | DelGroup([ 16 | DelGroup([]), 17 | DelChars(1), DelSkip(15) 18 | ]), 19 | DelWithGroup([]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "p"}, [ 23 | AddChars("6"), AddGroup({"tag": "caret", "client": "a"}, []) 24 | ]), 25 | AddGroup({"tag": "p"}, [ 26 | AddChars(" o5"), AddSkip(15) 27 | ]), 28 | AddWithGroup([ 29 | AddChars("6") 30 | ]) 31 | ] 32 | 33 | b_del: [ 34 | DelWithGroup([ 35 | DelWithGroup([]), 36 | DelSkip(16) 37 | ]), 38 | DelGroup([ 39 | DelGroup([]), 40 | DelChars(1), DelWithGroup([]), 41 | DelSkip(1), DelChars(1), DelSkip(16) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddWithGroup([ 47 | AddChars("s"), AddWithGroup([]), 48 | AddSkip(16) 49 | ]) 50 | ]), 51 | AddGroup({"tag": "h1"}, [ 52 | AddGroup({"tag": "caret", "client": "b"}, []), 53 | AddChars("0 "), AddWithGroup([]), 54 | AddSkip(1), AddChars("I"), AddSkip(16) 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /edit-common/tests/transform/484: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars("V"), DocGroup({"tag": "caret", "client": "a"}, []), 7 | DocChars(" ") 8 | ]), 9 | DocGroup({"tag": "h3"}, [ 10 | DocChars("6") 11 | ]), 12 | DocGroup({"tag": "h3"}, [ 13 | DocChars("778f6ello wo1What\'s up with you?") 14 | ]) 15 | ]) 16 | ] 17 | 18 | a_del: [ 19 | DelGroup([ 20 | DelGroup([ 21 | DelWithGroup([]), 22 | DelSkip(1), DelGroup([]), 23 | DelChars(2) 24 | ]), 25 | DelSkip(2) 26 | ]) 27 | ] 28 | a_add: [ 29 | AddGroup({"tag": "h3"}, [ 30 | AddWithGroup([]), 31 | AddSkip(1), AddChars("W"), AddGroup({"client": "a", "tag": "caret"}, []) 32 | ]) 33 | ] 34 | 35 | b_del: [ 36 | DelGroup([ 37 | DelGroup([ 38 | DelGroup([]), 39 | DelSkip(1), DelWithGroup([]), 40 | DelSkip(1), DelChars(1) 41 | ]), 42 | DelGroup([ 43 | DelChars(1) 44 | ]), 45 | DelGroup([ 46 | DelChars(1), DelSkip(31) 47 | ]) 48 | ]) 49 | ] 50 | b_add: [ 51 | AddGroup({"tag": "h3"}, [ 52 | AddSkip(1), AddWithGroup([]), 53 | AddSkip(1), AddChars("y"), AddGroup({"client": "b", "tag": "caret"}, []), 54 | AddSkip(31) 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /oatie/tests/transform/caret-28: -------------------------------------------------------------------------------- 1 | doc: [ 2 | DocGroup({"tag": "p"}, [ 3 | DocChars(" Pxlovx 8"), DocGroup({"tag": "caret", "client": "right"}, []), 4 | DocChars(" 51N2 3gF4pl sPB00Qa e4v b6 c iI6Ic750 IeP I1 R k450ou5ki1 Sj1 P0 xkcEq2gNtTR m7m7hP58a4 frP 10jH U2No0G 0A 63O1766 2 2 56e4eA 65 y KIuY1UWD 5J1 FVh k 4 eDl1idAg7ftNV 4 4 R3oM58 TXs LCLq b4SVq Ld 1") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars(" KY34 0fUK V K27gpxr7 4 Cmc7xR hek r y5 e M7 4nk5jyu017n 3CwX4qR7Pkt 0jJR cc1 7aq 2 c1 xeqC t67 213go7Y 7 8i572hf PB04 oX8DE8Nha 0 Qni c5 rb cRTFt Laq6AC JE7 382 iREQvDLNoU15Wg 7 g6Nr BP 7m087y7 v7e 8 6B g1uLq84 wN5 cjqt5 40 j s6 k l3wU37MfQ5 Qgrw k27 p73 c4W ao8pFfK 3mlP qg uP8 KsGr 7am4Fasl2 G ICi7L7T7 ojN4dhg 84RWA b 4 w0U7 7BWq5 5y A84 D veI 672 o6u1eYB fie6S46 O2804 pUA j71Gm 0KBUatV TTpxvv 6 8 4 s b 6 S QnR4XQS1 V u rJF M6u6Av m L Ys 7eny4q us0u c V H em7llo world Sv xm HG5NA7Yp 0ITK 6Vc y 8xJ5What\'s up with you?") 8 | ]) 9 | ] 10 | 11 | a_del: [ 12 | DelSkip(1) 13 | ] 14 | a_add: [ 15 | AddWithGroup([ 16 | AddGroup({"tag": "caret", "client": "left"}, []) 17 | ]) 18 | ] 19 | 20 | b_del: [ 21 | DelGroup([ 22 | DelSkip(6), DelChars(3), DelGroup([]), 23 | DelChars(1), DelSkip(204) 24 | ]) 25 | ] 26 | b_add: [ 27 | AddGroup({"tag": "h2"}, [ 28 | AddSkip(6), AddChars("m"), AddGroup({"client": "right", "tag": "caret"}, []), 29 | AddSkip(204) 30 | ]) 31 | ] -------------------------------------------------------------------------------- /edit-common/tests/transform/26: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("ello world!") 6 | ]), 7 | DocGroup({"tag": "pre"}, [ 8 | DocChars("p t\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelGroup([]), 15 | DelChars(1), DelSkip(2), DelChars(1), DelSkip(2), DelChars(5) 16 | ]), 17 | DelGroup([ 18 | DelChars(2), DelSkip(16) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "h1"}, [ 23 | AddGroup({"client": "d", "tag": "caret"}, []), 24 | AddChars(" "), AddGroup({"tag": "caret", "client": "b"}, []), 25 | AddChars("5 o") 26 | ]), 27 | AddGroup({"tag": "bullet"}, [ 28 | AddGroup({"tag": "h1"}, [ 29 | AddChars("g "), AddSkip(1), AddChars("5bCA"), AddSkip(1), AddGroup({"client": "a", "tag": "caret"}, []), 30 | AddSkip(2), AddChars("m"), AddGroup({"tag": "caret", "client": "c"}, []) 31 | ]) 32 | ]), 33 | AddGroup({"tag": "h1"}, [ 34 | AddSkip(16) 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelGroup([ 40 | DelWithGroup([]), 41 | DelSkip(1), DelChars(1), DelSkip(9) 42 | ]) 43 | ] 44 | b_add: [ 45 | AddGroup({"tag": "bullet"}, [ 46 | AddGroup({"tag": "h1"}, [ 47 | AddChars("n"), AddGroup({"tag": "caret", "client": "e"}, []), 48 | AddWithGroup([]), 49 | AddSkip(10) 50 | ]) 51 | ]) 52 | ] 53 | -------------------------------------------------------------------------------- /edit-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Tim Ryan "] 3 | name = "edit-server" 4 | version = "0.1.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | colored = "1.6.0" 9 | crossbeam-channel = "0.2" 10 | rust-crypto = "^0.2" 11 | dotenv = "^0.13" 12 | env_logger = "0.4.3" 13 | failure = "0.1" 14 | handlebars = "0.32.0" 15 | juniper = "0.9.2" 16 | lazy_static = "1.0.0" 17 | maplit = "1.0.0" 18 | md5 = "0.3.7" 19 | mime_guess = "1.8.4" 20 | pulldown-cmark = "0.1.2" 21 | pulldown-cmark-to-cmark = "1.1.0" 22 | quicli = "0.4" 23 | r2d2 = "0.8.2" 24 | r2d2-diesel = "1.0.0" 25 | open = "1.2.2" 26 | rand = "0.4" 27 | regex = "1" 28 | reqwest = "0.8.5" 29 | ron = "0.4" 30 | libsqlite3-sys = { version = "*", features = ["bundled"] } 31 | serde = "1.0.27" 32 | serde_derive = "1.0.27" 33 | serde_json = "1.0.6" 34 | structopt = "0.2.3" 35 | structopt-derive = "0.2.3" 36 | take_mut = "0.2.0" 37 | taken = "0.1.1" 38 | url = "1.6.0" 39 | ws = "0.7.3" 40 | yansi = "0.5" 41 | 42 | [dependencies.diesel] 43 | features = ["sqlite"] 44 | version = "1.3" 45 | 46 | [dependencies.include-dir-macro] 47 | git = "https://github.com/jcdyer/include-dir-macro" 48 | 49 | [dependencies.edit-common] 50 | path = "../edit-common" 51 | 52 | [dependencies.oatie] 53 | path = "../oatie" 54 | 55 | [dependencies.rouille] 56 | default-features = false 57 | features = [] 58 | version = "2.1.0" 59 | 60 | [dependencies.uuid] 61 | features = ["v4"] 62 | version = "0.5" 63 | 64 | [features] 65 | standalone = [] 66 | console_command_log = [] 67 | -------------------------------------------------------------------------------- /edit-common/tests/transform/140: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocGroup({"tag": "caret", "client": "a"}, []), 5 | DocChars("mM") 6 | ]), 7 | DocGroup({"tag": "p"}, [ 8 | DocGroup({"client": "b", "tag": "caret"}, []) 9 | ]), 10 | DocGroup({"tag": "p"}, [ 11 | DocChars("cGHello world!rWhat\'s up with you?") 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelGroup([]), 18 | DelChars(1), DelSkip(1) 19 | ]), 20 | DelGroup([ 21 | DelWithGroup([]) 22 | ]), 23 | DelGroup([ 24 | DelChars(1), DelSkip(33) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddGroup({"tag": "h3"}, [ 29 | AddChars("r"), AddSkip(1) 30 | ]), 31 | AddGroup({"tag": "bullet"}, [ 32 | AddGroup({"tag": "p"}, [ 33 | AddChars("s"), AddWithGroup([]), 34 | AddChars("s"), AddGroup({"tag": "caret", "client": "a"}, []), 35 | AddSkip(33) 36 | ]) 37 | ]) 38 | ] 39 | 40 | b_del: [ 41 | DelGroup([ 42 | DelWithGroup([]), 43 | DelSkip(2) 44 | ]), 45 | DelGroup([ 46 | DelGroup([]) 47 | ]), 48 | DelGroup([ 49 | DelSkip(34) 50 | ]) 51 | ] 52 | b_add: [ 53 | AddGroup({"tag": "bullet"}, [ 54 | AddGroup({"tag": "pre"}, [ 55 | AddChars(" "), AddGroup({"client": "b", "tag": "caret"}, []), 56 | AddWithGroup([]), 57 | AddSkip(2), AddChars(" "), AddSkip(34) 58 | ]) 59 | ]) 60 | ] 61 | -------------------------------------------------------------------------------- /edit-common/tests/transform/408: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h3"}, [ 5 | DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocGroup({"tag": "caret", "client": "c"}, []) 7 | ]), 8 | DocGroup({"tag": "h1"}, [ 9 | DocChars("71p54"), DocGroup({"tag": "caret", "client": "b"}, []) 10 | ]), 11 | DocGroup({"tag": "h1"}, [ 12 | DocChars(" wco ") 13 | ]) 14 | ]), 15 | DocGroup({"tag": "p"}, [ 16 | DocChars("x8 5ello worIhat\'s up with you?") 17 | ]) 18 | ] 19 | 20 | a_del: [ 21 | DelWithGroup([ 22 | DelGroup([ 23 | DelGroup([]), 24 | DelSkip(1) 25 | ]) 26 | ]) 27 | ] 28 | a_add: [ 29 | AddWithGroup([ 30 | AddGroup({"tag": "h3"}, [ 31 | AddGroup({"tag": "caret", "client": "a"}, []), 32 | AddChars("D "), AddSkip(1) 33 | ]) 34 | ]) 35 | ] 36 | 37 | b_del: [ 38 | DelGroup([ 39 | DelGroup([ 40 | DelWithGroup([]), 41 | DelWithGroup([]) 42 | ]), 43 | DelWithGroup([ 44 | DelSkip(4), DelChars(1), DelGroup([]) 45 | ]), 46 | DelSkip(1) 47 | ]) 48 | ] 49 | b_add: [ 50 | AddGroup({"tag": "h2"}, [ 51 | AddGroup({"tag": "caret", "client": "b"}, []), 52 | AddChars("2"), AddWithGroup([]), 53 | AddWithGroup([]) 54 | ]), 55 | AddWithGroup([ 56 | AddSkip(4) 57 | ]) 58 | ] 59 | -------------------------------------------------------------------------------- /edit-common/tests/transform/210: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h2"}, [ 4 | DocGroup({"client": "a", "tag": "caret"}, []), 5 | DocChars("e"), DocGroup({"tag": "caret", "client": "b"}, []), 6 | DocChars(" y") 7 | ]), 8 | DocGroup({"tag": "h2"}, [ 9 | DocChars("llo wgo 5") 10 | ]), 11 | DocGroup({"tag": "h2"}, [ 12 | DocChars("hat\'s up with you?") 13 | ]) 14 | ] 15 | 16 | a_del: [ 17 | DelWithGroup([ 18 | DelGroup([]), 19 | DelChars(1), DelWithGroup([]), 20 | DelSkip(2) 21 | ]), 22 | DelGroup([ 23 | DelSkip(4), DelChars(2), DelSkip(1), DelChars(2) 24 | ]), 25 | DelWithGroup([]) 26 | ] 27 | a_add: [ 28 | AddGroup({"tag": "bullet"}, [ 29 | AddWithGroup([ 30 | AddWithGroup([]), 31 | AddSkip(1), AddChars("1"), AddSkip(1) 32 | ]) 33 | ]), 34 | AddGroup({"tag": "h3"}, [ 35 | AddChars("2"), AddSkip(4), AddChars("p"), AddSkip(1), AddGroup({"client": "a", "tag": "caret"}, []) 36 | ]), 37 | AddWithGroup([]) 38 | ] 39 | 40 | b_del: [ 41 | DelGroup([ 42 | DelWithGroup([]), 43 | DelSkip(1), DelGroup([]), 44 | DelChars(2) 45 | ]) 46 | ] 47 | b_add: [ 48 | AddGroup({"tag": "bullet"}, [ 49 | AddGroup({"tag": "h2"}, [ 50 | AddChars("q"), AddWithGroup([]), 51 | AddSkip(1), AddChars(" 8"), AddGroup({"client": "b", "tag": "caret"}, []), 52 | AddChars("8") 53 | ]) 54 | ]) 55 | ] 56 | -------------------------------------------------------------------------------- /edit-common/tests/transform/171: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "h1"}, [ 4 | DocChars("p bllo wov") 5 | ]), 6 | DocGroup({"tag": "p"}, [ 7 | DocChars("Pg"), DocGroup({"client": "a", "tag": "caret"}, []), 8 | DocChars("4What\'s up with you?") 9 | ]) 10 | ] 11 | 12 | a_del: [ 13 | DelGroup([ 14 | DelChars(2), DelSkip(4), DelChars(4) 15 | ]), 16 | DelGroup([ 17 | DelChars(2), DelGroup([]), 18 | DelChars(3), DelSkip(17) 19 | ]) 20 | ] 21 | a_add: [ 22 | AddGroup({"tag": "bullet"}, [ 23 | AddGroup({"tag": "h1"}, [ 24 | AddGroup({"tag": "caret", "client": "b"}, []), 25 | AddChars("N ua") 26 | ]), 27 | AddGroup({"tag": "h2"}, [ 28 | AddSkip(4), AddChars("k25 "), AddGroup({"tag": "caret", "client": "d"}, []) 29 | ]), 30 | AddGroup({"tag": "h2"}, [ 31 | AddGroup({"client": "a", "tag": "caret"}, []), 32 | AddChars(" "), AddGroup({"client": "c", "tag": "caret"}, []), 33 | AddSkip(17) 34 | ]) 35 | ]) 36 | ] 37 | 38 | b_del: [ 39 | DelGroup([ 40 | DelChars(3), DelSkip(7) 41 | ]), 42 | DelGroup([ 43 | DelSkip(23) 44 | ]) 45 | ] 46 | b_add: [ 47 | AddGroup({"tag": "bullet"}, [ 48 | AddGroup({"tag": "pre"}, [ 49 | AddSkip(7) 50 | ]) 51 | ]), 52 | AddGroup({"tag": "p"}, [ 53 | AddGroup({"tag": "caret", "client": "e"}, []), 54 | AddSkip(23) 55 | ]) 56 | ] 57 | -------------------------------------------------------------------------------- /edit-common/tests/transform/828: -------------------------------------------------------------------------------- 1 | 2 | doc: [ 3 | DocGroup({"tag": "bullet"}, [ 4 | DocGroup({"tag": "h1"}, [ 5 | DocChars("2"), DocGroup({"tag": "caret", "client": "a"}, []), 6 | DocChars("0"), DocGroup({"client": "c", "tag": "caret"}, []) 7 | ]), 8 | DocGroup({"tag": "h3"}, [ 9 | DocGroup({"client": "b", "tag": "caret"}, []), 10 | DocChars("dello world1What\'s up with you?") 11 | ]) 12 | ]) 13 | ] 14 | 15 | a_del: [ 16 | DelGroup([ 17 | DelGroup([ 18 | DelChars(1), DelGroup([]), 19 | DelSkip(1), DelGroup([]) 20 | ]), 21 | DelWithGroup([ 22 | DelGroup([]), 23 | DelChars(1) 24 | ]) 25 | ]) 26 | ] 27 | a_add: [ 28 | AddGroup({"tag": "h1"}, [ 29 | AddGroup({"client": "a", "tag": "caret"}, []), 30 | AddGroup({"tag": "caret", "client": "d"}, []), 31 | AddChars("NC") 32 | ]), 33 | AddGroup({"tag": "h1"}, [ 34 | AddChars(" P"), AddSkip(1), AddGroup({"tag": "caret", "client": "c"}, []) 35 | ]), 36 | AddWithGroup([ 37 | AddGroup({"tag": "caret", "client": "b"}, []) 38 | ]) 39 | ] 40 | 41 | b_del: [ 42 | DelWithGroup([ 43 | DelGroup([ 44 | DelSkip(4) 45 | ]) 46 | ]) 47 | ] 48 | b_add: [ 49 | AddWithGroup([ 50 | AddGroup({"tag": "h1"}, [ 51 | AddGroup({"client": "e", "tag": "caret"}, []), 52 | AddSkip(4) 53 | ]) 54 | ]) 55 | ] 56 | --------------------------------------------------------------------------------