Skip to content

Commit

Permalink
Merge pull request #111 from ceautery/issue21
Browse files Browse the repository at this point in the history
Fix for #21
  • Loading branch information
bhollis committed Oct 10, 2015
2 parents da81416 + 16e5ce8 commit 5c8cb8b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
3 changes: 3 additions & 0 deletions lib/jsonformatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ JSONFormatter.prototype = {
else if (valueType == 'number') {
return this.decorateWithSpan(value, 'num');
}
else if (valueType == 'string' && value.charCodeAt(0) == 8203 && !isNaN(value.slice(1))) {
return this.decorateWithSpan(value, 'num');
}
else if (valueType == 'string') {
if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
return '<a href="' + this.htmlEncode(value) + '"><span class="q">&quot;</span>' + this.jsString(value) + '<span class="q">&quot;</span></a>';
Expand Down
52 changes: 51 additions & 1 deletion lib/jsonview.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,56 @@ var JSONView = Class({
this.listener.onStartRequest(this.channel, aContext);
},

/*
* Takes a JSON string and replaces number values with strings with a leading \u200B.
* Prior to this, it doubles any pre-existing \u200B characters. This Unicode value is
* a zero-width space, so doubling it won't affect the HTML view.
*
* This addresses JSONView issue 21 (https://github.com/bhollis/jsonview/issues/21),
* where numbers larger than Number.MAX_SAFE_INTEGER get rounded to the nearest value
* that can fit in the mantissa. Instead we will string encode those numbers, and rely
* on JSONFormatter to detect the leading zero-width space, check the remainder of the
* string with !isNaN() for number-ness, and render it with number styling, sans-quotes.
*/
safeStringEncodeNums: function(jsonString) {
function betweenOrderedPairs(numberIndex) {
function betweenPair(pair, pairIndex, o) {
if (numberIndex < pair[0]) return false;
if (numberIndex <= pair[1]) return true;
if (pairIndex + 1 == o.length) return false;
// orderedPairs.shift();
}
return orderedPairs.some(betweenPair);
}

// Find unescaped quotes by searching for a non-backslash followed by 0 or even
// pairs of backslashes, then a quote
var quoteFinder = /[^\\](\\\\)*(?=")/g,

// JSON legal number matcher, Andrew Cheong, http://stackoverflow.com/questions/13340717
numberFinder = /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/g,
quoteMap = [], orderedPairs = [],
viewString = jsonString.replace(/\u200B/g, "\u200B\u200B"),
match;

while((match = quoteFinder.exec(viewString)) != null) {
quoteMap.push(match.index + match[0].length);
}

// If we don't have an even number of quotes, bail and parse viewString as-is.
if (quoteMap.length % 2 !== 0) {
return viewString;
}

while(quoteMap.length) {
orderedPairs.push(quoteMap.splice(0, 2));
}

return viewString.replace(numberFinder,
(match, ndx) => betweenOrderedPairs(ndx) ? match : '"\u200B' + match + '"'
);
},

// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
/*
Expand All @@ -95,7 +145,7 @@ var JSONView = Class({
var outputDoc = '';

try {
var jsonObj = JSON.parse(this.data);
var jsonObj = JSON.parse(this.safeStringEncodeNums(this.data));
outputDoc = this.jsonFormatter.jsonToHTML(jsonObj, this.uri);
} catch (e) {
outputDoc = this.jsonFormatter.errorPage(e, this.data, this.uri);
Expand Down
36 changes: 36 additions & 0 deletions tests/issue21.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[{
"asset_id": "336541846568177664",
"versions-numbersShouldMatchURLSuffix": [
[336541846568177665, "http://aarons-mbp-2011.local/api/assets/336541846568177664/336541846568177665"],
[336541849961369600, "http://aarons-mbp-2011.local/api/assets/336541846568177664/336541849961369600"]
]
},
{
"files": {
"vulture.jpg": {
"name": "vulture.jpg",
"exif": {},
"tags": [
"source"
]
}
},
"updated": {
"timestamp": "2012-07-17T03:17:08Z",
"user": "[email protected]"
},
"tags": [
""
],
"taxonomy": {},
"related": {},
"id-shouldEndWith664": 336541846568177664,
"title": "vulture",
"created": {
"timestamp": "2012-07-17T03:17:08Z",
"user": "[email protected]"
},
"version-shouldEndWith665": 336541846568177665,
"storage_app": "reflib",
"storage_bucket": "336541846568177666"
}]

0 comments on commit 5c8cb8b

Please sign in to comment.