inline.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import FormatBlot from './abstract/format';
  2. import LeafBlot from './abstract/leaf';
  3. import ShadowBlot from './abstract/shadow';
  4. import * as Registry from '../registry';
  5. // Shallow object comparison
  6. function isEqual(obj1: Object, obj2: Object): boolean {
  7. if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
  8. // @ts-ignore
  9. for (let prop in obj1) {
  10. // @ts-ignore
  11. if (obj1[prop] !== obj2[prop]) return false;
  12. }
  13. return true;
  14. }
  15. class InlineBlot extends FormatBlot {
  16. static blotName = 'inline';
  17. static scope = Registry.Scope.INLINE_BLOT;
  18. static tagName = 'SPAN';
  19. static formats(domNode: HTMLElement): any {
  20. if (domNode.tagName === InlineBlot.tagName) return undefined;
  21. return super.formats(domNode);
  22. }
  23. format(name: string, value: any) {
  24. if (name === this.statics.blotName && !value) {
  25. this.children.forEach(child => {
  26. if (!(child instanceof FormatBlot)) {
  27. child = child.wrap(InlineBlot.blotName, true);
  28. }
  29. this.attributes.copy(<FormatBlot>child);
  30. });
  31. this.unwrap();
  32. } else {
  33. super.format(name, value);
  34. }
  35. }
  36. formatAt(index: number, length: number, name: string, value: any): void {
  37. if (this.formats()[name] != null || Registry.query(name, Registry.Scope.ATTRIBUTE)) {
  38. let blot = <InlineBlot>this.isolate(index, length);
  39. blot.format(name, value);
  40. } else {
  41. super.formatAt(index, length, name, value);
  42. }
  43. }
  44. optimize(context: { [key: string]: any }): void {
  45. super.optimize(context);
  46. let formats = this.formats();
  47. if (Object.keys(formats).length === 0) {
  48. return this.unwrap(); // unformatted span
  49. }
  50. let next = this.next;
  51. if (next instanceof InlineBlot && next.prev === this && isEqual(formats, next.formats())) {
  52. next.moveChildren(this);
  53. next.remove();
  54. }
  55. }
  56. }
  57. export default InlineBlot;