embed.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { EmbedBlot } from 'parchment';
  2. import TextBlot from './text';
  3. const GUARD_TEXT = '\uFEFF';
  4. class Embed extends EmbedBlot {
  5. constructor(scroll, node) {
  6. super(scroll, node);
  7. this.contentNode = document.createElement('span');
  8. this.contentNode.setAttribute('contenteditable', false);
  9. Array.from(this.domNode.childNodes).forEach(childNode => {
  10. this.contentNode.appendChild(childNode);
  11. });
  12. this.leftGuard = document.createTextNode(GUARD_TEXT);
  13. this.rightGuard = document.createTextNode(GUARD_TEXT);
  14. this.domNode.appendChild(this.leftGuard);
  15. this.domNode.appendChild(this.contentNode);
  16. this.domNode.appendChild(this.rightGuard);
  17. }
  18. index(node, offset) {
  19. if (node === this.leftGuard) return 0;
  20. if (node === this.rightGuard) return 1;
  21. return super.index(node, offset);
  22. }
  23. restore(node) {
  24. let range;
  25. let textNode;
  26. const text = node.data.split(GUARD_TEXT).join('');
  27. if (node === this.leftGuard) {
  28. if (this.prev instanceof TextBlot) {
  29. const prevLength = this.prev.length();
  30. this.prev.insertAt(prevLength, text);
  31. range = {
  32. startNode: this.prev.domNode,
  33. startOffset: prevLength + text.length,
  34. };
  35. } else {
  36. textNode = document.createTextNode(text);
  37. this.parent.insertBefore(this.scroll.create(textNode), this);
  38. range = {
  39. startNode: textNode,
  40. startOffset: text.length,
  41. };
  42. }
  43. } else if (node === this.rightGuard) {
  44. if (this.next instanceof TextBlot) {
  45. this.next.insertAt(0, text);
  46. range = {
  47. startNode: this.next.domNode,
  48. startOffset: text.length,
  49. };
  50. } else {
  51. textNode = document.createTextNode(text);
  52. this.parent.insertBefore(this.scroll.create(textNode), this.next);
  53. range = {
  54. startNode: textNode,
  55. startOffset: text.length,
  56. };
  57. }
  58. }
  59. node.data = GUARD_TEXT;
  60. return range;
  61. }
  62. update(mutations, context) {
  63. mutations.forEach(mutation => {
  64. if (
  65. mutation.type === 'characterData' &&
  66. (mutation.target === this.leftGuard ||
  67. mutation.target === this.rightGuard)
  68. ) {
  69. const range = this.restore(mutation.target);
  70. if (range) context.range = range;
  71. }
  72. });
  73. }
  74. }
  75. export default Embed;