ソースを参照

Merge pull request #17910 from overleaf/em-comment-ids

Include id in history Comment instances

GitOrigin-RevId: 25b897e8e9e8d7b19dfe2d90d7f0cafeb5e6e97f
Eric Mc Sween 2 年 前
親
コミット
88fe3e2942

+ 7 - 3
libraries/overleaf-editor-core/lib/comment.js

@@ -21,10 +21,12 @@ class Comment {
   resolved = false
   resolved = false
 
 
   /**
   /**
+   * @param {string} id
    * @param {ReadonlyArray<Range>} ranges
    * @param {ReadonlyArray<Range>} ranges
    * @param {boolean} [resolved]
    * @param {boolean} [resolved]
    */
    */
-  constructor(ranges, resolved = false) {
+  constructor(id, ranges, resolved = false) {
+    this.id = id
     this.resolved = resolved
     this.resolved = resolved
     this.ranges = this.mergeRanges(ranges)
     this.ranges = this.mergeRanges(ranges)
   }
   }
@@ -87,7 +89,7 @@ class Comment {
       newRanges.push(new Range(cursor, length))
       newRanges.push(new Range(cursor, length))
     }
     }
 
 
-    return new Comment(newRanges, this.resolved)
+    return new Comment(this.id, newRanges, this.resolved)
   }
   }
 
 
   /**
   /**
@@ -108,7 +110,7 @@ class Comment {
       }
       }
     }
     }
 
 
-    return new Comment(newRanges, this.resolved)
+    return new Comment(this.id, newRanges, this.resolved)
   }
   }
 
 
   /**
   /**
@@ -148,6 +150,7 @@ class Comment {
    */
    */
   toRaw() {
   toRaw() {
     return {
     return {
+      id: this.id,
       resolved: this.resolved,
       resolved: this.resolved,
       ranges: this.ranges.map(range => range.toRaw()),
       ranges: this.ranges.map(range => range.toRaw()),
     }
     }
@@ -189,6 +192,7 @@ class Comment {
    */
    */
   static fromRaw(rawComment) {
   static fromRaw(rawComment) {
     return new Comment(
     return new Comment(
+      rawComment.id,
       rawComment.ranges.map(range => Range.fromRaw(range)),
       rawComment.ranges.map(range => Range.fromRaw(range)),
       rawComment.resolved
       rawComment.resolved
     )
     )

+ 2 - 1
libraries/overleaf-editor-core/lib/file.js

@@ -15,6 +15,7 @@ const StringFileData = require('./file_data/string_file_data')
  * @typedef {import("./types").ReadonlyBlobStore} ReadonlyBlobStore
  * @typedef {import("./types").ReadonlyBlobStore} ReadonlyBlobStore
  * @typedef {import("./types").StringFileRawData} StringFileRawData
  * @typedef {import("./types").StringFileRawData} StringFileRawData
  * @typedef {import("./types").CommentRawData} CommentRawData
  * @typedef {import("./types").CommentRawData} CommentRawData
+ * @typedef {import("./file_data/comment_list")} CommentList
  * @typedef {import("./operation/text_operation")} TextOperation
  * @typedef {import("./operation/text_operation")} TextOperation
  * @typedef {{filterTrackedDeletes?: boolean}} FileGetContentOptions
  * @typedef {{filterTrackedDeletes?: boolean}} FileGetContentOptions
  */
  */
@@ -203,7 +204,7 @@ class File {
   /**
   /**
    * Get the comments for this file.
    * Get the comments for this file.
    *
    *
-   * @return {CommentRawData[]}
+   * @return {CommentList}
    */
    */
   getComments() {
   getComments() {
     return this.data.getComments()
     return this.data.getComments()

+ 32 - 20
libraries/overleaf-editor-core/lib/file_data/comment_list.js

@@ -2,28 +2,45 @@
 const Comment = require('../comment')
 const Comment = require('../comment')
 
 
 /**
 /**
- * @typedef {import("../types").CommentsListRawData} CommentsListRawData
+ * @typedef {import("../types").CommentRawData} CommentRawData
  * @typedef {import("../range")} Range
  * @typedef {import("../range")} Range
  */
  */
 
 
 class CommentList {
 class CommentList {
   /**
   /**
-   * @param {Map<string, Comment>} comments
+   * @param {Comment[]} comments
    */
    */
   constructor(comments) {
   constructor(comments) {
-    this.comments = comments
+    this.comments = new Map(comments.map(comment => [comment.id, comment]))
   }
   }
 
 
   /**
   /**
-   * @returns {CommentsListRawData}
+   * @returns {IterableIterator<Comment>}
    */
    */
-  getComments() {
-    return Array.from(this.comments).map(([commentId, comment]) => {
-      return {
-        id: commentId,
-        ...comment.toRaw(),
-      }
-    })
+  [Symbol.iterator]() {
+    return this.comments.values()
+  }
+
+  /**
+   * Return the length of the comment list
+   *
+   * @returns {number}
+   */
+  get length() {
+    return this.comments.size
+  }
+
+  /**
+   * Return the raw version of the comment list
+   *
+   * @returns {CommentRawData[]}
+   */
+  toRaw() {
+    const raw = []
+    for (const comment of this.comments.values()) {
+      raw.push(comment.toRaw())
+    }
+    return raw
   }
   }
 
 
   /**
   /**
@@ -35,11 +52,10 @@ class CommentList {
   }
   }
 
 
   /**
   /**
-   * @param {string} id
    * @param {Comment} newComment
    * @param {Comment} newComment
    */
    */
-  add(id, newComment) {
-    this.comments.set(id, newComment)
+  add(newComment) {
+    this.comments.set(newComment.id, newComment)
   }
   }
 
 
   /**
   /**
@@ -50,14 +66,10 @@ class CommentList {
   }
   }
 
 
   /**
   /**
-   * @param {CommentsListRawData} rawComments
+   * @param {CommentRawData[]} rawComments
    */
    */
   static fromRaw(rawComments) {
   static fromRaw(rawComments) {
-    const comments = new Map()
-    for (const rawComment of rawComments) {
-      comments.set(rawComment.id, Comment.fromRaw(rawComment))
-    }
-    return new CommentList(comments)
+    return new CommentList(rawComments.map(Comment.fromRaw))
   }
   }
 
 
   /**
   /**

+ 4 - 1
libraries/overleaf-editor-core/lib/file_data/index.js

@@ -1,3 +1,5 @@
+// @ts-check
+
 'use strict'
 'use strict'
 
 
 const assert = require('check-types').assert
 const assert = require('check-types').assert
@@ -17,6 +19,7 @@ let StringFileData = null
  * @typedef {import("../types").BlobStore} BlobStore
  * @typedef {import("../types").BlobStore} BlobStore
  * @typedef {import("../types").ReadonlyBlobStore} ReadonlyBlobStore
  * @typedef {import("../types").ReadonlyBlobStore} ReadonlyBlobStore
  * @typedef {import("../operation/edit_operation")} EditOperation
  * @typedef {import("../operation/edit_operation")} EditOperation
+ * @typedef {import("../file_data/comment_list")} CommentList
  * @typedef {import("../types").CommentRawData} CommentRawData
  * @typedef {import("../types").CommentRawData} CommentRawData
  */
  */
 
 
@@ -190,7 +193,7 @@ class FileData {
   /**
   /**
    * @see File#getComments
    * @see File#getComments
    * @function
    * @function
-   * @return {CommentRawData[]}
+   * @return {CommentList}
    * @abstract
    * @abstract
    */
    */
   getComments() {
   getComments() {

+ 6 - 7
libraries/overleaf-editor-core/lib/file_data/string_file_data.js

@@ -11,7 +11,7 @@ const TrackedChangeList = require('./tracked_change_list')
  * @typedef {import("../types").StringFileRawData} StringFileRawData
  * @typedef {import("../types").StringFileRawData} StringFileRawData
  * @typedef {import("../operation/edit_operation")} EditOperation
  * @typedef {import("../operation/edit_operation")} EditOperation
  * @typedef {import("../types").BlobStore} BlobStore
  * @typedef {import("../types").BlobStore} BlobStore
- * @typedef {import("../types").CommentsListRawData} CommentsListRawData
+ * @typedef {import("../types").CommentRawData} CommentRawData
  * @typedef {import("../types").TrackedChangeRawData} TrackedChangeRawData
  * @typedef {import("../types").TrackedChangeRawData} TrackedChangeRawData
  * @typedef {import('../types').RangesBlob} RangesBlob
  * @typedef {import('../types').RangesBlob} RangesBlob
  */
  */
@@ -19,7 +19,7 @@ const TrackedChangeList = require('./tracked_change_list')
 class StringFileData extends FileData {
 class StringFileData extends FileData {
   /**
   /**
    * @param {string} content
    * @param {string} content
-   * @param {CommentsListRawData} [rawComments]
+   * @param {CommentRawData[]} [rawComments]
    * @param {TrackedChangeRawData[]} [rawTrackedChanges]
    * @param {TrackedChangeRawData[]} [rawTrackedChanges]
    */
    */
   constructor(content, rawComments = [], rawTrackedChanges = []) {
   constructor(content, rawComments = [], rawTrackedChanges = []) {
@@ -49,9 +49,8 @@ class StringFileData extends FileData {
   toRaw() {
   toRaw() {
     const raw = { content: this.content }
     const raw = { content: this.content }
 
 
-    const comments = this.getComments()
-    if (comments.length) {
-      raw.comments = comments
+    if (this.comments.length) {
+      raw.comments = this.comments.toRaw()
     }
     }
 
 
     if (this.trackedChanges.length) {
     if (this.trackedChanges.length) {
@@ -110,7 +109,7 @@ class StringFileData extends FileData {
 
 
   /** @inheritdoc */
   /** @inheritdoc */
   getComments() {
   getComments() {
-    return this.comments.getComments()
+    return this.comments
   }
   }
 
 
   /**
   /**
@@ -135,7 +134,7 @@ class StringFileData extends FileData {
     if (this.comments.comments.size || this.trackedChanges.length) {
     if (this.comments.comments.size || this.trackedChanges.length) {
       /** @type {RangesBlob} */
       /** @type {RangesBlob} */
       const ranges = {
       const ranges = {
-        comments: this.getComments(),
+        comments: this.getComments().toRaw(),
         trackedChanges: this.trackedChanges.toRaw(),
         trackedChanges: this.trackedChanges.toRaw(),
       }
       }
       const rangesBlob = await blobStore.putObject(ranges)
       const rangesBlob = await blobStore.putObject(ranges)

+ 27 - 8
libraries/overleaf-editor-core/lib/operation/add_comment_operation.js

@@ -1,6 +1,7 @@
 // @ts-check
 // @ts-check
 const core = require('../../index')
 const core = require('../../index')
 const Comment = require('../comment')
 const Comment = require('../comment')
+const Range = require('../range')
 const EditOperation = require('./edit_operation')
 const EditOperation = require('./edit_operation')
 
 
 /**
 /**
@@ -16,12 +17,20 @@ const EditOperation = require('./edit_operation')
 class AddCommentOperation extends EditOperation {
 class AddCommentOperation extends EditOperation {
   /**
   /**
    * @param {string} commentId
    * @param {string} commentId
-   * @param {Comment} comment
+   * @param {ReadonlyArray<Range>} ranges
+   * @param {boolean} resolved
    */
    */
-  constructor(commentId, comment) {
+  constructor(commentId, ranges, resolved = false) {
     super()
     super()
+
+    /** @readonly */
     this.commentId = commentId
     this.commentId = commentId
-    this.comment = comment
+
+    /** @readonly */
+    this.ranges = ranges
+
+    /** @readonly */
+    this.resolved = resolved
   }
   }
 
 
   /**
   /**
@@ -30,8 +39,9 @@ class AddCommentOperation extends EditOperation {
    */
    */
   toJSON() {
   toJSON() {
     return {
     return {
-      ...this.comment.toRaw(),
       commentId: this.commentId,
       commentId: this.commentId,
+      ranges: this.ranges.map(range => range.toRaw()),
+      resolved: this.resolved,
     }
     }
   }
   }
 
 
@@ -39,7 +49,9 @@ class AddCommentOperation extends EditOperation {
    * @param {StringFileData} fileData
    * @param {StringFileData} fileData
    */
    */
   apply(fileData) {
   apply(fileData) {
-    fileData.comments.add(this.commentId, this.comment)
+    fileData.comments.add(
+      new Comment(this.commentId, this.ranges, this.resolved)
+    )
   }
   }
 
 
   /**
   /**
@@ -90,8 +102,11 @@ class AddCommentOperation extends EditOperation {
       other instanceof core.SetCommentStateOperation &&
       other instanceof core.SetCommentStateOperation &&
       other.commentId === this.commentId
       other.commentId === this.commentId
     ) {
     ) {
-      const comment = new Comment(this.comment.ranges, other.resolved)
-      return new AddCommentOperation(this.commentId, comment)
+      return new AddCommentOperation(
+        this.commentId,
+        this.ranges,
+        other.resolved
+      )
     }
     }
 
 
     throw new Error(
     throw new Error(
@@ -105,7 +120,11 @@ class AddCommentOperation extends EditOperation {
    * @returns {AddCommentOperation}
    * @returns {AddCommentOperation}
    */
    */
   static fromJSON(raw) {
   static fromJSON(raw) {
-    return new AddCommentOperation(raw.commentId, Comment.fromRaw(raw))
+    return new AddCommentOperation(
+      raw.commentId,
+      raw.ranges.map(Range.fromRaw),
+      raw.resolved ?? false
+    )
   }
   }
 }
 }
 
 

+ 5 - 1
libraries/overleaf-editor-core/lib/operation/delete_comment_operation.js

@@ -50,7 +50,11 @@ class DeleteCommentOperation extends EditOperation {
       return new EditNoOperation()
       return new EditNoOperation()
     }
     }
 
 
-    return new core.AddCommentOperation(this.commentId, comment)
+    return new core.AddCommentOperation(
+      comment.id,
+      comment.ranges.slice(),
+      comment.resolved
+    )
   }
   }
 
 
   /**
   /**

+ 15 - 4
libraries/overleaf-editor-core/lib/operation/edit_operation_transformer.js

@@ -29,8 +29,16 @@ class EditOperationTransformer {
       createTransformer(TextOperation, SetCommentStateOperation, noConflict),
       createTransformer(TextOperation, SetCommentStateOperation, noConflict),
       createTransformer(TextOperation, AddCommentOperation, (a, b) => {
       createTransformer(TextOperation, AddCommentOperation, (a, b) => {
         // apply the text operation to the comment
         // apply the text operation to the comment
-        const movedComment = b.comment.applyTextOperation(a, b.commentId)
-        return [a, new AddCommentOperation(b.commentId, movedComment)]
+        const originalComment = new Comment(b.commentId, b.ranges, b.resolved)
+        const movedComment = originalComment.applyTextOperation(a, b.commentId)
+        return [
+          a,
+          new AddCommentOperation(
+            movedComment.id,
+            movedComment.ranges,
+            movedComment.resolved
+          ),
+        ]
       }),
       }),
       createTransformer(AddCommentOperation, AddCommentOperation, (a, b) => {
       createTransformer(AddCommentOperation, AddCommentOperation, (a, b) => {
         if (a.commentId === b.commentId) {
         if (a.commentId === b.commentId) {
@@ -50,8 +58,11 @@ class EditOperationTransformer {
         SetCommentStateOperation,
         SetCommentStateOperation,
         (a, b) => {
         (a, b) => {
           if (a.commentId === b.commentId) {
           if (a.commentId === b.commentId) {
-            const mergedComment = new Comment(a.comment.ranges, b.resolved)
-            const newA = new AddCommentOperation(a.commentId, mergedComment)
+            const newA = new AddCommentOperation(
+              a.commentId,
+              a.ranges,
+              b.resolved
+            )
             return [newA, b]
             return [newA, b]
           }
           }
           return [a, b]
           return [a, b]

+ 2 - 2
libraries/overleaf-editor-core/lib/operation/set_comment_state_operation.js

@@ -42,8 +42,8 @@ class SetCommentStateOperation extends EditOperation {
   apply(fileData) {
   apply(fileData) {
     const comment = fileData.comments.getComment(this.commentId)
     const comment = fileData.comments.getComment(this.commentId)
     if (comment) {
     if (comment) {
-      const newComment = new Comment(comment.ranges, this.resolved)
-      fileData.comments.add(this.commentId, newComment)
+      const newComment = new Comment(comment.id, comment.ranges, this.resolved)
+      fileData.comments.add(newComment)
     }
     }
   }
   }
 
 

+ 12 - 6
libraries/overleaf-editor-core/lib/types.ts

@@ -11,7 +11,7 @@ export type BlobStore = {
 export type ReadonlyBlobStore = Pick<BlobStore, 'getString' | 'getObject'>
 export type ReadonlyBlobStore = Pick<BlobStore, 'getString' | 'getObject'>
 
 
 export type RangesBlob = {
 export type RangesBlob = {
-  comments: CommentsListRawData
+  comments: CommentRawData[]
   trackedChanges: TrackedChangeRawData[]
   trackedChanges: TrackedChangeRawData[]
 }
 }
 
 
@@ -21,6 +21,7 @@ type Range = {
 }
 }
 
 
 export type CommentRawData = {
 export type CommentRawData = {
+  id: string
   ranges: Range[]
   ranges: Range[]
   resolved?: boolean
   resolved?: boolean
 }
 }
@@ -36,11 +37,9 @@ export type TrackingPropsRawData = {
   ts: string
   ts: string
 }
 }
 
 
-export type CommentsListRawData = Array<{ id: string } & CommentRawData>
-
 export type StringFileRawData = {
 export type StringFileRawData = {
   content: string
   content: string
-  comments?: CommentsListRawData
+  comments?: CommentRawData[]
   trackedChanges?: TrackedChangeRawData[]
   trackedChanges?: TrackedChangeRawData[]
 }
 }
 
 
@@ -69,11 +68,18 @@ export type RawTextOperation = {
   textOperation: RawScanOp[]
   textOperation: RawScanOp[]
 }
 }
 
 
-export type RawAddCommentOperation = CommentRawData & { commentId: string }
+export type RawAddCommentOperation = {
+  commentId: string
+  ranges: Range[]
+  resolved?: boolean
+}
 
 
 export type RawDeleteCommentOperation = { deleteComment: string }
 export type RawDeleteCommentOperation = { deleteComment: string }
 
 
-export type RawSetCommentStateOperation = { commentId: string; resolved: boolean }
+export type RawSetCommentStateOperation = {
+  commentId: string
+  resolved: boolean
+}
 
 
 export type RawEditOperation =
 export type RawEditOperation =
   | RawTextOperation
   | RawTextOperation

+ 10 - 29
libraries/overleaf-editor-core/test/add_comment_operation.test.js

@@ -1,7 +1,7 @@
 // @ts-check
 // @ts-check
 const { expect } = require('chai')
 const { expect } = require('chai')
 const { AddCommentOperation, DeleteCommentOperation } = require('..')
 const { AddCommentOperation, DeleteCommentOperation } = require('..')
-const Comment = require('../lib/comment')
+const Range = require('../lib/range')
 const StringFileData = require('../lib/file_data/string_file_data')
 const StringFileData = require('../lib/file_data/string_file_data')
 
 
 describe('AddCommentOperation', function () {
 describe('AddCommentOperation', function () {
@@ -13,22 +13,12 @@ describe('AddCommentOperation', function () {
     })
     })
     expect(op).to.be.instanceOf(AddCommentOperation)
     expect(op).to.be.instanceOf(AddCommentOperation)
     expect(op.commentId).to.equal('123')
     expect(op.commentId).to.equal('123')
-    expect(op.comment).to.be.instanceOf(Comment)
-    expect(op.comment.resolved).to.be.true
+    expect(op.ranges[0]).to.be.instanceOf(Range)
+    expect(op.resolved).to.be.true
   })
   })
 
 
   it('should convert to JSON', function () {
   it('should convert to JSON', function () {
-    const op = new AddCommentOperation(
-      '123',
-      Comment.fromRaw({
-        ranges: [
-          {
-            pos: 0,
-            length: 1,
-          },
-        ],
-      })
-    )
+    const op = new AddCommentOperation('123', [new Range(0, 1)])
     expect(op.toJSON()).to.eql({
     expect(op.toJSON()).to.eql({
       commentId: '123',
       commentId: '123',
       resolved: false,
       resolved: false,
@@ -43,12 +33,9 @@ describe('AddCommentOperation', function () {
 
 
   it('should apply operation', function () {
   it('should apply operation', function () {
     const fileData = new StringFileData('abc')
     const fileData = new StringFileData('abc')
-    const op = new AddCommentOperation(
-      '123',
-      Comment.fromRaw({ ranges: [{ pos: 0, length: 1 }] })
-    )
+    const op = new AddCommentOperation('123', [new Range(0, 1)])
     op.apply(fileData)
     op.apply(fileData)
-    expect(fileData.getComments()).to.eql([
+    expect(fileData.getComments().toRaw()).to.eql([
       {
       {
         id: '123',
         id: '123',
         ranges: [{ pos: 0, length: 1 }],
         ranges: [{ pos: 0, length: 1 }],
@@ -59,12 +46,9 @@ describe('AddCommentOperation', function () {
 
 
   it('should invert operation', function () {
   it('should invert operation', function () {
     const fileData = new StringFileData('abc')
     const fileData = new StringFileData('abc')
-    const op = new AddCommentOperation(
-      '123',
-      Comment.fromRaw({ ranges: [{ pos: 0, length: 1 }] })
-    )
+    const op = new AddCommentOperation('123', [new Range(0, 1)])
     op.apply(fileData)
     op.apply(fileData)
-    expect(fileData.getComments()).to.eql([
+    expect(fileData.getComments().toRaw()).to.eql([
       {
       {
         id: '123',
         id: '123',
         ranges: [{ pos: 0, length: 1 }],
         ranges: [{ pos: 0, length: 1 }],
@@ -74,14 +58,11 @@ describe('AddCommentOperation', function () {
 
 
     const invertedOp = op.invert()
     const invertedOp = op.invert()
     invertedOp.apply(fileData)
     invertedOp.apply(fileData)
-    expect(fileData.getComments()).to.eql([])
+    expect(fileData.getComments().toRaw()).to.eql([])
   })
   })
 
 
   it('should compose with DeleteCommentOperation', function () {
   it('should compose with DeleteCommentOperation', function () {
-    const addOp = new AddCommentOperation(
-      '123',
-      Comment.fromRaw({ ranges: [{ pos: 0, length: 1 }] })
-    )
+    const addOp = new AddCommentOperation('123', [new Range(0, 1)])
     const deleteOp = new DeleteCommentOperation('123')
     const deleteOp = new DeleteCommentOperation('123')
     expect(addOp.canBeComposedWith(deleteOp)).to.be.true
     expect(addOp.canBeComposedWith(deleteOp)).to.be.true
 
 

+ 21 - 16
libraries/overleaf-editor-core/test/comment.test.js

@@ -7,77 +7,77 @@ const Range = require('../lib/range')
 
 
 describe('Comment', function () {
 describe('Comment', function () {
   it('should move ranges to the right of insert', function () {
   it('should move ranges to the right of insert', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const resComment = comment.applyInsert(3, 5, false)
     const resComment = comment.applyInsert(3, 5, false)
     expect(resComment.ranges).to.eql([new Range(10, 10)])
     expect(resComment.ranges).to.eql([new Range(10, 10)])
   })
   })
 
 
   describe('applyInsert', function () {
   describe('applyInsert', function () {
     it('should insert 1 char before the range', function () {
     it('should insert 1 char before the range', function () {
-      const comment = new Comment([new Range(5, 10)])
+      const comment = new Comment('c1', [new Range(5, 10)])
       expect(comment.applyInsert(4, 1).ranges).to.eql([new Range(6, 10)])
       expect(comment.applyInsert(4, 1).ranges).to.eql([new Range(6, 10)])
     })
     })
 
 
     it('should insert 1 char at the edge, without expandCommand', function () {
     it('should insert 1 char at the edge, without expandCommand', function () {
-      const comment = new Comment([new Range(5, 10)])
+      const comment = new Comment('c1', [new Range(5, 10)])
       expect(comment.applyInsert(5, 1).ranges).to.eql([new Range(6, 10)])
       expect(comment.applyInsert(5, 1).ranges).to.eql([new Range(6, 10)])
     })
     })
 
 
     it('should insert 1 char at the edge, with expandCommand', function () {
     it('should insert 1 char at the edge, with expandCommand', function () {
-      const comment = new Comment([new Range(5, 10)])
+      const comment = new Comment('c1', [new Range(5, 10)])
       expect(comment.applyInsert(5, 1, true).ranges).to.eql([new Range(5, 11)])
       expect(comment.applyInsert(5, 1, true).ranges).to.eql([new Range(5, 11)])
     })
     })
 
 
     it('should expand the range after insert inside it', function () {
     it('should expand the range after insert inside it', function () {
-      const comment = new Comment([new Range(5, 10)])
+      const comment = new Comment('c1', [new Range(5, 10)])
       expect(comment.applyInsert(6, 1, true).ranges).to.eql([new Range(5, 11)])
       expect(comment.applyInsert(6, 1, true).ranges).to.eql([new Range(5, 11)])
     })
     })
   })
   })
 
 
   it('should split the range if inside another and expandComment is false', function () {
   it('should split the range if inside another and expandComment is false', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyInsert(6, 10, false)
     const commentRes = comment.applyInsert(6, 10, false)
     expect(commentRes.ranges).to.eql([new Range(5, 1), new Range(16, 9)])
     expect(commentRes.ranges).to.eql([new Range(5, 1), new Range(16, 9)])
   })
   })
 
 
   it('should insert the range if expandComment is false', function () {
   it('should insert the range if expandComment is false', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyInsert(14, 10, false)
     const commentRes = comment.applyInsert(14, 10, false)
     expect(commentRes.ranges).to.eql([new Range(5, 9), new Range(24, 1)])
     expect(commentRes.ranges).to.eql([new Range(5, 9), new Range(24, 1)])
   })
   })
 
 
   it('should move the range if insert is at range start and expandComment is false', function () {
   it('should move the range if insert is at range start and expandComment is false', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyInsert(5, 10, false)
     const commentRes = comment.applyInsert(5, 10, false)
     expect(commentRes.ranges).to.eql([new Range(15, 10)])
     expect(commentRes.ranges).to.eql([new Range(15, 10)])
   })
   })
 
 
   it('should ignore the range if insert is at range end and expandComment is false', function () {
   it('should ignore the range if insert is at range end and expandComment is false', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyInsert(15, 10, false)
     const commentRes = comment.applyInsert(15, 10, false)
     expect(commentRes.ranges).to.eql([new Range(5, 10)])
     expect(commentRes.ranges).to.eql([new Range(5, 10)])
   })
   })
 
 
   it('should expand the range after inserting on the edge of it if expandComment is true', function () {
   it('should expand the range after inserting on the edge of it if expandComment is true', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyInsert(15, 10, true)
     const commentRes = comment.applyInsert(15, 10, true)
     expect(commentRes.ranges).to.eql([new Range(5, 20)])
     expect(commentRes.ranges).to.eql([new Range(5, 20)])
   })
   })
 
 
   it('should move comment ranges if delete is before it', function () {
   it('should move comment ranges if delete is before it', function () {
-    const comment = new Comment([new Range(5, 10)])
+    const comment = new Comment('c1', [new Range(5, 10)])
     const commentRes = comment.applyDelete(new Range(3, 5))
     const commentRes = comment.applyDelete(new Range(3, 5))
     expect(commentRes.ranges).to.eql([new Range(3, 7)])
     expect(commentRes.ranges).to.eql([new Range(3, 7)])
   })
   })
 
 
   it('should merge ranges after delete', function () {
   it('should merge ranges after delete', function () {
-    const comment = new Comment([new Range(5, 10), new Range(20, 10)])
+    const comment = new Comment('c1', [new Range(5, 10), new Range(20, 10)])
     const commentRes = comment.applyDelete(new Range(7, 18))
     const commentRes = comment.applyDelete(new Range(7, 18))
     expect(commentRes.ranges).to.eql([new Range(5, 7)])
     expect(commentRes.ranges).to.eql([new Range(5, 7)])
   })
   })
 
 
   it('should merge overlapping ranges', function () {
   it('should merge overlapping ranges', function () {
-    const comment = new Comment([
+    const comment = new Comment('c1', [
       new Range(5, 10),
       new Range(5, 10),
       new Range(15, 20),
       new Range(15, 20),
       new Range(50, 10),
       new Range(50, 10),
@@ -86,7 +86,7 @@ describe('Comment', function () {
   })
   })
 
 
   it('should merge unsorted ranges', function () {
   it('should merge unsorted ranges', function () {
-    const comment = new Comment([
+    const comment = new Comment('c1', [
       new Range(15, 20),
       new Range(15, 20),
       new Range(50, 10),
       new Range(50, 10),
       new Range(5, 10),
       new Range(5, 10),
@@ -96,12 +96,17 @@ describe('Comment', function () {
 
 
   it('should throw error when ranges overlap', function () {
   it('should throw error when ranges overlap', function () {
     expect(
     expect(
-      () => new Comment([new Range(5, 10), new Range(10, 5), new Range(50, 10)])
+      () =>
+        new Comment('c1', [
+          new Range(5, 10),
+          new Range(10, 5),
+          new Range(50, 10),
+        ])
     ).to.throw()
     ).to.throw()
   })
   })
 
 
   it('should join touching ranges', function () {
   it('should join touching ranges', function () {
-    const comment = new Comment([
+    const comment = new Comment('c1', [
       new Range(5, 10),
       new Range(5, 10),
       new Range(15, 5),
       new Range(15, 5),
       new Range(50, 10),
       new Range(50, 10),

+ 52 - 63
libraries/overleaf-editor-core/test/comments_list.test.js

@@ -8,15 +8,13 @@ const Range = require('../lib/range')
 
 
 describe('commentList', function () {
 describe('commentList', function () {
   it('checks if toRaw() returns a correct comment list', function () {
   it('checks if toRaw() returns a correct comment list', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)])],
-        ['comm2', new Comment([new Range(20, 5)])],
-        ['comm3', new Comment([new Range(30, 15)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)]),
+      new Comment('comm2', [new Range(20, 5)]),
+      new Comment('comm3', [new Range(30, 15)]),
+    ])
 
 
-    expect(commentList.getComments()).to.eql([
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       {
       {
@@ -28,16 +26,15 @@ describe('commentList', function () {
   })
   })
 
 
   it('should get a comment by id', function () {
   it('should get a comment by id', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)])],
-        ['comm3', new Comment([new Range(30, 15)])],
-        ['comm2', new Comment([new Range(20, 5)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)]),
+      new Comment('comm3', [new Range(30, 15)]),
+      new Comment('comm2', [new Range(20, 5)]),
+    ])
 
 
     const comment = commentList.getComment('comm2')
     const comment = commentList.getComment('comm2')
     expect(comment?.toRaw()).to.eql({
     expect(comment?.toRaw()).to.eql({
+      id: 'comm2',
       ranges: [
       ranges: [
         {
         {
           pos: 20,
           pos: 20,
@@ -49,16 +46,14 @@ describe('commentList', function () {
   })
   })
 
 
   it('should add new comment to the list', function () {
   it('should add new comment to the list', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)])],
-        ['comm2', new Comment([new Range(20, 5)])],
-        ['comm3', new Comment([new Range(30, 15)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)]),
+      new Comment('comm2', [new Range(20, 5)]),
+      new Comment('comm3', [new Range(30, 15)]),
+    ])
 
 
-    commentList.add('comm4', new Comment([new Range(40, 10)]))
-    expect(commentList.getComments()).to.eql([
+    commentList.add(new Comment('comm4', [new Range(40, 10)]))
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       {
       {
@@ -75,18 +70,16 @@ describe('commentList', function () {
   })
   })
 
 
   it('should overwrite existing comment if new one is added', function () {
   it('should overwrite existing comment if new one is added', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)], false)],
-        ['comm2', new Comment([new Range(20, 5)], true)],
-        ['comm3', new Comment([new Range(30, 15)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)], false),
+      new Comment('comm2', [new Range(20, 5)], true),
+      new Comment('comm3', [new Range(30, 15)]),
+    ])
 
 
-    commentList.add('comm1', new Comment([new Range(5, 10)], true))
-    commentList.add('comm2', new Comment([new Range(40, 10)], true))
+    commentList.add(new Comment('comm1', [new Range(5, 10)], true))
+    commentList.add(new Comment('comm2', [new Range(40, 10)], true))
 
 
-    expect(commentList.getComments()).to.eql([
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: true },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: true },
       {
       {
         id: 'comm2',
         id: 'comm2',
@@ -102,33 +95,29 @@ describe('commentList', function () {
   })
   })
 
 
   it('should delete a comment from the list', function () {
   it('should delete a comment from the list', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)])],
-        ['comm2', new Comment([new Range(20, 5)])],
-        ['comm3', new Comment([new Range(30, 15)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)]),
+      new Comment('comm2', [new Range(20, 5)]),
+      new Comment('comm3', [new Range(30, 15)]),
+    ])
 
 
     commentList.delete('comm3')
     commentList.delete('comm3')
-    expect(commentList.getComments()).to.eql([
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
     ])
     ])
   })
   })
 
 
   it('should not throw an error if comment id does not exist', function () {
   it('should not throw an error if comment id does not exist', function () {
-    const commentList = new CommentList(
-      new Map([
-        ['comm1', new Comment([new Range(5, 10)])],
-        ['comm2', new Comment([new Range(20, 5)])],
-        ['comm3', new Comment([new Range(30, 15)])],
-      ])
-    )
+    const commentList = new CommentList([
+      new Comment('comm1', [new Range(5, 10)]),
+      new Comment('comm2', [new Range(20, 5)]),
+      new Comment('comm3', [new Range(30, 15)]),
+    ])
 
 
     commentList.delete('comm5')
     commentList.delete('comm5')
 
 
-    expect(commentList.getComments()).to.eql([
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       {
       {
@@ -153,7 +142,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(15, 5), { commentIds: ['comm1'] })
       commentList.applyInsert(new Range(15, 5), { commentIds: ['comm1'] })
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 5, length: 15 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 5, length: 15 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 20, length: 10 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 20, length: 10 }], resolved: false },
       ])
       ])
@@ -172,7 +161,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(15, 5), { commentIds: ['comm2'] })
       commentList.applyInsert(new Range(15, 5), { commentIds: ['comm2'] })
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 15, length: 15 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 15, length: 15 }], resolved: false },
       ])
       ])
@@ -192,7 +181,7 @@ describe('commentList', function () {
     ])
     ])
 
 
     commentList.applyDelete(new Range(10, 10)) // 10-19
     commentList.applyDelete(new Range(10, 10)) // 10-19
-    expect(commentList.getComments()).to.eql([
+    expect(commentList.toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 5 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 10, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 10, length: 5 }], resolved: false },
     ])
     ])
@@ -216,7 +205,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(7, 5), { commentIds: ['comm1'] })
       commentList.applyInsert(new Range(7, 5), { commentIds: ['comm1'] })
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 5, length: 15 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 5, length: 15 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 25, length: 5 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 25, length: 5 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 35, length: 15 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 35, length: 15 }], resolved: false },
@@ -240,7 +229,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(7, 5), { commentIds: ['comm2'] })
       commentList.applyInsert(new Range(7, 5), { commentIds: ['comm2'] })
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         {
         {
           id: 'comm1',
           id: 'comm1',
           ranges: [
           ranges: [
@@ -280,7 +269,7 @@ describe('commentList', function () {
       commentList.applyInsert(new Range(7, 5), {
       commentList.applyInsert(new Range(7, 5), {
         commentIds: ['comm1', 'comm2'],
         commentIds: ['comm1', 'comm2'],
       })
       })
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         {
         {
           id: 'comm1',
           id: 'comm1',
           ranges: [{ pos: 5, length: 20 }],
           ranges: [{ pos: 5, length: 20 }],
@@ -315,7 +304,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(16, 5))
       commentList.applyInsert(new Range(16, 5))
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 25, length: 5 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 25, length: 5 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 35, length: 15 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 35, length: 15 }], resolved: false },
@@ -339,7 +328,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyInsert(new Range(50, 5))
       commentList.applyInsert(new Range(50, 5))
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 30, length: 15 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 30, length: 15 }], resolved: false },
@@ -363,7 +352,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyDelete(new Range(0, 4))
       commentList.applyDelete(new Range(0, 4))
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         { id: 'comm1', ranges: [{ pos: 1, length: 10 }], resolved: false },
         { id: 'comm1', ranges: [{ pos: 1, length: 10 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 16, length: 5 }], resolved: false },
         { id: 'comm2', ranges: [{ pos: 16, length: 5 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 26, length: 15 }], resolved: false },
         { id: 'comm3', ranges: [{ pos: 26, length: 15 }], resolved: false },
@@ -380,7 +369,7 @@ describe('commentList', function () {
         ])
         ])
 
 
         commentList.applyDelete(new Range(0, 6))
         commentList.applyDelete(new Range(0, 6))
-        expect(commentList.getComments()).to.eql([
+        expect(commentList.toRaw()).to.eql([
           { id: 'comm1', ranges: [{ pos: 0, length: 9 }], resolved: false },
           { id: 'comm1', ranges: [{ pos: 0, length: 9 }], resolved: false },
         ])
         ])
       })
       })
@@ -393,7 +382,7 @@ describe('commentList', function () {
           },
           },
         ])
         ])
         commentList.applyDelete(new Range(7, 10))
         commentList.applyDelete(new Range(7, 10))
-        expect(commentList.getComments()).to.eql([
+        expect(commentList.toRaw()).to.eql([
           { id: 'comm1', ranges: [{ pos: 5, length: 2 }], resolved: false },
           { id: 'comm1', ranges: [{ pos: 5, length: 2 }], resolved: false },
         ])
         ])
       })
       })
@@ -406,7 +395,7 @@ describe('commentList', function () {
           },
           },
         ])
         ])
         commentList.applyDelete(new Range(6, 2))
         commentList.applyDelete(new Range(6, 2))
-        expect(commentList.getComments()).to.eql([
+        expect(commentList.toRaw()).to.eql([
           { id: 'comm1', ranges: [{ pos: 5, length: 8 }], resolved: false },
           { id: 'comm1', ranges: [{ pos: 5, length: 8 }], resolved: false },
         ])
         ])
       })
       })
@@ -429,7 +418,7 @@ describe('commentList', function () {
       ])
       ])
 
 
       commentList.applyDelete(new Range(19, 10))
       commentList.applyDelete(new Range(19, 10))
-      expect(commentList.getComments()).to.eql([
+      expect(commentList.toRaw()).to.eql([
         {
         {
           id: 'comm1',
           id: 'comm1',
           ranges: [{ pos: 5, length: 10 }],
           ranges: [{ pos: 5, length: 10 }],

+ 4 - 5
libraries/overleaf-editor-core/test/delete_comment_operation.test.js

@@ -23,20 +23,19 @@ describe('DeleteCommentOperation', function () {
   it('should apply operation', function () {
   it('should apply operation', function () {
     const fileData = new StringFileData('abc')
     const fileData = new StringFileData('abc')
     const op = new DeleteCommentOperation('123')
     const op = new DeleteCommentOperation('123')
-    fileData.comments.add('123', new Comment([new Range(0, 1)]))
+    fileData.comments.add(new Comment('123', [new Range(0, 1)]))
     op.apply(fileData)
     op.apply(fileData)
-    expect(fileData.getComments()).to.eql([])
+    expect(fileData.getComments().toRaw()).to.eql([])
   })
   })
 
 
   it('should invert operation', function () {
   it('should invert operation', function () {
     const fileData = new StringFileData('abc')
     const fileData = new StringFileData('abc')
     const op = new DeleteCommentOperation('123')
     const op = new DeleteCommentOperation('123')
-    fileData.comments.add('123', new Comment([new Range(0, 1)]))
+    fileData.comments.add(new Comment('123', [new Range(0, 1)]))
     const invertedOp = /** @type {AddCommentOperation} */ (op.invert(fileData))
     const invertedOp = /** @type {AddCommentOperation} */ (op.invert(fileData))
     expect(invertedOp).to.be.instanceOf(AddCommentOperation)
     expect(invertedOp).to.be.instanceOf(AddCommentOperation)
     expect(invertedOp.commentId).to.equal('123')
     expect(invertedOp.commentId).to.equal('123')
-    expect(invertedOp.comment).to.be.instanceOf(Comment)
-    expect(invertedOp.comment.ranges).to.eql([new Range(0, 1)])
+    expect(invertedOp.ranges).to.eql([new Range(0, 1)])
   })
   })
 
 
   it('should not throw if comment not found', function () {
   it('should not throw if comment not found', function () {

+ 12 - 13
libraries/overleaf-editor-core/test/edit_operation.test.js

@@ -8,7 +8,6 @@ const random = require('./support/random')
 const AddCommentOperation = require('../lib/operation/add_comment_operation')
 const AddCommentOperation = require('../lib/operation/add_comment_operation')
 const DeleteCommentOperation = require('../lib/operation/delete_comment_operation')
 const DeleteCommentOperation = require('../lib/operation/delete_comment_operation')
 const SetCommentStateOperation = require('../lib/operation/set_comment_state_operation')
 const SetCommentStateOperation = require('../lib/operation/set_comment_state_operation')
-const Comment = require('../lib/comment')
 const Range = require('../lib/range')
 const Range = require('../lib/range')
 const EditNoOperation = require('../lib/operation/edit_no_operation')
 const EditNoOperation = require('../lib/operation/edit_no_operation')
 
 
@@ -38,16 +37,16 @@ describe('EditOperationTransformer', function () {
   })
   })
 
 
   it('Transforms two AddCommentOperations with same commentId', function () {
   it('Transforms two AddCommentOperations with same commentId', function () {
-    const a = new AddCommentOperation('comm1', new Comment([new Range(0, 1)]))
-    const b = new AddCommentOperation('comm1', new Comment([new Range(2, 3)]))
+    const a = new AddCommentOperation('comm1', [new Range(0, 1)])
+    const b = new AddCommentOperation('comm1', [new Range(2, 3)])
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(EditNoOperation)
     expect(aPrime).to.be.an.instanceof(EditNoOperation)
     expect(bPrime).to.be.an.instanceof(AddCommentOperation)
     expect(bPrime).to.be.an.instanceof(AddCommentOperation)
   })
   })
 
 
   it('Transforms two AddCommentOperations with different commentId', function () {
   it('Transforms two AddCommentOperations with different commentId', function () {
-    const a = new AddCommentOperation('comm1', new Comment([new Range(0, 1)]))
-    const b = new AddCommentOperation('comm2', new Comment([new Range(2, 3)]))
+    const a = new AddCommentOperation('comm1', [new Range(0, 1)])
+    const b = new AddCommentOperation('comm2', [new Range(2, 3)])
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(AddCommentOperation)
     expect(aPrime).to.be.an.instanceof(AddCommentOperation)
     expect(aPrime.toJSON()).to.eql(a.toJSON())
     expect(aPrime.toJSON()).to.eql(a.toJSON())
@@ -74,7 +73,7 @@ describe('EditOperationTransformer', function () {
   })
   })
 
 
   it('Transforms AddCommentOperation and DeleteCommentOperation with same commentId', function () {
   it('Transforms AddCommentOperation and DeleteCommentOperation with same commentId', function () {
-    const a = new AddCommentOperation('comm1', new Comment([new Range(0, 1)]))
+    const a = new AddCommentOperation('comm1', [new Range(0, 1)])
     const b = new DeleteCommentOperation('comm1')
     const b = new DeleteCommentOperation('comm1')
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(EditNoOperation)
     expect(aPrime).to.be.an.instanceof(EditNoOperation)
@@ -84,7 +83,7 @@ describe('EditOperationTransformer', function () {
 
 
   it('Transforms DeleteCommentOperation and AddCommentOperation with same commentId', function () {
   it('Transforms DeleteCommentOperation and AddCommentOperation with same commentId', function () {
     const a = new DeleteCommentOperation('comm1')
     const a = new DeleteCommentOperation('comm1')
-    const b = new AddCommentOperation('comm1', new Comment([new Range(0, 1)]))
+    const b = new AddCommentOperation('comm1', [new Range(0, 1)])
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(DeleteCommentOperation)
     expect(aPrime).to.be.an.instanceof(DeleteCommentOperation)
     expect(aPrime.toJSON()).to.eql(a.toJSON())
     expect(aPrime.toJSON()).to.eql(a.toJSON())
@@ -96,7 +95,7 @@ describe('EditOperationTransformer', function () {
     // abc hello |xyz| -   addComment(10, 3, "comment_id")
     // abc hello |xyz| -   addComment(10, 3, "comment_id")
 
 
     const a = new TextOperation().retain(9).insert(' world')
     const a = new TextOperation().retain(9).insert(' world')
-    const b = new AddCommentOperation('comm1', new Comment([new Range(10, 3)]))
+    const b = new AddCommentOperation('comm1', [new Range(10, 3)])
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(TextOperation)
     expect(aPrime).to.be.an.instanceof(TextOperation)
@@ -113,7 +112,7 @@ describe('EditOperationTransformer', function () {
     // abc hello |xyz| -   addComment(10, 3, "comment_id")
     // abc hello |xyz| -   addComment(10, 3, "comment_id")
     // abc hello[ world] xyz - insert(9, " world")
     // abc hello[ world] xyz - insert(9, " world")
 
 
-    const a = new AddCommentOperation('comm1', new Comment([new Range(10, 3)]))
+    const a = new AddCommentOperation('comm1', [new Range(10, 3)])
     const b = new TextOperation().retain(9).insert(' world')
     const b = new TextOperation().retain(9).insert(' world')
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
@@ -132,7 +131,7 @@ describe('EditOperationTransformer', function () {
     // abc |hello| xyz - addComment(5, 5, "comment_id")
     // abc |hello| xyz - addComment(5, 5, "comment_id")
 
 
     const a = new TextOperation().remove(13)
     const a = new TextOperation().remove(13)
-    const b = new AddCommentOperation('comm1', new Comment([new Range(5, 5)]))
+    const b = new AddCommentOperation('comm1', [new Range(5, 5)])
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(TextOperation)
     expect(aPrime).to.be.an.instanceof(TextOperation)
@@ -151,7 +150,7 @@ describe('EditOperationTransformer', function () {
     // abc hell|z|
     // abc hell|z|
 
 
     const a = new TextOperation().retain(8).remove(4)
     const a = new TextOperation().retain(8).remove(4)
-    const b = new AddCommentOperation('comm1', new Comment([new Range(10, 3)]))
+    const b = new AddCommentOperation('comm1', [new Range(10, 3)])
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(TextOperation)
     expect(aPrime).to.be.an.instanceof(TextOperation)
@@ -170,7 +169,7 @@ describe('EditOperationTransformer', function () {
     // foo abc hell|z|
     // foo abc hell|z|
 
 
     const a = new TextOperation().insert('foo ').retain(8).remove(4)
     const a = new TextOperation().insert('foo ').retain(8).remove(4)
-    const b = new AddCommentOperation('comm1', new Comment([new Range(10, 3)]))
+    const b = new AddCommentOperation('comm1', [new Range(10, 3)])
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     expect(aPrime).to.be.an.instanceof(TextOperation)
     expect(aPrime).to.be.an.instanceof(TextOperation)
@@ -206,7 +205,7 @@ describe('EditOperationTransformer', function () {
   })
   })
 
 
   it('Transforms SetCommentStateOperation and AddCommentOperation', function () {
   it('Transforms SetCommentStateOperation and AddCommentOperation', function () {
-    const a = new AddCommentOperation('comm1', new Comment([new Range(0, 1)]))
+    const a = new AddCommentOperation('comm1', [new Range(0, 1)])
     const b = new SetCommentStateOperation('comm1', true)
     const b = new SetCommentStateOperation('comm1', true)
 
 
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)
     const [aPrime, bPrime] = EditOperationTransformer.transform(a, b)

+ 1 - 1
libraries/overleaf-editor-core/test/file.test.js

@@ -91,6 +91,6 @@ describe('File', function () {
 
 
   it('getComments() returns an empty comment list', function () {
   it('getComments() returns an empty comment list', function () {
     const file = File.fromString('foo')
     const file = File.fromString('foo')
-    expect(file.getComments()).to.eql([])
+    expect(file.getComments().toRaw()).to.eql([])
   })
   })
 })
 })

+ 2 - 2
libraries/overleaf-editor-core/test/hash_file_data.test.js

@@ -106,7 +106,7 @@ describe('HashFileData', function () {
       expect(eagerFileData).to.be.instanceOf(StringFileData)
       expect(eagerFileData).to.be.instanceOf(StringFileData)
       expect(eagerFileData.getContent()).to.equal('content')
       expect(eagerFileData.getContent()).to.equal('content')
       expect(eagerFileData.trackedChanges.toRaw()).to.deep.equal(trackedChanges)
       expect(eagerFileData.trackedChanges.toRaw()).to.deep.equal(trackedChanges)
-      expect(eagerFileData.getComments()).to.deep.equal(comments)
+      expect(eagerFileData.getComments().toRaw()).to.deep.equal(comments)
     })
     })
 
 
     it('should convert HashFileData to StringFileData without ranges', async function () {
     it('should convert HashFileData to StringFileData without ranges', async function () {
@@ -119,7 +119,7 @@ describe('HashFileData', function () {
       expect(eagerFileData).to.be.instanceOf(StringFileData)
       expect(eagerFileData).to.be.instanceOf(StringFileData)
       expect(eagerFileData.getContent()).to.equal('content')
       expect(eagerFileData.getContent()).to.equal('content')
       expect(eagerFileData.trackedChanges.toRaw()).to.deep.equal([])
       expect(eagerFileData.trackedChanges.toRaw()).to.deep.equal([])
-      expect(eagerFileData.getComments()).to.deep.equal([])
+      expect(eagerFileData.getComments().toRaw()).to.deep.equal([])
     })
     })
   })
   })
 })
 })

+ 2 - 2
libraries/overleaf-editor-core/test/lazy_string_file_data.test.js

@@ -120,7 +120,7 @@ describe('LazyStringFileData', function () {
     const eagerString = await fileData.toEager(this.blobStore)
     const eagerString = await fileData.toEager(this.blobStore)
     expect(eagerString).to.be.instanceOf(EagerStringFileData)
     expect(eagerString).to.be.instanceOf(EagerStringFileData)
     expect(eagerString.getContent()).to.equal('the quick brown fox')
     expect(eagerString.getContent()).to.equal('the quick brown fox')
-    expect(eagerString.getComments()).to.deep.equal([
+    expect(eagerString.getComments().toRaw()).to.deep.equal([
       { id: 'foo', ranges: [{ pos: 0, length: 3 }], resolved: false },
       { id: 'foo', ranges: [{ pos: 0, length: 3 }], resolved: false },
     ])
     ])
     expect(eagerString.trackedChanges.toRaw()).to.deep.equal([
     expect(eagerString.trackedChanges.toRaw()).to.deep.equal([
@@ -143,7 +143,7 @@ describe('LazyStringFileData', function () {
     const eagerString = await fileData.toEager(this.blobStore)
     const eagerString = await fileData.toEager(this.blobStore)
     expect(eagerString).to.be.instanceOf(EagerStringFileData)
     expect(eagerString).to.be.instanceOf(EagerStringFileData)
     expect(eagerString.getContent()).to.equal('the quick brown fox')
     expect(eagerString.getContent()).to.equal('the quick brown fox')
-    expect(eagerString.getComments()).to.be.empty
+    expect(eagerString.getComments().toRaw()).to.be.empty
     expect(eagerString.trackedChanges.length).to.equal(0)
     expect(eagerString.trackedChanges.length).to.equal(0)
     expect(this.blobStore.getObject.called).to.be.false
     expect(this.blobStore.getObject.called).to.be.false
     expect(this.blobStore.getString.calledWith(testHash)).to.be.true
     expect(this.blobStore.getString.calledWith(testHash)).to.be.true

+ 3 - 1
libraries/overleaf-editor-core/test/operation.test.js

@@ -98,7 +98,9 @@ describe('Operation', function () {
           const file = this.snapshot.getFile(pathname)
           const file = this.snapshot.getFile(pathname)
           expect(file.getContent()).to.equal(expectedFile.content)
           expect(file.getContent()).to.equal(expectedFile.content)
           expect(file.getMetadata()).to.eql(expectedFile.metadata)
           expect(file.getMetadata()).to.eql(expectedFile.metadata)
-          expect(file.getComments()).to.deep.equal(expectedFile.comments)
+          expect(file.getComments().toRaw()).to.deep.equal(
+            expectedFile.comments
+          )
         })
         })
         return this
         return this
       },
       },

+ 3 - 3
libraries/overleaf-editor-core/test/string_file_data.test.js

@@ -38,7 +38,7 @@ describe('StringFileData', function () {
 
 
   it('getComments() should return an empty array', function () {
   it('getComments() should return an empty array', function () {
     const fileData = new StringFileData('test')
     const fileData = new StringFileData('test')
-    expect(fileData.getComments()).to.eql([])
+    expect(fileData.getComments().toRaw()).to.eql([])
   })
   })
 
 
   it('creates StringFileData with comments', function () {
   it('creates StringFileData with comments', function () {
@@ -63,7 +63,7 @@ describe('StringFileData', function () {
       },
       },
     ])
     ])
 
 
-    expect(fileData.getComments()).to.eql([
+    expect(fileData.getComments().toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: false },
     ])
     ])
@@ -96,7 +96,7 @@ describe('StringFileData', function () {
       ],
       ],
     })
     })
 
 
-    expect(fileData.getComments()).to.eql([
+    expect(fileData.getComments().toRaw()).to.eql([
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm1', ranges: [{ pos: 5, length: 10 }], resolved: false },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: true },
       { id: 'comm2', ranges: [{ pos: 20, length: 5 }], resolved: true },
     ])
     ])