diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/js/urweb.js | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js index 931ab1f5..357e4c1c 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -7,6 +7,61 @@ function needsDynPrefix() { return scripts.length == 0; } +// Codepoint implementations brought from https://norbertlindenberg.com/2012/05/ecmascript-supplementary-characters/#String +if (!String.fromCodePoint) { + String.fromCodePoint = function () { + var chars = [], i; + for(i = 0; i < arguments.length; ++i) { + var c = Number(arguments[i]); + if (!isFinite(c) || c < 0 || c > 0x10FFFF || Math.floor(c) !== c) { + throw new RangeError("Invalid code point " + c); + } + if (c < 0x10000) { + chars.push(c); + } else { + c -= 0x10000; + chars.push((c >> 10) + 0xD800); + chars.push((c % 0x400) + 0xDC00); + } + } + return String.fromCharCode.apply(undefined, chars); + }; + + String.prototype.codePointAt = function (index) { + var str = String(this); + if (index < 0 || index >= str.length) { + return undefined; + } + var first = str.charCodeAt(index); + if (first >= 0xD800 && first <= 0xDBFF && str.length > index + 1) { + var second = str.charCodeAt(index + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { + return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000; + } + } + return first; + }; +} + +function iterateString(s, fn) { + var strIdx = 0, idx = 0, res, cp; + for (; strIdx < s.length ;) { + cp = s.codePointAt(strIdx); + if (fn) { + res = fn(String.fromCodePoint(cp), idx, strIdx); + if (res === false) return; + } + strIdx += cp > 0xFFFF ? 2 : 1; + ++idx; + } +} + +function strSplit(s) { + var chars = []; + iterateString(s, function(c) { chars.push(c); }); + return chars; +} + var dynPrefix = needsDynPrefix() ? "<span style=\"display:none\">A</span>" : ""; // Function versions of operators @@ -2438,11 +2493,24 @@ function s2b(s) { return s == "True" ? true : s == "False" ? false : null; } function s2be(s) { return s == "True" ? true : s == "False" ? false : er("Illegal Boolean " ^ s); } function id(x) { return x; } -function sub(s, i) { return Array.from(s)[i]; } -function suf(s, i) { return Array.from(s).slice(i).join(""); } -function slen(s) { return Array.from(s).length; } +function sub(s, i) { + var ch = undefined; + iterateString(s, function(c, idx) { if (idx == i) { ch = c; return false; }}); + return ch; +} +function suf(s, i) { + var off = s.length; + iterateString(s, function(_, idx, sidx) { if (idx == i) { off = sidx; return false; } }); + return s.substring(off); +} +function slen(s) { + var len = 0; + iterateString(s, function(){ ++len;}); + return len; +} function sidx(s, ch) { - var r = Array.from(s).indexOf(ch); + var r = -1; + iterateString(s, function(c, idx){ if (c == ch) { r = idx; return false; } }); if (r == -1) return null; else @@ -2450,8 +2518,8 @@ function sidx(s, ch) { } function ssidx(h, n) { if (n == "") return 0; - var ah = Array.from(h); - var an = Array.from(n); + var ah = strSplit(h); + var an = strSplit(n); var i = 0, y = 0; var top = ah.length - an.length + 1; if (top < 0) top = 0; @@ -2474,8 +2542,8 @@ function ssidx(h, n) { } function sspn(s, chs) { - var s2 = Array.from(s); - var chs2 = Array.from(chs); + var s2 = strSplit(s); + var chs2 = strSplit(chs); for (var i = 0; i < s2.length; ++i) if (chs2.indexOf(s2[i]) != -1) @@ -2483,6 +2551,7 @@ function sspn(s, chs) { return s2.length; } + function schr(s, ch) { var r = s.indexOf(ch); if (r == -1) @@ -2491,7 +2560,7 @@ function schr(s, ch) { return s.substring(r); } function ssub(s, start, len) { - return Array.from(s).slice(start, start+len).join(""); + return strSplit(s).slice(start, start+len).join(""); } function strlenGe(s, len) { return slen(s) >= len; @@ -3228,7 +3297,7 @@ function bless(s) { var maxCh = chr(127); function blessData(s) { - var chars = Array.from(s); + var chars = strSplit(s); for (var i = 0; i < chars.length; ++i) { var c = chars[i]; @@ -3243,7 +3312,7 @@ function blessData(s) { // CSS validation function atom(s) { - var chars = Array.from(s); + var chars = strSplit(s); for (var i = 0; i < chars.length; ++i) { var c = chars[i]; @@ -3255,7 +3324,7 @@ function atom(s) { } function css_url(s) { - var chars = Array.from(s); + var chars = strSplit(s); for (var i = 0; i < chars.length; ++i) { var c = chars[i]; @@ -3268,7 +3337,7 @@ function css_url(s) { } function property(s) { - var chars = Array.from(s); + var chars = strSplit(s); if (chars.length <= 0) er("Empty CSS property"); |