Skip to content

Commit 91deb60

Browse files
committed
#9 - Cross browser fixes + WIP
1 parent a93caa1 commit 91deb60

File tree

8 files changed

+111
-20
lines changed

8 files changed

+111
-20
lines changed

src/scripts/modules/BlockFormatter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const BlockFormatter = Module({
8484
},
8585

8686
cleanupBlockquote (rootElem) {
87-
const blockquoteParagraphs = rootElem.querySelectorAll('BLOCKQUOTE P');
87+
const blockquoteParagraphs = rootElem.querySelectorAll('blockquote p');
8888
blockquoteParagraphs.forEach((paragraph) => {
8989
DOM.unwrap(paragraph);
9090
});

src/scripts/modules/ContentEditable.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ const ContentEditable = Module({
152152
} else {
153153
let currentSelection = mediator.get('selection:current');
154154
let currentRange = mediator.get('selection:range');
155-
155+
if (!currentSelection) {
156+
console.log('insertHTML:currentSelection');
157+
}
156158
currentRange.deleteContents();
157159

158160
let tmpContainer = document.createElement('container');

src/scripts/modules/Selection.js

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ const Selection = Module({
187187
const { props } = this;
188188
const currentSelection = this.getCurrentSelection();
189189
let currentRange;
190+
if (!currentSelection) {
191+
console.log('getCurrentRange:currentSelection', currentSelection);
192+
}
190193

191194
if (this.validateSelection(currentSelection)) {
192195
currentRange = currentSelection.getRangeAt(0);
@@ -201,11 +204,17 @@ const Selection = Module({
201204

202205
getAnchorNode () {
203206
const currentSelection = this.getCurrentSelection();
204-
return currentSelection.anchorNode;
207+
if (!currentSelection) {
208+
console.log('getAnchorNode:currentSelection', currentSelection);
209+
}
210+
return currentSelection && currentSelection.anchorNode;
205211
},
206212

207213
getCommonAncestor () {
208214
const currentSelection = this.getCurrentSelection();
215+
if (!currentSelection) {
216+
console.log('getCommonAncestor:currentSelection', currentSelection);
217+
}
209218
if (currentSelection.rangeCount > 0) {
210219
const selectionRange = currentSelection.getRangeAt(0);
211220
return selectionRange.commonAncestorContainer;
@@ -298,9 +307,50 @@ const Selection = Module({
298307

299308
const startTrimmablePrefix = startContainer.textContent.match(/^(\r?\n|\r)?(\s+)?/);
300309
const endTrimmablePrefix = endContainer.textContent.match(/^(\r?\n|\r)?(\s+)?/);
310+
const endTrimmableSuffix = endContainer.textContent.match(/(\r?\n|\r)?(\s+)?$/);
311+
const startElement = DOM.closestElement(startContainer);
312+
const endElement = DOM.closestElement(endContainer);
313+
314+
console.log({
315+
startTrimmablePrefix,
316+
endTrimmablePrefix,
317+
startPrefixLength: startTrimmablePrefix && startTrimmablePrefix[0].length,
318+
endPrefixLength: endTrimmablePrefix && endTrimmablePrefix[0].length,
319+
startContent: startContainer.textContent,
320+
endContent: endContainer.textContent,
321+
endSuffix: endContainer.textContent.match(/(\r?\n|\r)?(\s+)?$/),
322+
startOffset,
323+
endOffset
324+
});
325+
326+
if (startTrimmablePrefix && startTrimmablePrefix[0].length) {
327+
startOffset -= startTrimmablePrefix[0].length;
328+
if (DOM.nodeIsInline(startElement)) {
329+
startOffset -= startTrimmablePrefix[0].match(/\s/) ? 1 : 0;
330+
}
331+
}
332+
333+
if (endTrimmablePrefix && endTrimmablePrefix[0].length) {
334+
endOffset -= endTrimmablePrefix[0].length;
335+
if (DOM.nodeIsInline(endElement)) {
336+
endOffset -= endTrimmablePrefix[0].match(/\s/) ? 1 : 0;
337+
}
338+
}
339+
340+
if (endTrimmableSuffix && endTrimmableSuffix[0].length) {
341+
// endOffset -= endTrimmableSuffix[0].length;
342+
if (DOM.nodeIsInline(endElement)) {
343+
endOffset -= endTrimmableSuffix[0].match(/\s/) ? 1 : 0;
344+
}
345+
}
346+
347+
console.log({
348+
startOffset,
349+
endOffset
350+
});
301351

302-
startOffset -= startTrimmablePrefix ? startTrimmablePrefix[0].length : 0;
303-
endOffset -= endTrimmablePrefix ? endTrimmablePrefix[0].length : 0;
352+
startOffset = Math.max(0, startOffset);
353+
endOffset = Math.min(endContainer.textContent.length, endOffset);
304354

305355
startCoordinates.unshift(startOffset);
306356
endCoordinates.unshift(endOffset);
@@ -331,7 +381,6 @@ const Selection = Module({
331381
}
332382

333383
const isIn = DOM.isIn(anchorNode, selectors, rootEl);
334-
335384
if (isIn) {
336385
return isIn;
337386
}
@@ -341,8 +390,8 @@ const Selection = Module({
341390
let contains = false;
342391

343392
if (rangeFrag.childNodes.length) {
344-
selectors.forEach(selector => {
345-
contains = contains || rangeFrag.childNodes[0].nodeName === selector;
393+
rangeFrag.childNodes.forEach(childNode => {
394+
contains = contains || selectors.indexOf(childNode.nodeName) > -1;
346395
});
347396
}
348397

@@ -353,7 +402,9 @@ const Selection = Module({
353402
const currentSelection = this.getCurrentSelection();
354403
let { anchorNode, focusNode } = currentSelection;
355404
const selectionContainsNode = currentSelection.containsNode(node, true);
356-
405+
if (!currentSelection) {
406+
console.log('containsNode:currentSelection', currentSelection);
407+
}
357408
if (!currentSelection.rangeCount) {
358409
return false;
359410
}
@@ -487,7 +538,9 @@ const Selection = Module({
487538
updateRange (range, opts={}) {
488539
const { mediator, props } = this;
489540
const currentSelection = this.getCurrentSelection();
490-
541+
if (!currentSelection) {
542+
console.log('updateRange:currentSelection', currentSelection);
543+
}
491544
if (opts.silent) {
492545
props.silenceChanges.push(true); // silence removeAllRanges
493546
props.silenceChanges.push(true); // silence addRange
@@ -634,6 +687,8 @@ const Selection = Module({
634687
const startOffset = startCoordinates.pop();
635688
const endOffset = endCoordinates.pop();
636689

690+
console.log('selectByCoordinates', { rangeCoordinates });
691+
637692
let startContainer = dom.el[0];
638693
let endContainer = dom.el[0];
639694

@@ -647,6 +702,8 @@ const Selection = Module({
647702
endContainer = endContainer.childNodes[endIndex];
648703
}
649704

705+
console.log({ startContainer, endContainer, startLength: startContainer.length, endLength: endContainer.length, startOffset, endOffset });
706+
650707
newRange.setStart(startContainer, startOffset);
651708
newRange.setEnd(endContainer, endOffset);
652709

src/scripts/utils/DOM.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,11 @@ const DOM = {
253253

254254
closestElement(node) {
255255
let returnNode = node;
256+
console.log('closestElement', node);
256257

257-
while (returnNode.nodeType !== 1) {
258+
while (returnNode && returnNode.nodeType !== 1) {
258259
returnNode = returnNode.parentNode;
260+
console.log('returnNode', returnNode);
259261
}
260262

261263
return returnNode;
@@ -553,10 +555,13 @@ const DOM = {
553555

554556
trimNodeText (node) {
555557
if (node.nodeType === Node.TEXT_NODE) {
556-
const trimmedText = node.textContent
557-
.replace(/\s{2,}/g, ' ')
558-
.replace(/\r?\n|\r/g, '')
559-
.trim();
558+
const parentElement = DOM.closestElement(node);
559+
let trimmedText = node.textContent
560+
.replace(/\s{2,}/g, ' ')
561+
.replace(/\r?\n|\r/g, '');
562+
if (!DOM.nodeIsInline(parentElement)) {
563+
trimmedText = trimmedText.trim();
564+
}
560565
node.textContent = trimmedText;
561566
} else {
562567
node.childNodes.forEach((childNode) => {
@@ -579,6 +584,20 @@ const DOM = {
579584
return HTMLString;
580585
},
581586

587+
nodeIsInline (node) {
588+
const inlineTagNames = ['B', 'STRONG', 'I', 'U', 'S', 'SUP', 'SUB'];
589+
590+
if (!node) {
591+
return false;
592+
}
593+
594+
if (node.nodeType !== Node.ELEMENT_NODE) {
595+
return true;
596+
} else {
597+
return inlineTagNames.indexOf(node.nodeName) < 0;
598+
}
599+
},
600+
582601
//Pseudo-private methods
583602
_getGetMethodName(selector) {
584603
let methodName = null;

test/server/html/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ <h1>Typester test server</h1>
177177
node.childNodes.forEach(function (childNode) {
178178
if (childNode.nodeType === Node.TEXT_NODE) {
179179
if (childNode.textContent.trim().length) {
180-
appendHtmlText(childNode.textContent.trim(), opts.indentation + 1, true);
180+
appendHtmlText(childNode.textContent.replace(/\s/g, '\u00B7'), opts.indentation + 1, true);
181181
}
182182
} else {
183183
appendHtmlText(generateHtmlText(childNode, {

test/unit/modules/BaseFormatter.spec.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,14 @@ describe('modules/BaseFormatter', function () {
5353

5454
it('should clean html on export', () => {
5555
const canvasBody = mediator.get('canvas:body');
56-
canvasBody.innerHTML = `
57-
<h1><span>Heading copy</span></h1>
56+
canvasBody.innerHTML = `<h1><span>Heading copy</span></h1>
5857
<div><h2>Sub heading copy</h2></div>
5958
<article>
6059
<p>First paragraph</p>
6160
<span style='font-size: 16px;'>After first paragraph</span>
6261
<p><font>Second paragraph</font></p>
6362
</article>
64-
<ul><li><font>List item 1</font></li></ul>
65-
`;
63+
<ul><li><font>List item 1</font></li></ul>`;
6664
selectionHelper.selectFromTo(canvasBody.firstChild, 0, canvasBody.firstChild, 1);
6765
mediator.exec('format:import:from:canvas');
6866
if (!/\w+/.test(canvasBody.firstChild.textContent) && !/\w+/.test(editableEl.firstChild.textContent)) {

test/unit/modules/Commands.spec.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Mediator from '../../../src/scripts/core/Mediator';
44
import Commands from '../../../src/scripts/modules/Commands';
55
import Config from '../../../src/scripts/modules/Config';
66
import selectionHelper from '../helpers/selection';
7+
import DOM from '../../../src/scripts/utils/DOM';
78

89
describe('modules/Commands', function () {
910
let mediator, $editableEl, editableEl;
@@ -66,6 +67,12 @@ describe('modules/Commands', function () {
6667
style: 'BLOCKQUOTE'
6768
});
6869

70+
71+
const blockquoteParagraphs = editableEl.querySelectorAll('blockquote p');
72+
blockquoteParagraphs.forEach((paragraph) => {
73+
DOM.unwrap(paragraph);
74+
});
75+
6976
expect(editableEl.innerHTML).toBe(`<blockquote>${contentBlockText}</blockquote>`);
7077
});
7178
});

test/unit/modules/ListFormatter.spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,30 @@ describe('modules/ListFormatter', function () {
4040
afterEach(() => {
4141
editableEl.innerHTML = '';
4242
mediator.emit('app:destroy');
43+
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
4344
});
4445

4546
it('should toggle ordered lists', () => {
4647
setEditableElHTML();
4748
expect(editableEl.getElementsByTagName('ol').length).toBe(0);
4849
expect(editableEl.getElementsByTagName('li').length).toBe(0);
4950

51+
console.log('---------------------------------------------------------------------------------------[2:start]')
5052
selectionHelper.selectFirstAndLastTextNodes(editableEl);
53+
console.log(document.getSelection().toString());
5154
mediator.exec('format:list', orderedListOpts);
55+
console.log('---------------------------------------------------------------------------------------[2:end]')
5256
expect(editableEl.getElementsByTagName('ol').length).toBe(1);
5357
expect(editableEl.getElementsByTagName('li').length).toBe(5);
5458

59+
console.log('---------------------------------------------------------------------------------------[2:start]')
5560
selectionHelper.selectFirstAndLastTextNodes(editableEl);
61+
console.log(document.getSelection().toString());
5662
mediator.exec('format:list', orderedListOpts);
63+
console.log('---------------------------------------------------------------------------------------[2:end]')
5764
expect(editableEl.getElementsByTagName('ol').length).toBe(0);
5865
expect(editableEl.getElementsByTagName('li').length).toBe(0);
66+
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
5967

6068
});
6169

0 commit comments

Comments
 (0)