upgrading-to-rich-text-deltas.mdx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. ---
  2. title: Upgrading to Rich Text Deltas
  3. date: 2014-10-19
  4. ---
  5. The new rich text type is now live and being used in Quill v0.18.0. It is a big step towards 1.0 and will be the way documents and changes are represented going forward. In most cases this update is non-disruptive and an upgrade can be a simple increment of the version number[^1].
  6. However, if you happened to be storing the old Delta format, here's a short guide on how to migrate.
  7. The main relevant differences between the old and new Deltas are:
  8. 1. Explicit deletes - We need to go through the old Delta, find the implied deletes and insert explicit delete operations into the new Delta
  9. 2. Support for embeds - If we see the hacky representation of embeds, replace with the new representation
  10. {/* more */}
  11. ```javascript
  12. var richText = require('rich-text');
  13. var newDelta = new richText.Delta();
  14. var index = 0;
  15. var changeLength = 0;
  16. oldDelta.ops.forEach(function (op) {
  17. if (_.isString(op.value)) {
  18. // Insert operation
  19. if (op.value === '!' && op.attributes && _.isString(op.attributes.src)) {
  20. // Found the old hacky representation for an embed
  21. // Quill only supports images so far so we can be confident this is an image
  22. // which is represented by 1
  23. newDelta.insert(1, op.attributes);
  24. } else {
  25. newDelta.insert(op.value, op.attributes);
  26. }
  27. changeLength += op.value.length;
  28. } else if (_.isNumber(op.start) && _.isNumber(op.end)) {
  29. // Retain operation
  30. if (op.start > index) {
  31. // Delete operation was implied by the current retain operation
  32. var length = op.start - index;
  33. newDelta.delete(length);
  34. changeLength -= length;
  35. }
  36. // Now handle or retain operation
  37. newDelta.retain(op.end - op.start, op.attributes);
  38. index = op.end;
  39. } else {
  40. throw new Error('You have a misformed delta');
  41. }
  42. });
  43. // Handle implied deletes at the end of the document
  44. if (oldDelta.endLength < oldDelta.startLength + changeLength) {
  45. var length = oldDelta.startLength + changeLength - oldDelta.endLength;
  46. newDelta.delete(length);
  47. }
  48. ```
  49. If you cannot use the rich-text module or if you are using this as a general guide for another language, the following might be helpful in crafting insert, delete and retain operations.
  50. ```javascript
  51. var nweDelta = { ops: [] };
  52. oldDelta.ops.forEach(function () {
  53. // Following a similar logic to the earlier snippet
  54. // except replacing .insert(), .retain(), .delete() with:
  55. // insertOp(newDelta.ops, value, formats)
  56. // retainOp(newDelta.ops, length, formats)
  57. // deleteOp(newDelta.ops, length)
  58. });
  59. function insertOp(opsArr, text, formats) {
  60. var op = { insert: text };
  61. if (formats && Object.keys(formats).length > 0) {
  62. op.attributes = formats;
  63. }
  64. opsArr.push(op);
  65. }
  66. function deleteOp(opsArr, length) {
  67. opsArr.push({ delete: length });
  68. }
  69. function retainOp(opsArr, length, formats) {
  70. var op = { retain: length };
  71. if (formats && Object.keys(formats).length > 0) {
  72. op.attributes = formats;
  73. }
  74. opsArr.push(op);
  75. }
  76. ```
  77. There are some optimizations performed by rich-text such as excluding no-ops (delete 0 characters) and merging two adjacent operations of the same type (insert 'A' followed by insert 'B' is merged to be a single insert 'AB' operation). But you should not have to worry about these cases since the old Delta format had similar optimizations.
  78. [^1]: All it took to upgrade the examples on quilljs.com was: [2580c2](https://github.com/quilljs/quill/commit/2580c2a5d440622d226fbef407df7a5a5e9dcf61)