braid-text 0.2.48 → 0.2.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Or try opening the URL in [Braid-Chrome](https://github.com/braid-org/braid-chro
|
|
|
37
37
|
|
|
38
38
|
Check out the `server-demo.js` file to see examples for how to add simple access control, where a user need only enter a password into a cookie in the javascript console like: `document.cookie = 'password'`; and a `/pages` endpoint to show all the edited pages.
|
|
39
39
|
|
|
40
|
-
## General Use
|
|
40
|
+
## General Use as Server
|
|
41
41
|
|
|
42
42
|
Install it in your project:
|
|
43
43
|
```shell
|
|
@@ -94,51 +94,52 @@ http_server.on("request", (req, res) => {
|
|
|
94
94
|
- `patches`: <small style="color:lightgrey">[optional]</small> Array of patches, each of the form `{unit: 'text', range: '[1:3]', content: 'hi'}`, which would replace the second and third unicode code-points in the text with `hi`. See Braid [Range-Patches](https://github.com/braid-org/braid-spec/blob/master/draft-toomim-httpbis-range-patch-01.txt).
|
|
95
95
|
- `peer`: <small style="color:lightgrey">[optional]</small> Identifies this peer. This mutation will not be echoed back to `get` subscriptions that use this same `peer` header.
|
|
96
96
|
|
|
97
|
-
## General Use
|
|
97
|
+
## General Use as Client
|
|
98
|
+
|
|
99
|
+
Here's a basic running example to start:
|
|
98
100
|
|
|
99
101
|
```html
|
|
102
|
+
<!-- 1. Your textarea -->
|
|
103
|
+
<textarea id="my_textarea"></textarea>
|
|
104
|
+
|
|
105
|
+
<!-- 2. Include the library -->
|
|
106
|
+
<script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
|
|
100
107
|
<script src="https://unpkg.com/braid-text/simpleton-client.js"></script>
|
|
101
|
-
<script>
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Example data:
|
|
110
|
-
// state: "Hello World" // The new text
|
|
111
|
-
// patches: [{ range: [5, 5], content: " World" }] // Patches that create the new text
|
|
112
|
-
//
|
|
113
|
-
// Then return the new state of textarea as a string:
|
|
114
|
-
return new_state
|
|
115
|
-
},
|
|
116
|
-
generate_local_diff_update: (prev_state) => {
|
|
117
|
-
|
|
118
|
-
// Compute diff between prev_state ^ and the current textarea string, such as:
|
|
119
|
-
//
|
|
120
|
-
// var patches = [{
|
|
121
|
-
// range: [5, 5], // The range from position 5 to position 5
|
|
122
|
-
// content: " World" // is replaced with the string " World"
|
|
123
|
-
// }]
|
|
124
|
-
//
|
|
125
|
-
// ...to insert something after a prev_state of "Hello".
|
|
126
|
-
|
|
127
|
-
// Then return the new state (as a string) and the diff (as `patches`)
|
|
128
|
-
return {new_state, patches}
|
|
129
|
-
},
|
|
109
|
+
<!-- 3. Wire it up -->
|
|
110
|
+
<script>
|
|
111
|
+
// Connect to server
|
|
112
|
+
var simpleton = simpleton_client('https://braid.org/simpleton_example', {
|
|
113
|
+
on_state: state => my_textarea.value = state, // incoming changes
|
|
114
|
+
get_state: () => my_textarea.value // outgoing changes
|
|
130
115
|
})
|
|
131
|
-
|
|
132
|
-
...
|
|
133
|
-
|
|
134
|
-
// When changes occur in client's textarea, let simpleton know,
|
|
135
|
-
// so that it can call generate_local_diff_update() to ask for them.
|
|
136
|
-
simpleton.changed()
|
|
137
116
|
|
|
117
|
+
// Tell simpleton when user types
|
|
118
|
+
my_textarea.oninput = () => simpleton.changed()
|
|
138
119
|
</script>
|
|
139
120
|
```
|
|
140
121
|
|
|
141
|
-
|
|
122
|
+
You should see something if you run this (though the server in that example will likely ignore your changes).
|
|
123
|
+
|
|
124
|
+
The basic idea is that you create a simpleton_client and tell it to connect to a url. Any incoming changes trigger the `on_state` callback. For outgoing changes, you'd think we would tell simpleton the new state when we get the `oninput` event — however, the network may be backed up, and simpleton wants to hold off on sending more updates. So instead, we just inform simpleton that a change has occurred and let it handle when to actually send the change to the server.
|
|
125
|
+
|
|
126
|
+
This decoupling between `simpleton.changed` and `get_state` is especially helpful when disconnecting from the server for extended periods (like getting on a plane for a couple hours). Without it, simpleton would have queued up a message for every change made during those two hours and try to send them all upon reconnection. With the decoupling, simpleton can wait until reconnection and then request a single diff to the new final state.
|
|
127
|
+
|
|
128
|
+
### Finer-Grained Integration
|
|
129
|
+
|
|
130
|
+
There are a couple ways to do a more fine-grained integration:
|
|
131
|
+
|
|
132
|
+
**1. Receiving patches instead of full state**
|
|
133
|
+
|
|
134
|
+
Rather than receiving a completely new state in `on_state`, you can receive just changes to the current state in `on_patches`, as an array of patches. This can be more efficient, especially if you're integrating with an editor that has an API for making edits (rather than needing to set the whole string, as with an HTML textarea). Even with a textarea though, getting patches can be helpful for updating the cursor or selection position.
|
|
135
|
+
|
|
136
|
+
**2. Supplying custom patch generation**
|
|
137
|
+
|
|
138
|
+
Rather than only supplying `get_state`, you can also supply `get_patches` — a function that accepts a string representing the document at some point in the past and returns an array of patches to get from there to the current state.
|
|
139
|
+
|
|
140
|
+
Simpleton has a default simple way of computing this (scanning for a common prefix and suffix), but you may have a better function that handles complex cases. For example, when a user pastes in what seems like a large change that replaces the entire document, proper diff analysis might reveal it's just a few edits here and there. Also, with some editors, the analogous `oninput` event may provide patches for free, making `get_patches` more efficient.
|
|
141
|
+
|
|
142
|
+
You can see an example of both these finer-grained integration techniques here: [editor.html](https://raw.githubusercontent.com/braid-org/braid-text/master/editor.html).
|
|
142
143
|
|
|
143
144
|
## Client API
|
|
144
145
|
|