summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/js/urweb.js95
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");