├── slate-cursor-indicator ├── .vscode │ └── settings.json ├── .babelrc ├── src │ ├── cursor.js │ └── index.js ├── lib │ ├── index.js │ └── cursor.js └── package.json ├── collab-editor ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── setupTests.js │ ├── App.test.js │ ├── index.js │ ├── App.css │ ├── index.css │ ├── logo.svg │ ├── Components.js │ ├── serviceWorker.js │ └── App.js ├── .gitignore ├── package.json └── README.md ├── slate-multicursor-0.0.2 └── package │ ├── .babelrc │ ├── index.js │ └── package.json ├── package.json ├── defaultValue.js ├── .gitignore ├── server.js └── README.md /slate-cursor-indicator/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /slate-cursor-indicator/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "compact": false, 3 | "presets": [ "es2015", "react"] 4 | } -------------------------------------------------------------------------------- /collab-editor/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /slate-multicursor-0.0.2/package/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "compact": false, 3 | "presets": [ "es2015", "react"] 4 | } -------------------------------------------------------------------------------- /collab-editor/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Immortalin/slate-operational-transform/HEAD/collab-editor/public/favicon.ico -------------------------------------------------------------------------------- /collab-editor/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Immortalin/slate-operational-transform/HEAD/collab-editor/public/logo192.png -------------------------------------------------------------------------------- /collab-editor/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Immortalin/slate-operational-transform/HEAD/collab-editor/public/logo512.png -------------------------------------------------------------------------------- /collab-editor/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /collab-editor/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /collab-editor/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "collab-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@teamwork/websocket-json-stream": "^2.0.0", 14 | "sharedb": "^1.3.3", 15 | "slate": "^0.57.2", 16 | "ws": "^7.2.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /slate-cursor-indicator/src/cursor.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Cursor extends React.Component { 4 | constructor(props) { 5 | super(props) 6 | console.log(props, 'CALLED PROPSSSSS #################') 7 | this.style = { 8 | borderColor: this.props.borderColor || 'red', 9 | padding: '5px', 10 | } 11 | } 12 | 13 | render() { 14 | return ( 15 | 16 | {this.props.showName && {this.props.username}} 17 | 18 | ) 19 | } 20 | } 21 | 22 | export default Cursor; -------------------------------------------------------------------------------- /collab-editor/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /collab-editor/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /slate-cursor-indicator/src/index.js: -------------------------------------------------------------------------------- 1 | 2 | import CursorComponent from './cursor'; 3 | import { Range } from 'slate'; 4 | 5 | const CursorIndicator = (options) => { 6 | 7 | const markName = options.markName || 'cursor'; 8 | function addCursorIndicator(change) { 9 | change.operations.forEach((operation) => { 10 | if (operation.type === 'set_selection') { 11 | console.log('DONENENENENE ################################', markName) 12 | change.addMark(markName); 13 | } 14 | }) 15 | } 16 | 17 | return { 18 | addCursorIndicator 19 | } 20 | } 21 | 22 | export const Cursor = CursorComponent; 23 | export default CursorIndicator; -------------------------------------------------------------------------------- /collab-editor/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /slate-multicursor-0.0.2/package/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const CursorIndicator = (options) => { 4 | 5 | const markName = options.markName || 'cursor'; 6 | 7 | function addCursorIndicator(change) { 8 | change.operations.forEach((operation) => { 9 | if (operation.type === 'set_selection') { 10 | change.addMark(markName); 11 | } 12 | }) 13 | } 14 | 15 | function removeCursorIndicator(change, node) { 16 | const { document, startKey } = change.value 17 | const startBlock = document.getClosestBlock(startKey) 18 | const parent = document.getParent(startBlock.key) 19 | const parentParent = document.getParent(parent.key) 20 | const index = parentParent.nodes.indexOf(parent) 21 | change.removeMarkByKey(parentParent.key, 0, index, markName) 22 | } 23 | 24 | return { 25 | addCursorIndicator, 26 | removeCursorIndicator 27 | } 28 | } 29 | 30 | module.exports = CursorIndicator; -------------------------------------------------------------------------------- /slate-cursor-indicator/lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.Cursor = undefined; 7 | 8 | var _cursor = require('./cursor'); 9 | 10 | var _cursor2 = _interopRequireDefault(_cursor); 11 | 12 | var _slate = require('slate'); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15 | 16 | var CursorIndicator = function CursorIndicator(options) { 17 | 18 | var markName = options.markName || 'cursor'; 19 | function addCursorIndicator(change) { 20 | change.operations.forEach(function (operation) { 21 | if (operation.type === 'set_selection') { 22 | console.log('DONENENENENE ################################', markName); 23 | change.addMark(markName); 24 | } 25 | }); 26 | } 27 | 28 | return { 29 | addCursorIndicator: addCursorIndicator 30 | }; 31 | }; 32 | 33 | var Cursor = exports.Cursor = _cursor2.default; 34 | exports.default = CursorIndicator; -------------------------------------------------------------------------------- /slate-multicursor-0.0.2/package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slate-multicursor", 3 | "version": "0.0.2", 4 | "description": "A users' cursors position indicator for slatejs collaborative editing", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/humandx/slate-multicursor.git" 12 | }, 13 | "keywords": [ 14 | "slate", 15 | "collaboration", 16 | "cursor", 17 | "indicator", 18 | "editor", 19 | "user", 20 | "typing" 21 | ], 22 | "author": "Human Diagnosis Project", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/humandx/slate-multicursor/issues" 26 | }, 27 | "homepage": "https://github.com/humandx/slate-multicursor#readme", 28 | "peerDependencies": { 29 | "slate": "*", 30 | "react": "*" 31 | }, 32 | "devDependencies": { 33 | "babel-cli": "^6.26.0", 34 | "babel-preset-es2015": "^6.24.1", 35 | "babel-preset-react": "^6.24.1", 36 | "eslint": "^4.10.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /collab-editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "collab-editor", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "emotion": "^10.0.27", 10 | "json0-ot-diff": "^1.0.5", 11 | "react": "^16.13.1", 12 | "react-dom": "^16.13.1", 13 | "react-scripts": "3.4.1", 14 | "reconnecting-websocket": "^4.4.0", 15 | "sharedb": "^1.3.3", 16 | "slate": "^0.57.2", 17 | "slate-history": "^0.57.2", 18 | "slate-react": "^0.57.2" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": "react-app" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /slate-cursor-indicator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slate-cursor-indicator", 3 | "version": "0.0.2", 4 | "description": "A users' cursors position indicator for slatejs collaborative editing", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/humandx/slate-cursor-indicator.git" 12 | }, 13 | "keywords": [ 14 | "slate", 15 | "collaboration", 16 | "cursor", 17 | "indicator", 18 | "editor", 19 | "user", 20 | "typing" 21 | ], 22 | "author": "Human Diagnosis Project", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/humandx/slate-cursor-indicator/issues" 26 | }, 27 | "scripts": { 28 | "build": "babel src --out-dir lib" 29 | }, 30 | "homepage": "https://github.com/humandx/slate-cursor-indicator#readme", 31 | "peerDependencies": { 32 | "slate": "*", 33 | "react": "*" 34 | }, 35 | "devDependencies": { 36 | "babel-cli": "^6.26.0", 37 | "babel-preset-es2015": "^6.24.1", 38 | "babel-preset-react": "^6.24.1", 39 | "eslint": "^4.10.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /defaultValue.js: -------------------------------------------------------------------------------- 1 | 2 | const defaultValue = { 3 | users: { 0: { placeholder: true } }, 4 | // selection: { anchor: { path: [0, 0], offset: 0 }, focus: { path: [0, 0], offset: 0 } }, 5 | children: [ 6 | { 7 | type: 'paragraph', 8 | children: [ 9 | { text: 'This is editable ' }, 10 | { text: 'rich', bold: true }, 11 | { text: ' text, ' }, 12 | { text: 'much', italic: true }, 13 | { text: ' better than a ' }, 14 | { text: '