@type-editor/changeset 0.0.2

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/.editorconfig ADDED
@@ -0,0 +1,8 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 4
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ insert_final_newline = true
@@ -0,0 +1,8 @@
1
+ README.md
2
+ **/README.md
3
+
4
+ node_modules/
5
+ **/node_modules/
6
+ dist/
7
+ **/dist/
8
+ preview/
package/.prettierrc ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 4,
5
+ "trailingComma": "es5",
6
+ "printWidth": 100,
7
+ "endOfLine": "lf",
8
+ "bracketSpacing": true
9
+ }
package/LICENSE ADDED
@@ -0,0 +1,48 @@
1
+ Original ProseMirror License (https://github.com/ProseMirror)
2
+
3
+ Copyright (C) 2015-2017 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+
23
+
24
+ // -------------------------------------------------------
25
+
26
+ Type Editor License
27
+
28
+ MIT License
29
+
30
+ Copyright (c) 2026 - present (type-editor at mailbox.org)
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ of this software and associated documentation files (the "Software"), to deal
34
+ in the Software without restriction, including without limitation the rights
35
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the Software is
37
+ furnished to do so, subject to the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included in all
40
+ copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # @type-editor/changeset
2
+
3
+ A refactored version of ProseMirror's [prosemirror-changeset](https://github.com/ProseMirror/prosemirror-changeset) module, providing tools for tracking and comparing document changes over time.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @type-editor/changeset
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ This module provides utilities for tracking changes to a document from a given point in the past. It condenses step maps down to a flat sequence of replacements and simplifies replacements that partially undo themselves by comparing their content.
14
+
15
+ The `ChangeSet` maintains two coordinate systems:
16
+ - **A coordinates**: Positions in the original (starting) document
17
+ - **B coordinates**: Positions in the current (modified) document
18
+
19
+ ## Use Cases
20
+
21
+ - **Track Changes**: Visualize insertions and deletions in collaborative editing
22
+ - **Change History**: Build "diff view" features showing document modifications
23
+ - **Attribution**: Track which users made which changes when combined with metadata
24
+
25
+ ## Core Classes
26
+
27
+ ### ChangeSet
28
+
29
+ The main class for tracking document changes. A `ChangeSet` collects and simplifies a sequence of document modifications, making it easy to visualize what changed between two document states.
30
+
31
+ ```typescript
32
+ import { ChangeSet } from '@type-editor/changeset';
33
+
34
+ // Create a changeset from a starting document
35
+ const changeSet = ChangeSet.create(startDoc);
36
+
37
+ // Add steps as document changes occur
38
+ const updated = changeSet.addSteps(newDoc, stepMaps, metadata);
39
+
40
+ // Access the tracked changes
41
+ for (const change of updated.changes) {
42
+ console.log(`Replaced ${change.fromA}-${change.toA} with content at ${change.fromB}-${change.toB}`);
43
+ }
44
+ ```
45
+
46
+ #### Methods
47
+
48
+ | Method | Description |
49
+ |----------------------------------------|---------------------------------------------------------------------|
50
+ | `create(doc, combine?, tokenEncoder?)` | Creates a new changeset tracking from the given document. |
51
+ | `addSteps(doc, stepMaps, data?)` | Computes a new changeset by adding step maps and optional metadata. |
52
+ | `changes` | The array of changes tracked from the starting document. |
53
+ | `startDoc` | The starting document that changes are tracked relative to. |
54
+
55
+ ### Change
56
+
57
+ Represents a change between two document versions. A `Change` tracks a replaced range in the document, including both what was deleted from the old version and what was inserted in the new version.
58
+
59
+ ```typescript
60
+ interface Change<Data> {
61
+ fromA: number; // Start position in old document
62
+ toA: number; // End position in old document
63
+ fromB: number; // Start position in new document
64
+ toB: number; // End position in new document
65
+ deleted: ReadonlyArray<Span<Data>>; // Metadata spans for deleted content
66
+ inserted: ReadonlyArray<Span<Data>>; // Metadata spans for inserted content
67
+ }
68
+ ```
69
+
70
+ #### Methods
71
+
72
+ | Method | Description |
73
+ |-------------------------|-----------------------------------------------------------------------------|
74
+ | `fromJSON(json)` | Static method that deserializes a Change from its JSON representation. |
75
+ | `toJSON()` | Serializes this Change to a JSON-compatible representation. |
76
+ | `slice(startA, endA, startB, endB)` | Creates a sub-change by slicing ranges from both coordinate systems. |
77
+
78
+ #### Serialization Example
79
+
80
+ ```typescript
81
+ import { Change } from '@type-editor/changeset';
82
+
83
+ // Serialize a change to JSON
84
+ const json = change.toJSON();
85
+
86
+ // Deserialize a change from JSON
87
+ const restored = Change.fromJSON(json);
88
+ ```
89
+
90
+ ### Span
91
+
92
+ Stores metadata for a part of a change. A `Span` represents a contiguous range in a document with associated metadata.
93
+
94
+ ```typescript
95
+ import { Span } from '@type-editor/changeset';
96
+
97
+ const span = new Span(10, { author: 'user1' });
98
+ console.log(span.length); // 10
99
+ console.log(span.data); // { author: 'user1' }
100
+ ```
101
+
102
+ ## Utility Functions
103
+
104
+ ### computeDiff
105
+
106
+ Computes the difference between two document fragments using Myers' diff algorithm.
107
+
108
+ ```typescript
109
+ import { computeDiff } from '@type-editor/changeset';
110
+
111
+ const changes = computeDiff(fragmentA, fragmentB, range);
112
+ ```
113
+
114
+ ### simplifyChanges
115
+
116
+ Simplifies a set of changes for presentation by expanding insertions and deletions to word boundaries.
117
+
118
+ ```typescript
119
+ import { simplifyChanges } from '@type-editor/changeset';
120
+
121
+ const simplified = simplifyChanges(changes, document);
122
+ ```
123
+
124
+ ## Token Encoder
125
+
126
+ A `TokenEncoder` can be provided when creating a `ChangeSet` to influence how the diffing algorithm compares document content. The default encoder compares nodes by name and text by character, ignoring marks and attributes.
127
+
128
+ ```typescript
129
+ import type { TokenEncoder } from '@type-editor/changeset';
130
+
131
+ const customEncoder: TokenEncoder<string> = {
132
+ encodeCharacter: (char, marks) => String.fromCharCode(char),
133
+ encodeNodeStart: (node) => node.type.name,
134
+ encodeNodeEnd: (node) => `/${node.type.name}`,
135
+ compareTokens: (a, b) => a === b
136
+ };
137
+
138
+ const changeSet = ChangeSet.create(doc, combine, customEncoder);
139
+ ```
140
+
141
+ ### TokenEncoder Interface
142
+
143
+ | Method | Description |
144
+ |--------------------------------|-----------------------------------------------------|
145
+ | `encodeCharacter(char, marks)` | Encode a character with its applied marks. |
146
+ | `encodeNodeStart(node)` | Encode the start of a node or the entire leaf node. |
147
+ | `encodeNodeEnd(node)` | Encode the end token for a node. |
148
+ | `compareTokens(a, b)` | Compare two encoded tokens for equality. |
149
+
150
+ ## License
151
+
152
+ MIT
153
+
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@type-editor/commons");class e{static none=[];_length;_data;constructor(t,e){this._length=t,this._data=e}get length(){return this._length}get data(){return this._data}cut(t){return t===this.length?this:new e(t,this._data)}static slice(t,n,o){if(n===o)return e.none;if(0===n){if(o>=e.len(t))return t}const r=[];let s=0;for(let e=0;s<o&&e<t.length;e++){const i=t[e],l=s+i.length,h=Math.max(n,s),f=Math.min(o,l)-h;f>0&&r.push(i.cut(f)),s=l}return r}static join(n,o,r){if(0===n.length)return o;if(0===o.length)return n;const s=n[n.length-1],i=o[0],l=r(s.data,i.data);if(t.isUndefinedOrNull(l))return n.concat(o);const h=n.slice(0,n.length-1),f=new e(s.length+i.length,l);h.push(f);for(let t=1;t<o.length;t++)h.push(o[t]);return h}static len(t){let e=0;for(const n of t)e+=n.length;return e}}class n{_fromA;_toA;_fromB;_toB;_deleted;_inserted;constructor(t,e,n,o,r,s){this._fromA=t,this._toA=e,this._fromB=n,this._toB=o,this._deleted=r,this._inserted=s}get fromA(){return this._fromA}get toA(){return this._toA}get fromB(){return this._fromB}get toB(){return this._toB}get deleted(){return this._deleted}get inserted(){return this._inserted}get lenA(){return this._toA-this._fromA}get lenB(){return this._toB-this._fromB}static merge(t,e,n){if(0===t.length)return e;if(0===e.length)return t;const o=[];let r=t[0],s=e[0],i=0,l=0,h=0,f=0;for(;(r||s)&&(r||s);)if(r&&(!s||r.toB<s._fromA))o.push(this.adjustChangeForYOffset(r,f)),h+=r.lenB-r.lenA,r=++i<t.length?t[i]:null;else if(s&&(!r||s.toA<r.fromB))o.push(this.adjustChangeForXOffset(s,h)),f+=s.lenB-s.lenA,s=++l<e.length?e[l]:null;else{const a=this.mergeOverlappingChanges(t,e,r,s,i,l,h,f,n);a.change&&o.push(a.change);for(let e=i;e<a.indexX;e++)h+=t[e].lenB-t[e].lenA;for(let t=l;t<a.indexY;t++)f+=e[t].lenB-e[t].lenA;r=a.nextX,s=a.nextY,i=a.indexX,l=a.indexY}return o}static fromJSON(t){return new n(t.fromA,t.toA,t.fromB,t.toB,t.deleted.map(t=>new e(t.length,t.data)),t.inserted.map(t=>new e(t.length,t.data)))}static adjustChangeForYOffset(t,e){return 0===e?t:new n(t.fromA,t.toA,t.fromB+e,t.toB+e,t.deleted,t.inserted)}static adjustChangeForXOffset(t,e){return 0===e?t:new n(t.fromA-e,t.toA-e,t.fromB,t.toB,t.deleted,t.inserted)}static mergeOverlappingChanges(t,o,r,s,i,l,h,f,a){if(!r||!s)throw new Error("mergeOverlappingChanges called with null change");let c=Math.min(r.fromB,s.fromA);const u=Math.min(r.fromA,s.fromA-h);let m=u;const d=Math.min(s.fromB,r.fromB+f);let g=d,B=e.none,A=e.none,p=!1,_=!1,M=r,x=s;for(;;){const n=this.getNextBoundary(M,c,"fromB","toB"),r=this.getNextBoundary(x,c,"fromA","toA"),s=Math.min(n,r),h=M&&c>=M.fromB,f=x&&c>=x.fromA;if(!h&&!f)break;if(h&&c===M?.fromB&&!p&&(B=e.join(B,M.deleted,a),m+=M.lenA,p=!0),h&&!f&&M){const t=e.slice(M.inserted,c-M.fromB,s-M.fromB);A=e.join(A,t,a),g+=s-c}if(f&&c===x?.fromA&&!_&&(A=e.join(A,x.inserted,a),g+=x.lenB,_=!0),f&&!h&&x){const t=e.slice(x.deleted,c-x.fromA,s-x.fromA);B=e.join(B,t,a),m+=s-c}h&&s===M?.toB&&(M=++i<t.length?t[i]:null,p=!1),f&&s===x?.toA&&(x=++l<o.length?o[l]:null,_=!1),c=s}return{change:u<m||d<g?new n(u,m,d,g,B,A):null,nextX:M,nextY:x,indexX:i,indexY:l}}static getNextBoundary(t,e,n,o){return t?e>=t[n]?t[o]:t[n]:Number.MAX_SAFE_INTEGER}slice(t,o,r,s){const i=0===t&&o===this.lenA,l=0===r&&s===this.lenB;return i&&l?this:new n(this._fromA+t,this._fromA+o,this._fromB+r,this._fromB+s,e.slice(this._deleted,t,o),e.slice(this._inserted,r,s))}toJSON(){return this}}const o={encodeCharacter:t=>t,encodeNodeStart:t=>t.type.name,encodeNodeEnd:t=>-function(t){let e=t.schema.cached.changeSetIDs;if(!e){e={};const n=Object.keys(t.schema.nodes);for(let t=0;t<n.length;t++)e[n[t]]=t+1;t.schema.cached.changeSetIDs=e}return e[t.name]}(t.type),compareTokens:(t,e)=>t===e};function r(t,e,n,o,r){const l=n.endA-n.start,h=n.endB-n.start,f=Math.min(5e3,l+h),a=f+1,c=[],u=new Array(2*a).fill(-1);for(let m=0;m<=f;m++){for(let f=-m;f<=m;f+=2){if(s(t,e,u,f,a,n,l,h,o))return i(c,u,f,a,m,n,r)}m%2==0&&c.push(u.slice())}return null}function s(t,e,n,o,r,s,i,l,h){const f=n[o+1+r],a=n[o-1+r];let c=f<a?a:f+1,u=c+o;const m=s.start;for(;c<i&&u<l&&h(t[m+c],e[m+u]);)c++,u++;return n[o+r]=c,c>=i&&u>=l}function i(t,e,n,o,r,s,i){const h=[],f=function(t,e){const n=Math.max(t,e),o=Math.floor(n/10);return Math.min(15,Math.max(2,o))}(s.endA-s.start,s.endB-s.start),a={fromA:-1,toA:-1,fromB:-1,toB:-1};let c=n,u=e;for(let m=r-1;m>=0;m--){const e=u[c+1+o],n=u[c-1+o];let r,d;e<n?(c--,r=n+s.start,d=r+c,l(a,h,i,f,r,r,d,d+1)):(c++,r=e+s.start,d=r+c,l(a,h,i,f,r,r+1,d,d)),u=t[m>>1]}return a.fromA>-1&&h.push(i.slice(a.fromA,a.toA,a.fromB,a.toB)),h.reverse()}function l(t,e,n,o,r,s,i,l){t.fromA>-1&&t.fromA<s+o?(t.fromA=r,t.fromB=i):(t.fromA>-1&&e.push(n.slice(t.fromA,t.toA,t.fromB,t.toB)),t.fromA=r,t.toA=s,t.fromB=i,t.toB=l)}function h(t,e,n,o,r,s,i){n===r&&i.push(e.encodeNodeStart(t));const l=Math.max(r+1,n)-r-1,h=Math.min(s-1,o)-r-1;a(t.content,e,l,h,i),o===s&&i.push(e.encodeNodeEnd(t))}function f(t,e,n,o,r,s){const i=t.text;if(i)for(let l=n;l<o;l++){const n=i.charCodeAt(l-r);s.push(e.encodeCharacter(n,t.marks))}}function a(t,e,n,o,r){let s=0;for(let i=0;i<t.childCount;i++){const l=t.child(i),a=s+l.nodeSize,c=Math.max(s,n),u=Math.min(a,o);c<u&&(l.isText?f(l,e,c,u,s,r):l.isLeaf?r.push(e.encodeNodeStart(l)):h(l,e,c,u,s,a,r)),s=a}return r}function c(t,e,n,s=o){const i=a(t,s,n.fromA,n.toA,[]),l=a(e,s,n.fromB,n.toB,[]),h=(t,e)=>s.compareTokens(t,e),f=function(t,e,n){let o=0,r=t.length,s=e.length;for(;o<t.length&&o<e.length&&n(t[o],e[o]);)o++;for(;r>o&&s>o&&n(t[r-1],e[s-1]);)r--,s--;return{start:o,endA:r,endB:s}}(i,l,h);if(f.start===i.length&&f.start===l.length)return[];if(function(t){return t.endA===t.start||t.endB===t.start||t.endA===t.endB&&t.endA===t.start+1}(f))return[n.slice(f.start,f.endA,f.start,f.endB)];return r(i,l,f,h,n)??[n.slice(f.start,f.endA,f.start,f.endB)]}class u{static computeDiff=c;static MAX_POSITION=2e8;static MIN_POSITION=-2e8;_changes;config;constructor(t,e){this.config=t,this._changes=e}get changes(){return this._changes}get startDoc(){return this.config.doc}static create(t,e=(t,e)=>t===e?t:null,n=o,r=[]){return new u({combine:e,doc:t,encoder:n},r)}addSteps(t,e,o){const r=this.buildChangesFromStepMaps(e,o);if(0===r.length)return this;const s=this.mergeAll(r,this.config.combine),i=n.merge(this._changes,s,this.config.combine),l=this.minimizeChanges(i,s,t);return new u(this.config,l)}map(t){const o=n=>{const o=t(n);return o===n.data?n:new e(n.length,o)},r={doc:this.config.doc,combine:this.config.combine,encoder:this.config.encoder};return new u(r,this._changes.map(t=>new n(t.fromA,t.toA,t.fromB,t.toB,t.deleted.map(o),t.inserted.map(o))))}changedRange(t,e){if(t===this)return null;const n=e?this.computeTouchedRange(e):null,o=n?n.toB-n.fromB-(n.toA-n.fromA):0,r=t=>!n||t<=n.fromA?t:t+o;let s=n?n.fromB:u.MAX_POSITION,i=n?n.toB:u.MIN_POSITION;const l=(t,e=t)=>{s=Math.min(t,s),i=Math.max(e,i)},h=this._changes,f=t.changes;for(let a=0,c=0;a<h.length||c<f.length;){const t=h[a],e=f[c];t&&e&&this.sameRanges(t,e,r)?(a++,c++):e&&(!t||r(t.fromB)>=e.fromB)?(l(e.fromB,e.toB),c++):t&&(l(r(t.fromB),r(t.toB)),a++)}return s<=i?{from:s,to:i}:null}buildChangesFromStepMaps(t,o){const r=[],s=Array.isArray(o);for(let i=0;i<t.length;i++){const l=s?o[i]:o;let h=0;t[i].forEach((t,o,s,i)=>{const f=t===o?e.none:[new e(o-t,l)],a=s===i?e.none:[new e(i-s,l)];r.push(new n(t+h,o+h,s,i,f,a)),h+=i-s-(o-t)})}return r}minimizeChanges(t,e,n){let o=t;for(let r=0;r<o.length;r++){const s=o[r];if(!this.shouldMinimizeChange(s,e))continue;const i=c(this.config.doc.content,n.content,s,this.config.encoder);this.isCompletelyDifferent(i,s)||(o===t&&(o=t.slice()),this.applyDiffToChanges(o,r,i),r+=i.length-1)}return o}shouldMinimizeChange(t,e){return t.fromA!==t.toA&&t.fromB!==t.toB&&e.some(e=>e.toB>t.fromB&&e.fromB<t.toB)}isCompletelyDifferent(t,e){return 1===t.length&&0===t[0].fromB&&t[0].toB===e.toB-e.fromB}applyDiffToChanges(t,e,n){1===n.length?t[e]=n[0]:t.splice(e,1,...n)}mergeAll(t,e,o=0,r=t.length){if(r===o+1)return[t[o]];const s=o+r>>1;return n.merge(this.mergeAll(t,e,o,s),this.mergeAll(t,e,s,r),e)}computeTouchedRange(t){const e=this.computeEndRange(t);if(!e)return null;const n=t.map(t=>t.invert()).reverse(),o=this.computeEndRange(n);return o?{fromA:o.from,toA:o.to,fromB:e.from,toB:e.to}:null}computeEndRange(t){let e=u.MAX_POSITION,n=u.MIN_POSITION;for(const o of t)e!==u.MAX_POSITION&&(e=o.map(e,-1),n=o.map(n,1)),o.forEach((t,o,r,s)=>{e=Math.min(e,r),n=Math.max(n,s)});return e===u.MAX_POSITION?null:{from:e,to:n}}sameRanges(t,e,n){return n(t.fromB)===e.fromB&&n(t.toB)===e.toB&&this.sameSpans(t.deleted,e.deleted)&&this.sameSpans(t.inserted,e.inserted)}sameSpans(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n].length!==e[n].length||t[n].data!==e[n].data)return!1;return!0}}let m;try{m=new RegExp("[\\p{Alphabetic}_]","u")}catch(x){}const d=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function g(t){if(t<128)return t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122;const e=String.fromCharCode(t);return m?m.test(e):e.toUpperCase()!==e.toLowerCase()||d.test(e)}function B(t,e,n,o,r){let s=o,i=r;if(s<n&&g(t.charCodeAt(s-e)))for(;s>e&&g(t.charCodeAt(s-1-e));)s--;if(i>e&&i<=n&&g(t.charCodeAt(i-1-e)))for(;i<n&&g(t.charCodeAt(i-e));)i++;return[s,i]}function A(t,o,r){const s=t[0].fromA-(t[0].fromB-o),i=t[t.length-1],l=i.toA+(r-i.toB);let h=e.none,f=e.none;const a=t[0].deleted.length?t[0].deleted:t[0].inserted.length?t[0].inserted:null;let c=a?.[0]?.data,u=(t[0].inserted.length?t[0].inserted:t[0].deleted.length?t[0].deleted:null)?.[0]?.data,m=s,d=o;for(let n=0;n<=t.length;n++){const o=n===t.length?null:t[n],s=o?o.fromA:l,i=o?o.fromB:r;if(s>m&&(h=e.join(h,[new e(s-m,c)],p)),i>d&&(f=e.join(f,[new e(i-d,u)],p)),!o)break;h=e.join(h,o.deleted,p),f=e.join(f,o.inserted,p),h.length>0&&(c=h[h.length-1].data),f.length>0&&(u=f[f.length-1].data),m=o.toA,d=o.toB}return new n(s,l,o,r,h,f)}function p(t,e){return t===e?t:null}function _(t,e,n,o,r){for(let s=n;s<o;s++){if(!(!(s>=r)&&g(t.charCodeAt(s-e))))return!0}return!1}function M(t,e,o,r,s){const i=Math.max(0,t[e].fromB-30),l=Math.min(r.content.size,t[o-1].toB+30),h=function(t,e,n){const o=[];return function t(e,n,r){let s=0;for(let i=0;i<e.childCount;i++){const l=e.child(i),h=s+l.nodeSize,f=Math.max(s,n),a=Math.min(h,r);if(f<a)if(l.isText){const t=Math.max(0,n-s),e=Math.min(l.text.length,r-s);o.push(l.text.slice(t,e))}else if(l.isLeaf)o.push(" ");else{f===s&&o.push(" ");const e=Math.max(0,f-s-1),n=Math.min(l.content.size,a-s);t(l.content,e,n),a===h&&o.push(" ")}s=h}}(t,e,n),o.join("")}(r.content,i,l);for(let f=e;f<o;f++){const e=f;let r=t[f],a=r.lenA,c=r.lenB;for(;f<o-1;){const e=t[f+1];if(_(h,i,r.toB,e.fromB,l))break;a+=e.lenA,c+=e.lenB,r=e,f++}if(c>0&&a>0&&!(1===c&&1===a)){const[o,r]=B(h,i,l,t[e].fromB,t[f].toB),a=A(t.slice(e,f+1),o,r),c=s.length>0?s[s.length-1]:null;c?.toA===a.fromA?s[s.length-1]=new n(c.fromA,a.toA,c.fromB,a.toB,c.deleted.concat(a.deleted),c.inserted.concat(a.inserted)):s.push(a)}else for(let n=e;n<=f;n++)s.push(t[n])}}exports.Change=n,exports.ChangeSet=u,exports.DefaultEncoder=o,exports.Span=e,exports.computeDiff=c,exports.simplifyChanges=function(t,e){const n=[];for(let o=0;o<t.length;o++){const r=o;let s=t[o].toB;for(;o<t.length-1&&t[o+1].fromB<=s+30;)s=t[++o].toB;M(t,r,o+1,e,n)}return n};
@@ -0,0 +1,107 @@
1
+ import { Fragment } from '@type-editor/model';
2
+ import { Mark } from '@type-editor/model';
3
+ import { Node as Node_2 } from '@type-editor/model';
4
+ import { StepMap } from '@type-editor/transform';
5
+
6
+ export declare class Change<Data = any> {
7
+ private readonly _fromA;
8
+ private readonly _toA;
9
+ private readonly _fromB;
10
+ private readonly _toB;
11
+ private readonly _deleted;
12
+ private readonly _inserted;
13
+ constructor(fromA: number, toA: number, fromB: number, toB: number, deleted: ReadonlyArray<Span<Data>>, inserted: ReadonlyArray<Span<Data>>);
14
+ get fromA(): number;
15
+ get toA(): number;
16
+ get fromB(): number;
17
+ get toB(): number;
18
+ get deleted(): ReadonlyArray<Span<Data>>;
19
+ get inserted(): ReadonlyArray<Span<Data>>;
20
+ get lenA(): number;
21
+ get lenB(): number;
22
+ static merge<Data>(x: ReadonlyArray<Change<Data>>, y: ReadonlyArray<Change<Data>>, combine: (dataA: Data, dataB: Data) => Data): ReadonlyArray<Change<Data>>;
23
+ static fromJSON<Data>(json: ChangeJSON<Data>): Change<Data>;
24
+ private static adjustChangeForYOffset;
25
+ private static adjustChangeForXOffset;
26
+ private static mergeOverlappingChanges;
27
+ private static getNextBoundary;
28
+ slice(startA: number, endA: number, startB: number, endB: number): Change<Data>;
29
+ toJSON(): ChangeJSON<Data>;
30
+ }
31
+
32
+ declare interface ChangeJSON<Data> {
33
+ fromA: number;
34
+ toA: number;
35
+ fromB: number;
36
+ toB: number;
37
+ deleted: ReadonlyArray<{
38
+ length: number;
39
+ data: Data;
40
+ }>;
41
+ inserted: ReadonlyArray<{
42
+ length: number;
43
+ data: Data;
44
+ }>;
45
+ }
46
+
47
+ export declare class ChangeSet<Data = any> {
48
+ static computeDiff: typeof computeDiff;
49
+ private static readonly MAX_POSITION;
50
+ private static readonly MIN_POSITION;
51
+ private readonly _changes;
52
+ private readonly config;
53
+ constructor(config: ChangeSetConfig<Data>, changes: ReadonlyArray<Change<Data>>);
54
+ get changes(): ReadonlyArray<Change<Data>>;
55
+ get startDoc(): Node_2;
56
+ static create<Data = any>(doc: Node_2, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>, changes?: ReadonlyArray<Change<Data>>): ChangeSet<Data>;
57
+ addSteps(newDoc: Node_2, maps: ReadonlyArray<StepMap>, data: Data | ReadonlyArray<Data>): ChangeSet<Data>;
58
+ map<NewData = Data>(callbackFunc: (range: Span<Data>) => NewData): ChangeSet<NewData>;
59
+ changedRange(changeSet: ChangeSet, maps?: ReadonlyArray<StepMap>): {
60
+ from: number;
61
+ to: number;
62
+ } | null;
63
+ private buildChangesFromStepMaps;
64
+ private minimizeChanges;
65
+ private shouldMinimizeChange;
66
+ private isCompletelyDifferent;
67
+ private applyDiffToChanges;
68
+ private mergeAll;
69
+ private computeTouchedRange;
70
+ private computeEndRange;
71
+ private sameRanges;
72
+ private sameSpans;
73
+ }
74
+
75
+ export declare interface ChangeSetConfig<Data> {
76
+ doc: Node_2;
77
+ combine: (dataA: Data, dataB: Data) => Data;
78
+ encoder: TokenEncoder<any>;
79
+ }
80
+
81
+ export declare function computeDiff<T>(fragA: Fragment, fragB: Fragment, range: Change, encoder?: TokenEncoder<T>): Array<Change>;
82
+
83
+ export declare const DefaultEncoder: TokenEncoder<number | string>;
84
+
85
+ export declare function simplifyChanges(changes: ReadonlyArray<Change>, doc: Node_2): Array<Change>;
86
+
87
+ export declare class Span<Data = any> {
88
+ static readonly none: ReadonlyArray<Span>;
89
+ private readonly _length;
90
+ private readonly _data;
91
+ constructor(length: number, data: Data);
92
+ get length(): number;
93
+ get data(): Data;
94
+ private cut;
95
+ static slice<Data>(spans: ReadonlyArray<Span<Data>>, from: number, to: number): ReadonlyArray<Span<Data>>;
96
+ static join<Data>(spanListA: ReadonlyArray<Span<Data>>, spanListB: ReadonlyArray<Span<Data>>, combine: (dataA: Data, dataB: Data) => Data): ReadonlyArray<Span<Data>>;
97
+ private static len;
98
+ }
99
+
100
+ export declare interface TokenEncoder<T> {
101
+ encodeCharacter(char: number, marks: ReadonlyArray<Mark>): T;
102
+ encodeNodeStart(node: Node_2): T;
103
+ encodeNodeEnd(node: Node_2): T;
104
+ compareTokens(a: T, b: T): boolean;
105
+ }
106
+
107
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{isUndefinedOrNull as t}from"@type-editor/commons";class e{static none=[];_length;_data;constructor(t,e){this._length=t,this._data=e}get length(){return this._length}get data(){return this._data}cut(t){return t===this.length?this:new e(t,this._data)}static slice(t,n,o){if(n===o)return e.none;if(0===n){if(o>=e.len(t))return t}const r=[];let s=0;for(let e=0;s<o&&e<t.length;e++){const i=t[e],l=s+i.length,h=Math.max(n,s),f=Math.min(o,l)-h;f>0&&r.push(i.cut(f)),s=l}return r}static join(n,o,r){if(0===n.length)return o;if(0===o.length)return n;const s=n[n.length-1],i=o[0],l=r(s.data,i.data);if(t(l))return n.concat(o);const h=n.slice(0,n.length-1),f=new e(s.length+i.length,l);h.push(f);for(let t=1;t<o.length;t++)h.push(o[t]);return h}static len(t){let e=0;for(const n of t)e+=n.length;return e}}class n{_fromA;_toA;_fromB;_toB;_deleted;_inserted;constructor(t,e,n,o,r,s){this._fromA=t,this._toA=e,this._fromB=n,this._toB=o,this._deleted=r,this._inserted=s}get fromA(){return this._fromA}get toA(){return this._toA}get fromB(){return this._fromB}get toB(){return this._toB}get deleted(){return this._deleted}get inserted(){return this._inserted}get lenA(){return this._toA-this._fromA}get lenB(){return this._toB-this._fromB}static merge(t,e,n){if(0===t.length)return e;if(0===e.length)return t;const o=[];let r=t[0],s=e[0],i=0,l=0,h=0,f=0;for(;(r||s)&&(r||s);)if(r&&(!s||r.toB<s._fromA))o.push(this.adjustChangeForYOffset(r,f)),h+=r.lenB-r.lenA,r=++i<t.length?t[i]:null;else if(s&&(!r||s.toA<r.fromB))o.push(this.adjustChangeForXOffset(s,h)),f+=s.lenB-s.lenA,s=++l<e.length?e[l]:null;else{const c=this.mergeOverlappingChanges(t,e,r,s,i,l,h,f,n);c.change&&o.push(c.change);for(let e=i;e<c.indexX;e++)h+=t[e].lenB-t[e].lenA;for(let t=l;t<c.indexY;t++)f+=e[t].lenB-e[t].lenA;r=c.nextX,s=c.nextY,i=c.indexX,l=c.indexY}return o}static fromJSON(t){return new n(t.fromA,t.toA,t.fromB,t.toB,t.deleted.map(t=>new e(t.length,t.data)),t.inserted.map(t=>new e(t.length,t.data)))}static adjustChangeForYOffset(t,e){return 0===e?t:new n(t.fromA,t.toA,t.fromB+e,t.toB+e,t.deleted,t.inserted)}static adjustChangeForXOffset(t,e){return 0===e?t:new n(t.fromA-e,t.toA-e,t.fromB,t.toB,t.deleted,t.inserted)}static mergeOverlappingChanges(t,o,r,s,i,l,h,f,c){if(!r||!s)throw new Error("mergeOverlappingChanges called with null change");let a=Math.min(r.fromB,s.fromA);const u=Math.min(r.fromA,s.fromA-h);let m=u;const d=Math.min(s.fromB,r.fromB+f);let g=d,B=e.none,A=e.none,p=!1,_=!1,M=r,x=s;for(;;){const n=this.getNextBoundary(M,a,"fromB","toB"),r=this.getNextBoundary(x,a,"fromA","toA"),s=Math.min(n,r),h=M&&a>=M.fromB,f=x&&a>=x.fromA;if(!h&&!f)break;if(h&&a===M?.fromB&&!p&&(B=e.join(B,M.deleted,c),m+=M.lenA,p=!0),h&&!f&&M){const t=e.slice(M.inserted,a-M.fromB,s-M.fromB);A=e.join(A,t,c),g+=s-a}if(f&&a===x?.fromA&&!_&&(A=e.join(A,x.inserted,c),g+=x.lenB,_=!0),f&&!h&&x){const t=e.slice(x.deleted,a-x.fromA,s-x.fromA);B=e.join(B,t,c),m+=s-a}h&&s===M?.toB&&(M=++i<t.length?t[i]:null,p=!1),f&&s===x?.toA&&(x=++l<o.length?o[l]:null,_=!1),a=s}return{change:u<m||d<g?new n(u,m,d,g,B,A):null,nextX:M,nextY:x,indexX:i,indexY:l}}static getNextBoundary(t,e,n,o){return t?e>=t[n]?t[o]:t[n]:Number.MAX_SAFE_INTEGER}slice(t,o,r,s){const i=0===t&&o===this.lenA,l=0===r&&s===this.lenB;return i&&l?this:new n(this._fromA+t,this._fromA+o,this._fromB+r,this._fromB+s,e.slice(this._deleted,t,o),e.slice(this._inserted,r,s))}toJSON(){return this}}const o={encodeCharacter:t=>t,encodeNodeStart:t=>t.type.name,encodeNodeEnd:t=>-function(t){let e=t.schema.cached.changeSetIDs;if(!e){e={};const n=Object.keys(t.schema.nodes);for(let t=0;t<n.length;t++)e[n[t]]=t+1;t.schema.cached.changeSetIDs=e}return e[t.name]}(t.type),compareTokens:(t,e)=>t===e};function r(t,e,n,o,r){const l=n.endA-n.start,h=n.endB-n.start,f=Math.min(5e3,l+h),c=f+1,a=[],u=new Array(2*c).fill(-1);for(let m=0;m<=f;m++){for(let f=-m;f<=m;f+=2){if(s(t,e,u,f,c,n,l,h,o))return i(a,u,f,c,m,n,r)}m%2==0&&a.push(u.slice())}return null}function s(t,e,n,o,r,s,i,l,h){const f=n[o+1+r],c=n[o-1+r];let a=f<c?c:f+1,u=a+o;const m=s.start;for(;a<i&&u<l&&h(t[m+a],e[m+u]);)a++,u++;return n[o+r]=a,a>=i&&u>=l}function i(t,e,n,o,r,s,i){const h=[],f=function(t,e){const n=Math.max(t,e),o=Math.floor(n/10);return Math.min(15,Math.max(2,o))}(s.endA-s.start,s.endB-s.start),c={fromA:-1,toA:-1,fromB:-1,toB:-1};let a=n,u=e;for(let m=r-1;m>=0;m--){const e=u[a+1+o],n=u[a-1+o];let r,d;e<n?(a--,r=n+s.start,d=r+a,l(c,h,i,f,r,r,d,d+1)):(a++,r=e+s.start,d=r+a,l(c,h,i,f,r,r+1,d,d)),u=t[m>>1]}return c.fromA>-1&&h.push(i.slice(c.fromA,c.toA,c.fromB,c.toB)),h.reverse()}function l(t,e,n,o,r,s,i,l){t.fromA>-1&&t.fromA<s+o?(t.fromA=r,t.fromB=i):(t.fromA>-1&&e.push(n.slice(t.fromA,t.toA,t.fromB,t.toB)),t.fromA=r,t.toA=s,t.fromB=i,t.toB=l)}function h(t,e,n,o,r,s,i){n===r&&i.push(e.encodeNodeStart(t));const l=Math.max(r+1,n)-r-1,h=Math.min(s-1,o)-r-1;c(t.content,e,l,h,i),o===s&&i.push(e.encodeNodeEnd(t))}function f(t,e,n,o,r,s){const i=t.text;if(i)for(let l=n;l<o;l++){const n=i.charCodeAt(l-r);s.push(e.encodeCharacter(n,t.marks))}}function c(t,e,n,o,r){let s=0;for(let i=0;i<t.childCount;i++){const l=t.child(i),c=s+l.nodeSize,a=Math.max(s,n),u=Math.min(c,o);a<u&&(l.isText?f(l,e,a,u,s,r):l.isLeaf?r.push(e.encodeNodeStart(l)):h(l,e,a,u,s,c,r)),s=c}return r}function a(t,e,n,s=o){const i=c(t,s,n.fromA,n.toA,[]),l=c(e,s,n.fromB,n.toB,[]),h=(t,e)=>s.compareTokens(t,e),f=function(t,e,n){let o=0,r=t.length,s=e.length;for(;o<t.length&&o<e.length&&n(t[o],e[o]);)o++;for(;r>o&&s>o&&n(t[r-1],e[s-1]);)r--,s--;return{start:o,endA:r,endB:s}}(i,l,h);if(f.start===i.length&&f.start===l.length)return[];if(function(t){return t.endA===t.start||t.endB===t.start||t.endA===t.endB&&t.endA===t.start+1}(f))return[n.slice(f.start,f.endA,f.start,f.endB)];return r(i,l,f,h,n)??[n.slice(f.start,f.endA,f.start,f.endB)]}class u{static computeDiff=a;static MAX_POSITION=2e8;static MIN_POSITION=-2e8;_changes;config;constructor(t,e){this.config=t,this._changes=e}get changes(){return this._changes}get startDoc(){return this.config.doc}static create(t,e=(t,e)=>t===e?t:null,n=o,r=[]){return new u({combine:e,doc:t,encoder:n},r)}addSteps(t,e,o){const r=this.buildChangesFromStepMaps(e,o);if(0===r.length)return this;const s=this.mergeAll(r,this.config.combine),i=n.merge(this._changes,s,this.config.combine),l=this.minimizeChanges(i,s,t);return new u(this.config,l)}map(t){const o=n=>{const o=t(n);return o===n.data?n:new e(n.length,o)},r={doc:this.config.doc,combine:this.config.combine,encoder:this.config.encoder};return new u(r,this._changes.map(t=>new n(t.fromA,t.toA,t.fromB,t.toB,t.deleted.map(o),t.inserted.map(o))))}changedRange(t,e){if(t===this)return null;const n=e?this.computeTouchedRange(e):null,o=n?n.toB-n.fromB-(n.toA-n.fromA):0,r=t=>!n||t<=n.fromA?t:t+o;let s=n?n.fromB:u.MAX_POSITION,i=n?n.toB:u.MIN_POSITION;const l=(t,e=t)=>{s=Math.min(t,s),i=Math.max(e,i)},h=this._changes,f=t.changes;for(let c=0,a=0;c<h.length||a<f.length;){const t=h[c],e=f[a];t&&e&&this.sameRanges(t,e,r)?(c++,a++):e&&(!t||r(t.fromB)>=e.fromB)?(l(e.fromB,e.toB),a++):t&&(l(r(t.fromB),r(t.toB)),c++)}return s<=i?{from:s,to:i}:null}buildChangesFromStepMaps(t,o){const r=[],s=Array.isArray(o);for(let i=0;i<t.length;i++){const l=s?o[i]:o;let h=0;t[i].forEach((t,o,s,i)=>{const f=t===o?e.none:[new e(o-t,l)],c=s===i?e.none:[new e(i-s,l)];r.push(new n(t+h,o+h,s,i,f,c)),h+=i-s-(o-t)})}return r}minimizeChanges(t,e,n){let o=t;for(let r=0;r<o.length;r++){const s=o[r];if(!this.shouldMinimizeChange(s,e))continue;const i=a(this.config.doc.content,n.content,s,this.config.encoder);this.isCompletelyDifferent(i,s)||(o===t&&(o=t.slice()),this.applyDiffToChanges(o,r,i),r+=i.length-1)}return o}shouldMinimizeChange(t,e){return t.fromA!==t.toA&&t.fromB!==t.toB&&e.some(e=>e.toB>t.fromB&&e.fromB<t.toB)}isCompletelyDifferent(t,e){return 1===t.length&&0===t[0].fromB&&t[0].toB===e.toB-e.fromB}applyDiffToChanges(t,e,n){1===n.length?t[e]=n[0]:t.splice(e,1,...n)}mergeAll(t,e,o=0,r=t.length){if(r===o+1)return[t[o]];const s=o+r>>1;return n.merge(this.mergeAll(t,e,o,s),this.mergeAll(t,e,s,r),e)}computeTouchedRange(t){const e=this.computeEndRange(t);if(!e)return null;const n=t.map(t=>t.invert()).reverse(),o=this.computeEndRange(n);return o?{fromA:o.from,toA:o.to,fromB:e.from,toB:e.to}:null}computeEndRange(t){let e=u.MAX_POSITION,n=u.MIN_POSITION;for(const o of t)e!==u.MAX_POSITION&&(e=o.map(e,-1),n=o.map(n,1)),o.forEach((t,o,r,s)=>{e=Math.min(e,r),n=Math.max(n,s)});return e===u.MAX_POSITION?null:{from:e,to:n}}sameRanges(t,e,n){return n(t.fromB)===e.fromB&&n(t.toB)===e.toB&&this.sameSpans(t.deleted,e.deleted)&&this.sameSpans(t.inserted,e.inserted)}sameSpans(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n].length!==e[n].length||t[n].data!==e[n].data)return!1;return!0}}let m;try{m=new RegExp("[\\p{Alphabetic}_]","u")}catch(C){}const d=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function g(t){if(t<128)return t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122;const e=String.fromCharCode(t);return m?m.test(e):e.toUpperCase()!==e.toLowerCase()||d.test(e)}function B(t,e,n,o,r){let s=o,i=r;if(s<n&&g(t.charCodeAt(s-e)))for(;s>e&&g(t.charCodeAt(s-1-e));)s--;if(i>e&&i<=n&&g(t.charCodeAt(i-1-e)))for(;i<n&&g(t.charCodeAt(i-e));)i++;return[s,i]}function A(t,o,r){const s=t[0].fromA-(t[0].fromB-o),i=t[t.length-1],l=i.toA+(r-i.toB);let h=e.none,f=e.none;const c=t[0].deleted.length?t[0].deleted:t[0].inserted.length?t[0].inserted:null;let a=c?.[0]?.data,u=(t[0].inserted.length?t[0].inserted:t[0].deleted.length?t[0].deleted:null)?.[0]?.data,m=s,d=o;for(let n=0;n<=t.length;n++){const o=n===t.length?null:t[n],s=o?o.fromA:l,i=o?o.fromB:r;if(s>m&&(h=e.join(h,[new e(s-m,a)],p)),i>d&&(f=e.join(f,[new e(i-d,u)],p)),!o)break;h=e.join(h,o.deleted,p),f=e.join(f,o.inserted,p),h.length>0&&(a=h[h.length-1].data),f.length>0&&(u=f[f.length-1].data),m=o.toA,d=o.toB}return new n(s,l,o,r,h,f)}function p(t,e){return t===e?t:null}function _(t,e,n,o,r){for(let s=n;s<o;s++){if(!(!(s>=r)&&g(t.charCodeAt(s-e))))return!0}return!1}function M(t,e,o,r,s){const i=Math.max(0,t[e].fromB-30),l=Math.min(r.content.size,t[o-1].toB+30),h=function(t,e,n){const o=[];return function t(e,n,r){let s=0;for(let i=0;i<e.childCount;i++){const l=e.child(i),h=s+l.nodeSize,f=Math.max(s,n),c=Math.min(h,r);if(f<c)if(l.isText){const t=Math.max(0,n-s),e=Math.min(l.text.length,r-s);o.push(l.text.slice(t,e))}else if(l.isLeaf)o.push(" ");else{f===s&&o.push(" ");const e=Math.max(0,f-s-1),n=Math.min(l.content.size,c-s);t(l.content,e,n),c===h&&o.push(" ")}s=h}}(t,e,n),o.join("")}(r.content,i,l);for(let f=e;f<o;f++){const e=f;let r=t[f],c=r.lenA,a=r.lenB;for(;f<o-1;){const e=t[f+1];if(_(h,i,r.toB,e.fromB,l))break;c+=e.lenA,a+=e.lenB,r=e,f++}if(a>0&&c>0&&!(1===a&&1===c)){const[o,r]=B(h,i,l,t[e].fromB,t[f].toB),c=A(t.slice(e,f+1),o,r),a=s.length>0?s[s.length-1]:null;a?.toA===c.fromA?s[s.length-1]=new n(a.fromA,c.toA,a.fromB,c.toB,a.deleted.concat(c.deleted),a.inserted.concat(c.inserted)):s.push(c)}else for(let n=e;n<=f;n++)s.push(t[n])}}function x(t,e){const n=[];for(let o=0;o<t.length;o++){const r=o;let s=t[o].toB;for(;o<t.length-1&&t[o+1].fromB<=s+30;)s=t[++o].toB;M(t,r,o+1,e,n)}return n}export{n as Change,u as ChangeSet,o as DefaultEncoder,e as Span,a as computeDiff,x as simplifyChanges};
@@ -0,0 +1,69 @@
1
+ import eslint from '@eslint/js';
2
+ import {defineConfig, globalIgnores} from 'eslint/config';
3
+ import tseslint from 'typescript-eslint';
4
+ import sortImports from 'eslint-plugin-simple-import-sort';
5
+
6
+
7
+ export default defineConfig(
8
+ eslint.configs.recommended,
9
+ ...tseslint.configs.strictTypeChecked,
10
+ ...tseslint.configs.stylisticTypeChecked,
11
+ {
12
+ languageOptions: {
13
+ parserOptions: {
14
+ projectService: true,
15
+ tsconfigRootDir: __dirname,
16
+ sourceType: 'module',
17
+ ecmaVersion: 'latest',
18
+ parser: '@typescript-eslint/parser',
19
+ },
20
+ },
21
+ plugins: {
22
+ 'simple-import-sort': sortImports,
23
+ },
24
+ rules: {
25
+ 'simple-import-sort/imports': 'error',
26
+ 'simple-import-sort/exports': 'error',
27
+ // Enforce the use of single quotes for strings
28
+ quotes: ['error', 'single'],
29
+ // Enforce semicolons at the end of statements
30
+ semi: ['error', 'always'],
31
+ // Require the use of === and !== (no implicit type conversions)
32
+ eqeqeq: ['error', 'always'],
33
+ curly: [2],
34
+ '@typescript-eslint/no-unnecessary-condition': 'off',
35
+ '@typescript-eslint/restrict-template-expressions': ['error', {
36
+ allowNumber: true,
37
+ }],
38
+ '@typescript-eslint/array-type': ['warn', {
39
+ default: 'generic'
40
+ }],
41
+ '@typescript-eslint/no-extraneous-class': 'off',
42
+ '@typescript-eslint/prefer-return-this-type': 'off',
43
+ '@typescript-eslint/class-literal-property-style': 'off',
44
+
45
+ '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
46
+
47
+ '@typescript-eslint/no-unsafe-member-access': "error",
48
+ '@typescript-eslint/no-unsafe-return': "error",
49
+ '@typescript-eslint/no-unsafe-assignment': "error",
50
+ '@typescript-eslint/no-unsafe-call': "error",
51
+ '@typescript-eslint/no-unsafe-argument': "error",
52
+ '@typescript-eslint/no-explicit-any': "error",
53
+ 'no-unused-vars': "off",
54
+ '@typescript-eslint/no-unused-vars': ['error', {
55
+ argsIgnorePattern: '^_',
56
+ varsIgnorePattern: '^_',
57
+ caughtErrorsIgnorePattern: '^_'
58
+ }]
59
+ },
60
+ },
61
+ globalIgnores([
62
+ ".git/**/*",
63
+ "node_modules/**/*",
64
+ "build/**/*",
65
+ "dist/**/*",
66
+ "test/**/*",
67
+ "test-browser/**/*",
68
+ ]),
69
+ );
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@type-editor/changeset",
3
+ "description": "This is a refactored version of the ProseMirror's 'changeset' module. Original: https://github.com/ProseMirror/prosemirror-changeset",
4
+ "version": "0.0.2",
5
+ "license": "MIT",
6
+ "homepage": "https://type-editor.io",
7
+ "maintainers": [
8
+ {
9
+ "name": "Type Editor",
10
+ "email": "type-editor@mailbox.org",
11
+ "web": "https://type-editor.io"
12
+ }
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git://github.com/type-editor/type.git"
17
+ },
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "module": "dist/index.js",
21
+ "types": "dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.cjs"
27
+ }
28
+ },
29
+ "keywords": [
30
+ "type",
31
+ "type-editor",
32
+ "richtext-editor",
33
+ "prosemirror"
34
+ ],
35
+ "peerDependencies": {
36
+ "@type-editor/commons": "^0.0.2",
37
+ "@type-editor/model": "^0.0.2",
38
+ "@type-editor/transform": "^0.0.2"
39
+ },
40
+ "devDependencies": {
41
+ "@type-editor/test-builder": "^0.0.2",
42
+ "@type-editor/commons": "^0.0.2",
43
+ "@type-editor/transform": "^0.0.2",
44
+ "@type-editor/model": "^0.0.2"
45
+ },
46
+ "scripts": {
47
+ "build": "vite build",
48
+ "build:prod": "NODE_ENV=production vite build --mode production",
49
+ "build:dev": "NODE_ENV=development tsc && vite build --mode development",
50
+ "build:ts": "tsc --noEmit",
51
+ "test": "vitest run",
52
+ "test:watch": "vitest"
53
+ }
54
+ }