DiffCodec.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. const DMP = require('diff-match-patch')
  2. const { TextOperation } = require('overleaf-editor-core')
  3. const dmp = new DMP()
  4. // Do not attempt to produce a diff for more than 100ms
  5. dmp.Diff_Timeout = 0.1
  6. module.exports = {
  7. ADDED: 1,
  8. REMOVED: -1,
  9. UNCHANGED: 0,
  10. diffAsShareJsOp(before, after) {
  11. const diffs = dmp.diff_main(before.join('\n'), after.join('\n'))
  12. dmp.diff_cleanupSemantic(diffs)
  13. const ops = []
  14. let position = 0
  15. for (const diff of diffs) {
  16. const [type, content] = diff
  17. if (type === this.ADDED) {
  18. ops.push({
  19. i: content,
  20. p: position,
  21. })
  22. position += content.length
  23. } else if (type === this.REMOVED) {
  24. ops.push({
  25. d: content,
  26. p: position,
  27. })
  28. } else if (type === this.UNCHANGED) {
  29. position += content.length
  30. } else {
  31. throw new Error('Unknown type')
  32. }
  33. }
  34. return ops
  35. },
  36. diffAsHistoryV1EditOperation(before, after) {
  37. const diffs = dmp.diff_main(before, after)
  38. dmp.diff_cleanupSemantic(diffs)
  39. const op = new TextOperation()
  40. for (const diff of diffs) {
  41. const [type, content] = diff
  42. if (type === this.ADDED) {
  43. op.insert(content)
  44. } else if (type === this.REMOVED) {
  45. op.remove(content.length)
  46. } else if (type === this.UNCHANGED) {
  47. op.retain(content.length)
  48. } else {
  49. throw new Error('Unknown type')
  50. }
  51. }
  52. return op
  53. },
  54. }