Skip to content
This repository has been archived by the owner on May 12, 2020. It is now read-only.

Commit

Permalink
Treat the first space text character after a text:tab as significant …
Browse files Browse the repository at this point in the history
…whitespace

A space character is considered significant when it follows either a
non-space character element (e.g., text:tab), or a non-space character.

From the ODF specs (6.1.3, <text:s/>):
This element shall be used to represent the second and all following
“ “ (U+0020, SPACE) characters in a sequence of “ “ (U+0020, SPACE)
characters.
  • Loading branch information
peitschie committed Nov 21, 2013
1 parent 503ea1d commit 9ca633a
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 15 deletions.
25 changes: 13 additions & 12 deletions webodf/lib/odf/OdfUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,23 +191,23 @@ odf.OdfUtils = function OdfUtils() {
}
this.isCharacterElement = isCharacterElement;
/**
* Determine if the node is a whitespace character element.
* Determine if the node is a <text:s/> character element.
* @param {?Node} e
* @return {!boolean}
*/
function isWhitespaceElement(e) {
function isSpaceElement(e) {
var n = e && e.localName,
ns,
r = false;
if (n) {
ns = e.namespaceURI;
if (ns === textns) {
r = n === "s" || n === "tab";
r = n === "s";
}
}
return r;
}
this.isWhitespaceElement = isWhitespaceElement;
this.isSpaceElement = isSpaceElement;
/**
* @param {!Node} node
* @return {!Node}
Expand Down Expand Up @@ -255,12 +255,13 @@ odf.OdfUtils = function OdfUtils() {

/**
* Walk to the left along the DOM and return true if the first thing
* encountered is either a non-whitespace character or a non-whitespace
* character element. Walking goes through grouping elements.
* encountered is either a non-whitespace text character or a non-space
* character element (i.e., any character element other than <text:s/>).
* Walking goes through grouping elements.
* @param {?Node} node the first node to scan
* @return {!boolean}
*/
function scanLeftForNonWhitespace(node) {
function scanLeftForNonSpace(node) {
var r = false;
while (node) {
if (node.nodeType === Node.TEXT_NODE) {
Expand All @@ -272,15 +273,15 @@ odf.OdfUtils = function OdfUtils() {
);
}
} else if (isCharacterElement(node)) {
r = isWhitespaceElement(node) === false;
r = isSpaceElement(node) === false;
node = null;
} else {
node = previousNode(node);
}
}
return r;
}
this.scanLeftForNonWhitespace = scanLeftForNonWhitespace;
this.scanLeftForNonSpace = scanLeftForNonSpace;
/**
* Walk to the left along the DOM and return the type of the first
* thing encountered.
Expand All @@ -299,7 +300,7 @@ odf.OdfUtils = function OdfUtils() {
if (!isODFWhitespace(text.substr(text.length - 1, 1))) {
r = 1; // character found
} else if (text.length === 1) {
r = scanLeftForNonWhitespace(previousNode(node)) ? 2 : 0;
r = scanLeftForNonSpace(previousNode(node)) ? 2 : 0;
} else {
r = isODFWhitespace(text.substr(text.length - 2, 1)) ? 0 : 2;
}
Expand Down Expand Up @@ -426,7 +427,7 @@ odf.OdfUtils = function OdfUtils() {
// First whitespace after a character is significant
result = true;
}
} else if (scanLeftForNonWhitespace(previousNode(textNode))) {
} else if (scanLeftForNonSpace(previousNode(textNode))) {
// If the first character found scanning to the left is non-whitespace, this might still be significant
result = true;
}
Expand All @@ -449,7 +450,7 @@ odf.OdfUtils = function OdfUtils() {
*/
this.isDowngradableSpaceElement = function(node) {
if (node.namespaceURI === textns && node.localName === "s") {
return scanLeftForNonWhitespace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node));
return scanLeftForNonSpace(previousNode(node)) && scanRightForAnyCharacter(nextNode(node));
}
return false;
};
Expand Down
4 changes: 2 additions & 2 deletions webodf/lib/ops/TextPositionFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ ops.TextPositionFilter = function TextPositionFilter(getRootNode) {
}
} else {
// check if there is a non-whitespace character or
// character element in a preceding node
// character element (other than text:s) in a preceding node
leftNode = odfUtils.previousNode(container);
if (odfUtils.scanLeftForNonWhitespace(leftNode)) {
if (odfUtils.scanLeftForNonSpace(leftNode)) {
r = FILTER_ACCEPT;
}
}
Expand Down
7 changes: 7 additions & 0 deletions webodf/tests/odf/OdfUtilsTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ odf.OdfUtilsTests = function OdfUtilsTests(runner) {

r.shouldBe(t, "t.isDowngradable", "true");
}
function isDowngradableWhitespace_DowngradesFirstSpaceAfterTab() {
t.doc = createDocument("<text:p><text:tab> </text:tab><text:s> </text:s>b</text:p>");
t.isDowngradable = t.odfUtils.isDowngradableSpaceElement(t.doc.childNodes[1]);

r.shouldBe(t, "t.isDowngradable", "true");
}
function isDowngradableWhitespace_DoesNotDowngradeTrailingSpace() {
t.doc = createDocument("<text:p>a<text:s> </text:s></text:p>");
t.isDowngradable = t.odfUtils.isDowngradableSpaceElement(t.doc.childNodes[1]);
Expand Down Expand Up @@ -271,6 +277,7 @@ odf.OdfUtilsTests = function OdfUtilsTests(runner) {
getImageElements_ReturnTwoImages,

isDowngradableWhitespace_DowngradesFirstSpaceAfterChar,
isDowngradableWhitespace_DowngradesFirstSpaceAfterTab,
isDowngradableWhitespace_DoesNotDowngradeTrailingSpace,
isDowngradableWhitespace_DoesNotDowngradeLeading,
isDowngradableWhitespace_DoesNotDowngradeAfterSpace
Expand Down
3 changes: 3 additions & 0 deletions webodf/tests/ops/OdtDocumentTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,9 @@ ops.OdtDocumentTests = function OdtDocumentTests(runner) {
testCursorPositions("<text:p><text:span>|<text:s> </text:s>|</text:span></text:p>");
// TODO behaviour is different from README_cursorpositions
// cursorPositionsTest("<text:p> <text:span>|A| |</text:span> <text:s></text:s>| <text:span><text:s> </text:s>|B|</text:span> </text:p>");
testCursorPositions("<text:p>|<text:tab> </text:tab>|<text:s> </text:s>|<text:s> </text:s>|</text:p>");
testCursorPositions("<text:p>|<text:tab> </text:tab>| |<text:s> </text:s>|</text:p>");
testCursorPositions("<text:p>|a| | <text:s> </text:s>| </text:p>");
}
function testAvailablePositions_DrawElements() {
testCursorPositions("<text:p>|<draw:frame text:anchor-type=\"as-char\"><draw:image><office:binary-data>data</office:binary-data></draw:image></draw:frame>|</text:p>");
Expand Down
12 changes: 11 additions & 1 deletion webodf/tests/ops/operationtests.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@
</ops>
<after><office:text><text:p>a b</text:p></office:text></after>
</test>

<test name="InsertText_withSameCursor_AfterSpace2">
<before><office:text><text:p>a<text:s> </text:s></text:p><text:p/></office:text></before>
<ops>
Expand Down Expand Up @@ -288,6 +287,17 @@
</ops>
<after><office:text><text:p>a bc</text:p></office:text></after>
</test>
<test name="InsertText_AfterSpaceAndTab_InNewParagraph">
<before><office:text><text:p/></office:text></before>
<ops>
<op optype="SplitParagraph" position="0"/>
<op optype="InsertText" position="1" text="&#x9; "/>
<op optype="SplitParagraph" position="4"/>
<op optype="InsertText" position="5" text="U"/>
<op optype="RemoveText" position="0" length="1"/>
</ops>
<after><office:text><text:p><text:tab>&#x9;</text:tab> <text:s> </text:s></text:p><text:p>U</text:p></office:text></after>
</test>
<test name="RemoveSpace">
<before><office:text><text:p><text:s> </text:s></text:p></office:text></before>
<ops>
Expand Down

0 comments on commit 9ca633a

Please sign in to comment.