Skip to content

Commit

Permalink
Merge pull request #785 from w3c/fix_whitespace
Browse files Browse the repository at this point in the history
Fix whitespace issues
  • Loading branch information
Marcos Cáceres committed May 25, 2016
2 parents e326691 + d7c68c3 commit 9215df8
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 70 deletions.
6 changes: 5 additions & 1 deletion js/core/markdown.js
Expand Up @@ -261,7 +261,11 @@ define([
processBlockLevelElements(newBody);
var dirtyHTML = toHTML(newBody.innerHTML);
// Markdown parsing sometimes inserts empty p tags
var cleanHTML = dirtyHTML.replace(/<p>\s*<\/p>/gm, "");
var cleanHTML = dirtyHTML
.replace(/<p>\s*<\/p>/gm, "")
// beautifer has a bad time with "\n&quot;<element"
// https://github.com/beautify-web/js-beautify/issues/943
.replace(/\n&quot;</mg, " &quot;<");
var beautifulHTML = beautify.html_beautify(cleanHTML, beautifyOps);
newBody.innerHTML = beautifulHTML;
// Remove links where class pre.nolinks
Expand Down
147 changes: 78 additions & 69 deletions js/core/utils.js
Expand Up @@ -13,7 +13,6 @@ define(
msg.pub("end", "core/utils");
cb();
}
,
/**
* Allows a node to be swapped into a different document at
* some insertion point(Element). This function is useful for
Expand All @@ -28,7 +27,7 @@ define(
* insertion point (node) - or just appended, if
* the element has no children.
*/
makeOwnerSwapper: function(node) {
, makeOwnerSwapper: function(node) {
if(!(node instanceof Node)){
throw TypeError();
}
Expand All @@ -43,21 +42,27 @@ define(
};
}
, calculateLeftPad: function(text) {
if (typeof text !== "string") {
throw new TypeError("Invalid input");
}
var spaceOrTab = /^[\ |\t]*/;
// Find smallest padding value
var leftPad = text
.split("\n")
.filter(function (item){
.filter(function(item) {
return item;
})
.map(function(item){
.reduce(function(smallest, item) {
// can't go smaller than 0
if (smallest === 0) {
return smallest;
}
var match = item.match(spaceOrTab)[0] || "";
return (match) ? match.length : 0;
})
.sort()
.shift(1);
return leftPad || 0;
}
return Math.min(match.length, smallest);
}, +Infinity);
return (leftPad === +Infinity) ? 0 : leftPad;
}

/**
* Makes a ES conforming iterator allowing objects to be used with
* methods that can interface with Iterators (Array.from(), etc.).
Expand Down Expand Up @@ -96,6 +101,10 @@ define(
throw TypeError("Invalid input");
}

if(text === "\n"){
return "\n";
}

function isEmpty(node) {
return node.textContent === "";
}
Expand Down Expand Up @@ -135,68 +144,68 @@ define(
.map(function(textNode) {
return textNode.textContent;
})
.reduce(function(collector, textContent) {
if (collector) {
return collector;
}
var result = textContent
.split("\n")
.find(function(text) {
var result = /^[\s|\w]+/gm.test(text);
return result;
});
return result || "";
}, "");
var baseCol = this.calculateLeftPad(firstPaddedLine);
.find(function(textContent) {
var result = /^[\#|\s|\w]+/gm.test(textContent);
return result;
});
// There is no padding, so just return what we started with.
if (!firstPaddedLine) {
return text;
}

var baseColumn = this.calculateLeftPad(firstPaddedLine);

// Only if we have a baseColumn to work with ...
// With only the text nodes that are not children of pre elements,
// we left align all those text nodes.
Array
.from(doc.body.childNodes)
.filter(isTextNode)
.filter(function(textNode) {
// 🎵 Hey, processor! Leave those pre's alone! 🎵
return !filterParentIsPre(textNode);
})
.filter(function(textNode) {
// we don't care about last nodes that are just white space
var isLastChild = textNode.parentElement.lastChild === textNode;
var isJustWS = isWhiteSpace(textNode);
return !(isLastChild && isJustWS);
})
.map(function toTrimmedTextNode(textNode) {
var rawText = textNode.textContent;
// We remove tailing space on the right, which is just there
// to pad out tags like:
// <div>
// <div>
// Next line has 2 spaces hidden!
// __</div>
// </div>
//
var trimmedRight = rawText.trimRight();
var trimBy = this.calculateLeftPad(trimmedRight) || baseCol;
if (!trimBy) {
return null; //nothing to do
}
var exp = "^ {" + trimBy + "}";
var startTrim = new RegExp(exp, "gm");
var trimmedText = (trimBy) ? rawText.replace(startTrim, "") : rawText;
var newNode = textNode.ownerDocument.createTextNode(trimmedText);
// We can then swap the old with the new
return {
oldNode: textNode,
newNode: newNode,
};
}.bind(this))
.filter(function(nodes) {
return nodes;
})
.forEach(function(nodes) {
var oldNode = nodes.oldNode;
var newNode = nodes.newNode;
oldNode.parentElement.replaceChild(newNode, oldNode);
});
if(baseColumn){
Array
.from(doc.body.childNodes)
.filter(isTextNode)
.filter(function(textNode) {
// 🎵 Hey, processor! Leave those pre's alone! 🎵
return !filterParentIsPre(textNode);
})
.filter(function(textNode) {
// we don't care about last nodes that are just white space
var isLastChild = textNode.parentElement.lastChild === textNode;
var isJustWS = isWhiteSpace(textNode);
return !(isLastChild && isJustWS);
})
.map(function toTrimmedTextNode(textNode) {
var rawText = textNode.textContent;
// We remove tailing space on the right, which is just there
// to pad out tags like:
// <div>
// <div>
// Next line has 2 spaces hidden!
// __</div>
// </div>
//
var trimmedRight = rawText.trimRight();
var trimBy = this.calculateLeftPad(trimmedRight) || baseColumn;
if (!trimBy) {
return null; //nothing to do
}
var exp = "^ {" + trimBy + "}";
var startTrim = new RegExp(exp, "gm");
var trimmedText = (trimBy) ? rawText.replace(startTrim, "") : rawText;
var newNode = textNode.ownerDocument.createTextNode(trimmedText);
// We can then swap the old with the new
return {
oldNode: textNode,
newNode: newNode,
};
}.bind(this))
.filter(function(nodes) {
return nodes;
})
.forEach(function(nodes) {
var oldNode = nodes.oldNode;
var newNode = nodes.newNode;
oldNode.parentElement.replaceChild(newNode, oldNode);
});
}
var nodeIterator = doc.createNodeIterator(doc.body, NodeFilter.SHOW_TEXT, filterLastChildIsPadding);
var iterable = this.toESIterable(nodeIterator.nextNode.bind(nodeIterator));
// Remove trailing whitespace nodes
Expand Down
31 changes: 31 additions & 0 deletions tests/spec/core/utils-spec.js
Expand Up @@ -8,6 +8,37 @@ describe("Core - Utils", function() {
});
});

describe("calculateLeftPad()", function(){
it("throws given invalid input", function(){
expect(function(){
expect(utils.calculateLeftPad());
}).toThrow();
expect(function(){
expect(utils.calculateLeftPad({}));
}).toThrow();
expect(function(){
expect(utils.calculateLeftPad(123));
}).toThrow();
expect(function(){
expect(utils.calculateLeftPad(null));
}).toThrow();
});
it("calculates the smallest left padding of multiline text", function(done){
expect(utils.calculateLeftPad("")).toEqual(0);
expect(utils.calculateLeftPad("\n \n ")).toEqual(2);
expect(utils.calculateLeftPad(" ")).toEqual(25);
expect(utils.calculateLeftPad(" a ")).toEqual(1);
expect(utils.calculateLeftPad(" \n a ")).toEqual(1);
expect(utils.calculateLeftPad(" \n a ")).toEqual(1);
expect(utils.calculateLeftPad("\n \n \n ")).toEqual(4);
expect(utils.calculateLeftPad("\n \n \n ")).toEqual(2);
expect(utils.calculateLeftPad("\n \n \n \n ")).toEqual(2);
expect(utils.calculateLeftPad("\n\n\n\n\n\n\n\n\n\n")).toEqual(0);
expect(utils.calculateLeftPad(" \n\n\n\n\n \n\n\n\n\n ")).toEqual(2);
done();
});
});

describe("makeOwnerSwapper()", function() {
it("throws if passed something that is not a node", function(done) {
expect(function() {
Expand Down

0 comments on commit 9215df8

Please sign in to comment.