@zipify/wysiwyg 1.0.0-dev.79 → 1.0.0-dev.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/wysiwyg.css CHANGED
@@ -740,7 +740,6 @@ $font-height--md: 1.72;
740
740
  }
741
741
  .zw-superscript {
742
742
  font-size: 75%;
743
- line-height: 0;
744
743
  position: relative;
745
744
  vertical-align: initial;
746
745
  top: -0.5em;
@@ -781,7 +780,6 @@ $font-height--md: 1.72;
781
780
  }
782
781
  .ProseMirror {
783
782
  word-wrap: break-word;
784
- white-space: pre-wrap;
785
783
  white-space: break-spaces;
786
784
  -webkit-font-variant-ligatures: none;
787
785
  font-variant-ligatures: none;
package/dist/wysiwyg.mjs CHANGED
@@ -19433,30 +19433,9 @@ class FavoriteColors {
19433
19433
  this.triggerUpdate = triggerUpdate;
19434
19434
  }
19435
19435
  }
19436
- class ContextWindow {
19437
- static use(window2) {
19438
- this.window = window2;
19439
- }
19440
- static get document() {
19441
- return this.window.document;
19442
- }
19443
- static get body() {
19444
- return this.document.body;
19445
- }
19446
- static get head() {
19447
- return this.document.head;
19448
- }
19449
- static getComputedStyle(element) {
19450
- return this.window.getComputedStyle(element);
19451
- }
19452
- }
19453
- __publicField(ContextWindow, "window", window);
19454
19436
  const _ContentNormalizer = class {
19455
19437
  static normalize(content) {
19456
- const options = {
19457
- content,
19458
- parser: _ContentNormalizer.PARSER
19459
- };
19438
+ const options = { content, parser: _ContentNormalizer.PARSER };
19460
19439
  return new _ContentNormalizer(options).normalize();
19461
19440
  }
19462
19441
  constructor({ content, parser }) {
@@ -19471,7 +19450,8 @@ const _ContentNormalizer = class {
19471
19450
  return this._normalizeTextContent();
19472
19451
  }
19473
19452
  _normalizeTextContent() {
19474
- this._dom = this._parser.parseFromString(this._content, "text/html");
19453
+ this._dom = this._parser.parseFromString(this._content.replace(/(\r)?\n/g, ""), "text/html");
19454
+ this._iterateNodes(this._normalizeBreakLines, (node) => node.tagName === "BR");
19475
19455
  this._iterateNodes(this._removeEmptyNodes, this._isBlockNode);
19476
19456
  this._iterateNodes(this._normalizeListItems, (node) => node.tagName === "LI");
19477
19457
  this._iterateNodes(this._normalizeSettingsStructure, (node) => node.tagName === "SPAN");
@@ -19489,9 +19469,9 @@ const _ContentNormalizer = class {
19489
19469
  }
19490
19470
  }
19491
19471
  _removeEmptyNodes(node) {
19492
- if (!node.innerHTML.replace(/\n/g, "").trim()) {
19472
+ const html2 = node.innerHTML.replace(/ /g, "").trim();
19473
+ if (!html2)
19493
19474
  node.remove();
19494
- }
19495
19475
  }
19496
19476
  _normalizeListItems(itemEl) {
19497
19477
  const fragment = new DocumentFragment();
@@ -19503,7 +19483,7 @@ const _ContentNormalizer = class {
19503
19483
  };
19504
19484
  this._assignElementProperties(itemEl, itemEl.parentElement, _ContentNormalizer.BLOCK_STYLES);
19505
19485
  for (const node of children) {
19506
- if (node.tagName === "P") {
19486
+ if (this._isBlockNode(node)) {
19507
19487
  append2(node);
19508
19488
  capturingParagraph = null;
19509
19489
  continue;
@@ -19567,7 +19547,7 @@ const _ContentNormalizer = class {
19567
19547
  _wrapTextNode(parent, node) {
19568
19548
  if (node.nodeType !== Node.TEXT_NODE)
19569
19549
  return node;
19570
- const span = ContextWindow.document.createElement("span");
19550
+ const span = document.createElement("span");
19571
19551
  span.append(node.cloneNode());
19572
19552
  parent.replaceChild(span, node);
19573
19553
  return span;
@@ -19597,6 +19577,29 @@ const _ContentNormalizer = class {
19597
19577
  element.removeAttribute("style");
19598
19578
  }
19599
19579
  }
19580
+ _normalizeBreakLines({ parentElement }) {
19581
+ if (!this._isBlockNode(parentElement))
19582
+ return;
19583
+ if (!parentElement.textContent)
19584
+ return;
19585
+ const fragment = new DocumentFragment();
19586
+ const children = Array.from(parentElement.childNodes);
19587
+ let capturingParagraph = document.createElement("p");
19588
+ const append2 = (node) => {
19589
+ this._assignElementProperties(node, parentElement, _ContentNormalizer.BLOCK_STYLES);
19590
+ fragment.append(node);
19591
+ };
19592
+ for (const child of children) {
19593
+ if (child.tagName === "BR") {
19594
+ append2(capturingParagraph);
19595
+ capturingParagraph = document.createElement("p");
19596
+ continue;
19597
+ }
19598
+ capturingParagraph.append(child);
19599
+ }
19600
+ fragment.append(capturingParagraph);
19601
+ parentElement.replaceWith(fragment);
19602
+ }
19600
19603
  };
19601
19604
  let ContentNormalizer = _ContentNormalizer;
19602
19605
  __publicField(ContentNormalizer, "PARSER", new DOMParser());
@@ -19616,6 +19619,24 @@ __publicField(ContentNormalizer, "ASSIGN_STYLE_RULES", [
19616
19619
  ignore: /text-decoration(.+)?/
19617
19620
  }
19618
19621
  ]);
19622
+ class ContextWindow {
19623
+ static use(window2) {
19624
+ this.window = window2;
19625
+ }
19626
+ static get document() {
19627
+ return this.window.document;
19628
+ }
19629
+ static get body() {
19630
+ return this.document.body;
19631
+ }
19632
+ static get head() {
19633
+ return this.document.head;
19634
+ }
19635
+ static getComputedStyle(element) {
19636
+ return this.window.getComputedStyle(element);
19637
+ }
19638
+ }
19639
+ __publicField(ContextWindow, "window", window);
19619
19640
  class NodeFactory {
19620
19641
  static doc(content) {
19621
19642
  return {
@@ -25550,60 +25571,6 @@ const History = Extension.create({
25550
25571
  };
25551
25572
  }
25552
25573
  });
25553
- const HardBreak = Node$1.create({
25554
- name: "hardBreak",
25555
- addOptions() {
25556
- return {
25557
- keepMarks: true,
25558
- HTMLAttributes: {}
25559
- };
25560
- },
25561
- inline: true,
25562
- group: "inline",
25563
- selectable: false,
25564
- parseHTML() {
25565
- return [
25566
- { tag: "br" }
25567
- ];
25568
- },
25569
- renderHTML({ HTMLAttributes }) {
25570
- return ["br", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
25571
- },
25572
- renderText() {
25573
- return "\n";
25574
- },
25575
- addCommands() {
25576
- return {
25577
- setHardBreak: () => ({ commands: commands2, chain, state, editor }) => {
25578
- return commands2.first([
25579
- () => commands2.exitCode(),
25580
- () => commands2.command(() => {
25581
- const { selection, storedMarks } = state;
25582
- if (selection.$from.parent.type.spec.isolating) {
25583
- return false;
25584
- }
25585
- const { keepMarks } = this.options;
25586
- const { splittableMarks } = editor.extensionManager;
25587
- const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
25588
- return chain().insertContent({ type: this.name }).command(({ tr, dispatch }) => {
25589
- if (dispatch && marks && keepMarks) {
25590
- const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
25591
- tr.ensureMarks(filteredMarks);
25592
- }
25593
- return true;
25594
- }).run();
25595
- })
25596
- ]);
25597
- }
25598
- };
25599
- },
25600
- addKeyboardShortcuts() {
25601
- return {
25602
- "Mod-Enter": () => this.editor.commands.setHardBreak(),
25603
- "Shift-Enter": () => this.editor.commands.setHardBreak()
25604
- };
25605
- }
25606
- });
25607
25574
  const NodeProcessor = Extension.create({
25608
25575
  name: "node_processor",
25609
25576
  addCommands() {
@@ -25759,9 +25726,6 @@ const buildCoreExtensions = () => [
25759
25726
  }),
25760
25727
  Text,
25761
25728
  History,
25762
- HardBreak.configure({
25763
- keepMarks: false
25764
- }),
25765
25729
  NodeProcessor,
25766
25730
  TextProcessor,
25767
25731
  SelectionProcessor,
@@ -3,7 +3,6 @@ import Paragraph from '@tiptap/extension-paragraph';
3
3
  import Text from '@tiptap/extension-text';
4
4
  import Placeholder from '@tiptap/extension-placeholder';
5
5
  import History from '@tiptap/extension-history';
6
- import HardBreak from '@tiptap/extension-hard-break';
7
6
  import { NodeProcessor } from './NodeProcessor';
8
7
  import { TextProcessor } from './TextProcessor';
9
8
  import { SelectionProcessor } from './SelectionProcessor';
@@ -20,9 +19,6 @@ export const buildCoreExtensions = () => [
20
19
  }),
21
20
  Text,
22
21
  History,
23
- HardBreak.configure({
24
- keepMarks: false
25
- }),
26
22
  NodeProcessor,
27
23
  TextProcessor,
28
24
  SelectionProcessor,
@@ -1,5 +1,3 @@
1
- import { ContextWindow } from './ContextWidnow';
2
-
3
1
  export class ContentNormalizer {
4
2
  static PARSER = new DOMParser();
5
3
  static BLOCK_STYLES = ['text-align', 'line-height'];
@@ -21,10 +19,7 @@ export class ContentNormalizer {
21
19
  ];
22
20
 
23
21
  static normalize(content) {
24
- const options = {
25
- content,
26
- parser: ContentNormalizer.PARSER
27
- };
22
+ const options = { content, parser: ContentNormalizer.PARSER };
28
23
 
29
24
  return new ContentNormalizer(options).normalize();
30
25
  }
@@ -43,8 +38,9 @@ export class ContentNormalizer {
43
38
  }
44
39
 
45
40
  _normalizeTextContent() {
46
- this._dom = this._parser.parseFromString(this._content, 'text/html');
41
+ this._dom = this._parser.parseFromString(this._content.replace(/(\r)?\n/g, ''), 'text/html');
47
42
 
43
+ this._iterateNodes(this._normalizeBreakLines, (node) => node.tagName === 'BR');
48
44
  this._iterateNodes(this._removeEmptyNodes, this._isBlockNode);
49
45
  this._iterateNodes(this._normalizeListItems, (node) => node.tagName === 'LI');
50
46
  this._iterateNodes(this._normalizeSettingsStructure, (node) => node.tagName === 'SPAN');
@@ -66,9 +62,9 @@ export class ContentNormalizer {
66
62
  }
67
63
 
68
64
  _removeEmptyNodes(node) {
69
- if (!node.innerHTML.replace(/\n/g, '').trim()) {
70
- node.remove();
71
- }
65
+ const html = node.innerHTML.replace(/ /g, '').trim();
66
+
67
+ if (!html) node.remove();
72
68
  }
73
69
 
74
70
  _normalizeListItems(itemEl) {
@@ -84,7 +80,7 @@ export class ContentNormalizer {
84
80
  this._assignElementProperties(itemEl, itemEl.parentElement, ContentNormalizer.BLOCK_STYLES);
85
81
 
86
82
  for (const node of children) {
87
- if (node.tagName === 'P') {
83
+ if (this._isBlockNode(node)) {
88
84
  append(node);
89
85
  capturingParagraph = null;
90
86
  continue;
@@ -166,7 +162,7 @@ export class ContentNormalizer {
166
162
  _wrapTextNode(parent, node) {
167
163
  if (node.nodeType !== Node.TEXT_NODE) return node;
168
164
 
169
- const span = ContextWindow.document.createElement('span');
165
+ const span = document.createElement('span');
170
166
 
171
167
  span.append(node.cloneNode());
172
168
  parent.replaceChild(span, node);
@@ -203,4 +199,31 @@ export class ContentNormalizer {
203
199
  element.removeAttribute('style');
204
200
  }
205
201
  }
202
+
203
+ _normalizeBreakLines({ parentElement }) {
204
+ if (!this._isBlockNode(parentElement)) return;
205
+ if (!parentElement.textContent) return;
206
+
207
+ const fragment = new DocumentFragment();
208
+ const children = Array.from(parentElement.childNodes);
209
+ let capturingParagraph = document.createElement('p');
210
+
211
+ const append = (node) => {
212
+ this._assignElementProperties(node, parentElement, ContentNormalizer.BLOCK_STYLES);
213
+ fragment.append(node);
214
+ };
215
+
216
+ for (const child of children) {
217
+ if (child.tagName === 'BR') {
218
+ append(capturingParagraph);
219
+ capturingParagraph = document.createElement('p');
220
+ continue;
221
+ }
222
+
223
+ capturingParagraph.append(child);
224
+ }
225
+
226
+ fragment.append(capturingParagraph);
227
+ parentElement.replaceWith(fragment);
228
+ }
206
229
  }
@@ -72,6 +72,12 @@ describe('normalize text content', () => {
72
72
  expect(ContentNormalizer.normalize(input)).toBe(output);
73
73
  });
74
74
 
75
+ test('should allow using heading in list', () => {
76
+ const input = '<ul><li><h2>lorem ipsum</h2></li></ul>';
77
+
78
+ expect(ContentNormalizer.normalize(input)).toBe(input);
79
+ });
80
+
75
81
  test('should ignore empty nodes', () => {
76
82
  const input = '<p>lorem ipsum 1</p><p></p><p>lorem ipsum 2</p>';
77
83
  const output = '<p>lorem ipsum 1</p><p>lorem ipsum 2</p>';
@@ -86,6 +92,13 @@ describe('normalize text content', () => {
86
92
  expect(ContentNormalizer.normalize(input)).toBe(output);
87
93
  });
88
94
 
95
+ test('should ignore non-breaking space only nodes', () => {
96
+ const input = '<p>lorem ipsum 1</p><p>&nbsp;</p><p>lorem ipsum 2</p>';
97
+ const output = '<p>lorem ipsum 1</p><p>lorem ipsum 2</p>';
98
+
99
+ expect(ContentNormalizer.normalize(input)).toBe(output);
100
+ });
101
+
89
102
  test('should ignore newline chapters only nodes', () => {
90
103
  const input = '<p>lorem ipsum 1</p><p>\n</p><p>lorem ipsum 2</p>';
91
104
  const output = '<p>lorem ipsum 1</p><p>lorem ipsum 2</p>';
@@ -127,4 +140,18 @@ describe('normalize text content', () => {
127
140
 
128
141
  expect(ContentNormalizer.normalize(input)).toBe(output);
129
142
  });
143
+
144
+ test('should migrate br to paragraphs', () => {
145
+ const input = '<p><b>lorem</b><br>ipsum</p>';
146
+ const output = '<p><b>lorem</b></p><p>ipsum</p>';
147
+
148
+ expect(ContentNormalizer.normalize(input)).toBe(output);
149
+ });
150
+
151
+ test('should not migrate single br to paragraph', () => {
152
+ const input = '<p><br></p>';
153
+ const output = '<p><br></p>';
154
+
155
+ expect(ContentNormalizer.normalize(input)).toBe(output);
156
+ });
130
157
  });
@@ -12,7 +12,6 @@
12
12
 
13
13
  .zw-superscript {
14
14
  font-size: 75%;
15
- line-height: 0;
16
15
  position: relative;
17
16
  vertical-align: initial;
18
17
  top: -0.5em;
@@ -64,7 +63,6 @@
64
63
 
65
64
  .ProseMirror {
66
65
  word-wrap: break-word;
67
- white-space: pre-wrap;
68
66
  white-space: break-spaces;
69
67
  -webkit-font-variant-ligatures: none;
70
68
  font-variant-ligatures: none;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zipify/wysiwyg",
3
- "version": "1.0.0-dev.79",
3
+ "version": "1.0.0-dev.81",
4
4
  "description": "Zipify modification of TipTap text editor",
5
5
  "main": "dist/wysiwyg.mjs",
6
6
  "repository": {
@@ -30,7 +30,6 @@
30
30
  "@popperjs/core": "^2.11.5",
31
31
  "@tiptap/core": "^2.0.0-beta.182",
32
32
  "@tiptap/extension-document": "^2.0.0-beta.17",
33
- "@tiptap/extension-hard-break": "^2.0.0-beta.33",
34
33
  "@tiptap/extension-heading": "^2.0.0-beta.29",
35
34
  "@tiptap/extension-history": "^2.0.0-beta.26",
36
35
  "@tiptap/extension-link": "^2.0.0-beta.43",