{"id":19569026,"url":"https://github.com/d6y/wootjs","last_synced_at":"2025-04-27T03:30:37.080Z","repository":{"id":30447668,"uuid":"34001219","full_name":"d6y/wootjs","owner":"d6y","description":"WOOT model for Scala and JavaScript via Scala.js","archived":false,"fork":false,"pushed_at":"2016-07-03T13:50:25.000Z","size":7283,"stargazers_count":104,"open_issues_count":0,"forks_count":8,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-04T20:25:16.924Z","etag":null,"topics":["crdt","scala"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d6y.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-15T15:11:30.000Z","updated_at":"2023-03-07T04:46:00.000Z","dependencies_parsed_at":"2022-07-28T01:49:29.109Z","dependency_job_id":null,"html_url":"https://github.com/d6y/wootjs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d6y%2Fwootjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d6y%2Fwootjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d6y%2Fwootjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d6y%2Fwootjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d6y","download_url":"https://codeload.github.com/d6y/wootjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251085147,"owners_count":21533821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crdt","scala"],"created_at":"2024-11-11T06:07:20.228Z","updated_at":"2025-04-27T03:30:36.268Z","avatar_url":"https://github.com/d6y.png","language":"JavaScript","readme":"[![Build Status](https://travis-ci.org/d6y/wootjs.svg?branch=master)](https://travis-ci.org/d6y/wootjs)\n\n# WOOT with Scala.js\n\n* Collaborative text editing, using the WOOT algorithm.\n* Implemented in Scala, running on both the JVM and a JavaScript interpreter.\n\n## For the Impatient\n\n    $ sbt server/run\n\nThen open _http://127.0.0.1:8080/_ to edit a document.\n\nOpen another browser at the same address, and you'll get the idea of collaboration.\n\n## What is WOOT?\n\nWOOT is a collaborative text editing algorithm, allowing multiple users (\"sites\") to insert or delete characters (`WChar`) from a shared document (`WString`). The algorithm preserves the intention of users, and ensures that the text converges to the same state for all users.\n\nIts key properties are simplicity, and avoiding the need for a reliable network or vector clocks (it can be peer-to-peer).\n\nThe key references are:\n\n* Oster _et al._ (2005) _Real time group editors without Operational transformation_, report paper 5580, INRIA - [PDF](http://www.loria.fr/~oster/pmwiki/pub/papers/OsterRR05a.pdf)\n\n* Oster _et al._ (2006) _Data Consistency for P2P Collaborative Editing_, CSCW'06 - [PDF](http://hal.archives-ouvertes.fr/docs/00/10/85/23/PDF/OsterCSCW06.pdf)\n\nWOOT stands for With Out [Operational Transforms](https://en.wikipedia.org/wiki/Operational_transform).\n\n## Presentations\n\nI've spoken about this project at Scala Days 2015: [there's video](https://www.parleys.com/tutorial/towards-browser-server-utopia-scala-js-example-using-crdts) and also [the slides](https://speakerdeck.com/d6y/towards-browser-and-server-utopia-with-scala-dot-js-an-example-using-crdts).\n\n\n## This Project\n\nThis project contains a Scala implementation of WOOT. It has been compiled to JavaScript using Scala.js.\nIn other words, this is an example of sharing one implementation (the WOOT model) in both a JavaScript and Scala context.\n\nWOOT is only the algorithm for text consistency.\nYou need to bring your own editor and network layer.\n\nThis example includes the [ACE](http://ace.c9.io/) editor, which is wired up to the\nScala.js implementation of WOOT locally within the browser.\nUpdates are sent over a web socket to a http4s server which also maintains a copy of the model, but on the JVM.\n\n![Screen Shot of Editor being Used](docs/poem.png)\n\n## Performance\n\nThis is a simple implementation that is slow for bulk actions (e.g., paste and cut).\n\nTo improve performance you will want to:\n\n- measure what's slow for your scenarios\n- batch messages between client and server (maybe)\n- optimize the `trim`, `canIntegrate`, and `indexOf` methods.\n\nI may get round to doing this at some point!\n\n## What Happens When You Run the Web Server\n\nRunning the sever code will likely produce:\n\n```\n$ sbt \"project server\" run\n[info] Loading global plugins from ...\n[info] Loading project definition from wootjs/project/project\n[info] Loading project definition from wootjs/project\n[info] Set current project to woot\n[info] Set current project to woot-server\n[info] Fast optimizing wootjs/client/target/scala-2.11/woot-client-fastopt.js\n[info] Running Main\n2015-04-08 13:43:52 [run-main-0] INFO  WootServer - Starting Http4s-blaze WootServer on '0.0.0.0:8080'\n...\n```\n\nNotice that the Scala.js compiler has run on the _woot-client_ project, to convert the client Scala code into JavaScript.  This JavaScript, _woot-client-fastopt.js_, is made available on the classpath of the server, so it can be included on the web page.  The web page is _server/src/main/resources/index.html_.\n\nThis reflects the structure of the project:\n\n* _client_ - Scala source code, to be compiled to JavaScript.\n* _server_ - Scala source code to run server-side, plus other assets to be served, such as HTML, CSS and plain old JavaScript.\n* _wootModel_ - Scala source code shared by both the client and server projects. This is the WOOT algorithm, implemented once, used in the JVM and the JavaScript runtime.\n\n\n## Exploring the Code\n\n1. _server/src/main/resources/index.html_ is the starting point for the client. This folder also contains a trivial websocket JavaScript client (_ws.js_) and the editor bindings (_editor.js_).\n2. _editor.js_ creates a local instance of the \"woot client\" and kicks off the web socket interactions.\n3. _client/src/main/scala/client/WootClient.scala_ is the exposed interface to the WOOT model.  This is Scala compiled to JavaScript.\n4.  _server/src/main/scala/main.scala_ is the server that accepts and broadcasts WOOT operations to clients.\n\n\n## Tests\n\nThe tests for this project are implemented as [ScalaCheck](http://www.scalacheck.org/) properties.\n\n### Running the tests in the JVM\n\n    sbt\u003e project wootModelJVM\n    sbt\u003e coverage\n    sbt\u003e test\n\nThen open _wootModel/jvm/target/scala-2.11/scoverage-report/index.html_\n\n## Publishing Woot Model\n\n* Follow [bintray-sbt publishing instructions](https://github.com/softprops/bintray-sbt#publishing)\n* `;wootModelJS/publish; wootModelJVM/publish`\n\nIt will now be available with\n\n```scala\nresolvers += \"\u003crepo-name\u003e\" at \"http://dl.bintray.com/content/\u003crepo-name\u003e/maven\",\nlibraryDependencies += \"com.dallaway.richard\" %%% \"woot-model\" % \"\u003ccurrent-version\u003e\",\n```\n\n## Reference\n\n* [Exporting Scala.js APIs to JavaScript](http://www.scala-js.org/doc/export-to-javascript.html)\n* [Calling JavaScript from Scala.js](http://www.scala-js.org/doc/calling-javascript.html)\n* [Semantics of Scala.js](http://www.scala-js.org/doc/semantics.html) - exceptions to the rule that Scala.js prorgrams behave the same as Scala on the JVM.\n* [JavaScript interoperability ](http://www.scala-js.org/doc/js-interoperability.html) - including a list of [opaque types](http://stackoverflow.com/questions/27821841/working-with-opaque-types-char-and-long).\n* [µPickle 0.2.8](http://lihaoyi.github.io/upickle/) - the JVM and JavaScript JSON/case class serialization library used in this demo.\n* [Depending on Libraries](http://www.scala-js.org/doc/sbt/depending.html) -- both JavaScript and Scala.js.\n* [http4s](http://http4s.org/) - the server used in this demo.\n\n## Scala.js Learning Path\n\nIf you're new to Scala:\n\n* [Creative Scala](http://underscore.io/training/courses/creative-scala/) - a free course from Underscore teaching Scala using drawing primitives backed by Scala.js.\n\nAnd then...\n\n* [Scala-js.org Tutorial](http://www.scala-js.org/doc/tutorial.html)\n* [Hands-on Scala.js](http://lihaoyi.github.io/hands-on-scala-js/#Hands-onScala.js)\n\n\n# License\n\nCopyright 2015 Richard Dallaway\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd6y%2Fwootjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd6y%2Fwootjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd6y%2Fwootjs/lists"}