-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
85 lines (75 loc) · 2.65 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* global define */
void (function (root, factory) {
if (typeof define === 'function' && define.amd) define(factory)
else if (typeof exports === 'object') module.exports = factory()
else root.unorphan = factory()
}(this, function () {
var nbsp = '\xA0'
var TEXT = 3
var ELEMENT = 1
unorphan.reverseWalk = reverseWalk
return unorphan
function unorphan (n, options) {
if (!options) options = {}
if (!n) return
if (typeof n === 'string') { /* selector string */
unorphan(document.querySelectorAll(n), options)
} else if (n.nodeType === ELEMENT) {
unorphanElement(n, options)
} else if (n.nodeType === TEXT) {
n.nodeValue = n.nodeValue.replace(/\s+([^\s]*)\s*$/, nbsp + '$1')
} else if (n.length) { /* node list or jQuery object */
for (var i = 0, len = n.length; i < len; i++) { unorphan(n[i], options) }
}
}
/*
* Recursively checks text nodes in an element and replaces the first
* eligible space it encounters to a non-breaking space.
*/
function unorphanElement (node, options) {
var dirty /* keep track if we've seen a non-space character yet */
var paused /* stop processing text nodes until the next <br> */
reverseWalk(node, function (n) {
if (n.nodeType === TEXT && !paused) {
var text = n.nodeValue
if (/\s+[^\s]+\s*$/.test(text) && !dirty) {
// " xx" or " xx " => "_xx" (done!)
n.nodeValue = text.replace(/\s+([^\s]+)\s*$/, nbsp + '$1')
if (!options.br) return false
paused = true
} else if (/^[^\s]+\s*$/.test(text) && !dirty) {
// "xx " or "xx" => pass
dirty = true
} else if (/\s/.test(text) && dirty) {
// " " => "_"
// "xx " => "xx_"
// "xx x" => "xx_x" (done!)
n.nodeValue = text.replace(/\s+([^\s]*)$/, nbsp + '$1')
if (!options.br) return false
paused = true
}
} else if (n.nodeType === ELEMENT) {
// Start over when encountering <br>
if (n.nodeName.toLowerCase() === 'br') {
paused = false
dirty = false
}
}
})
}
/*
* Internal: iterates *backwards* through all available text and element
* subnodes. Abort by returning `false` on the block.
*/
function reverseWalk (node, fn) {
for (var i = node.childNodes.length - 1; i >= 0; i--) {
var sub = node.childNodes[i]
if (sub.nodeType === TEXT) {
if (fn(sub) === false) return false
} else if (sub.nodeType === ELEMENT) {
if (fn(sub) === false) return false
if (reverseWalk(sub, fn) === false) return false
}
}
}
})); // eslint-disable-line