98126c6c37a5ef1e9c7bfc08e1bcea8262a21020c208aaff060997ec29a74364267ef9d2bf11a59f2ae8cfaae7107ead70621b86091157a427e47ac92a2983 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import Scope from '../scope.js';
  2. import type { Blot, Leaf, Root } from './abstract/blot.js';
  3. import LeafBlot from './abstract/leaf.js';
  4. class TextBlot extends LeafBlot implements Leaf {
  5. public static readonly blotName = 'text';
  6. public static scope = Scope.INLINE_BLOT;
  7. public static create(value: string): Text {
  8. return document.createTextNode(value);
  9. }
  10. public static value(domNode: Text): string {
  11. return domNode.data;
  12. }
  13. public domNode!: Text;
  14. protected text: string;
  15. constructor(scroll: Root, node: Node) {
  16. super(scroll, node);
  17. this.text = this.statics.value(this.domNode);
  18. }
  19. public deleteAt(index: number, length: number): void {
  20. this.domNode.data = this.text =
  21. this.text.slice(0, index) + this.text.slice(index + length);
  22. }
  23. public index(node: Node, offset: number): number {
  24. if (this.domNode === node) {
  25. return offset;
  26. }
  27. return -1;
  28. }
  29. public insertAt(index: number, value: string, def?: any): void {
  30. if (def == null) {
  31. this.text = this.text.slice(0, index) + value + this.text.slice(index);
  32. this.domNode.data = this.text;
  33. } else {
  34. super.insertAt(index, value, def);
  35. }
  36. }
  37. public length(): number {
  38. return this.text.length;
  39. }
  40. public optimize(context: { [key: string]: any }): void {
  41. super.optimize(context);
  42. this.text = this.statics.value(this.domNode);
  43. if (this.text.length === 0) {
  44. this.remove();
  45. } else if (this.next instanceof TextBlot && this.next.prev === this) {
  46. this.insertAt(this.length(), (this.next as TextBlot).value());
  47. this.next.remove();
  48. }
  49. }
  50. public position(index: number, _inclusive = false): [Node, number] {
  51. return [this.domNode, index];
  52. }
  53. public split(index: number, force = false): Blot | null {
  54. if (!force) {
  55. if (index === 0) {
  56. return this;
  57. }
  58. if (index === this.length()) {
  59. return this.next;
  60. }
  61. }
  62. const after = this.scroll.create(this.domNode.splitText(index));
  63. this.parent.insertBefore(after, this.next || undefined);
  64. this.text = this.statics.value(this.domNode);
  65. return after;
  66. }
  67. public update(
  68. mutations: MutationRecord[],
  69. _context: { [key: string]: any },
  70. ): void {
  71. if (
  72. mutations.some((mutation) => {
  73. return (
  74. mutation.type === 'characterData' && mutation.target === this.domNode
  75. );
  76. })
  77. ) {
  78. this.text = this.statics.value(this.domNode);
  79. }
  80. }
  81. public value(): string {
  82. return this.text;
  83. }
  84. }
  85. export default TextBlot;