Skip to content

Commit a6692b8

Browse files
committed
Fixed a regression where floating-point numbers were truncated to integers.
1 parent bf7a463 commit a6692b8

8 files changed

+128
-7
lines changed

.vscode/settings.json

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"editor.codeActionsOnSave": {
99
"source.fixAll": "explicit"
1010
},
11-
"jest.jestCommandLine": "pnpm test --",
1211
"[javascript]": {
1312
"editor.codeActionsOnSave": {
1413
"source.organizeImports": "never"

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## JSONView 3.0.1
2+
3+
- Fixed a regression where floating-point numbers were truncated to integers.
4+
15
## JSONView 3.0.0
26

37
- JSONView is now compatible with Manifest V3, which is required in Chrome.

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- [Install for Firefox](https://addons.mozilla.org/en-US/firefox/addon/jsonview/)
66
- [Install for Chrome](https://chrome.google.com/webstore/detail/jsonview/gmegofmjomhknnokphhckolhcffdaihd)
77
- [Install for Edge](https://microsoftedge.microsoft.com/addons/detail/jsonview/kmpfgkgaimakokfhgdahhiaaiidiphco)
8+
- There is no version for Safari because it costs $100/year to publish a free extension to the Mac App Store.
89

910
Normally, when encountering a [JSON](http://json.org) document (content type `application/json`), Firefox simply prompts you to download the view. With the JSONView extension, JSON documents are shown in the browser similar to how XML documents are shown. The document is formatted, highlighted, and arrays and objects can be collapsed. Even if the JSON document contains errors, JSONView will still show the raw text.
1011

@@ -49,3 +50,7 @@ pnpm start
4950
```
5051

5152
`jsonview-chrome.zip` and `jsonview-firefox.zip` can then be manually uploaded to the extension sites.
53+
54+
- Chrome: https://chrome.google.com/webstore/devconsole/
55+
- Firefox: https://addons.mozilla.org/en-US/developers/addons
56+
- Edge: https://partner.microsoft.com/en-us/dashboard/microsoftedge/overview

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
3-
"version": "3.0.0",
3+
"version": "3.0.1",
44
"name": "jsonview",
55
"title": "JSONView",
66
"description": "View JSON documents in the browser.",

src/jsonformatter.test.ts

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { strict as assert } from "node:assert";
2+
import test from "node:test";
3+
import { valueToHTML } from "./jsonformatter.js";
4+
import { safeStringEncodeNums } from "./safe-encode-numbers.js";
5+
6+
const jsonContent = [
7+
[`{}`, `{ }`],
8+
[
9+
`{ "hey": "guy" }`,
10+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.hey"><span class="q">&quot;</span>hey<span class="q">&quot;</span></span>: <span class="string">&quot;guy&quot;</span></li></ul><span class="spacer"></span>}`,
11+
],
12+
[
13+
`{ "float": 10.5 }`,
14+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.float"><span class="q">&quot;</span>float<span class="q">&quot;</span></span>: <span class="num">10.5</span></li></ul><span class="spacer"></span>}`,
15+
],
16+
[
17+
`{ "10.5": "hello" }`,
18+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop quoted" title=""><span class="q">&quot;</span>10.5<span class="q">&quot;</span></span>: <span class="string">&quot;hello&quot;</span></li></ul><span class="spacer"></span>}`,
19+
],
20+
[
21+
// bigger than max safe integer
22+
`{ "anumber": 9117199254740991 }`,
23+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.anumber"><span class="q">&quot;</span>anumber<span class="q">&quot;</span></span>: <span class="num">9117199254740992</span></li></ul><span class="spacer"></span>}`,
24+
],
25+
[
26+
`{ "anobject": {"whoa": "nuts","anarray": [1,2,"thr<h1>ee"], "more":"stuff"} }`,
27+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.anobject"><span class="q">&quot;</span>anobject<span class="q">&quot;</span></span>: <span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.anobject.whoa"><span class="q">&quot;</span>whoa<span class="q">&quot;</span></span>: <span class="string">&quot;nuts&quot;</span>,</li><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.anobject.anarray"><span class="q">&quot;</span>anarray<span class="q">&quot;</span></span>: <span class="collapser"></span>[<ul class="array collapsible"><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="num">1</span>,</li><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="num">2</span>,</li><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">&quot;thr&lt;h1&gt;ee&quot;</span></li></ul><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span>],</li><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.anobject.more"><span class="q">&quot;</span>more<span class="q">&quot;</span></span>: <span class="string">&quot;stuff&quot;</span></li></ul><span class="spacer">&nbsp;&nbsp;</span>}</li></ul><span class="spacer"></span>}`,
28+
],
29+
[
30+
`{ "awesome": true }`,
31+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.awesome"><span class="q">&quot;</span>awesome<span class="q">&quot;</span></span>: <span class="bool">true</span></li></ul><span class="spacer"></span>}`,
32+
],
33+
[
34+
`{ "bogus": false }`,
35+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.bogus"><span class="q">&quot;</span>bogus<span class="q">&quot;</span></span>: <span class="bool">false</span></li></ul><span class="spacer"></span>}`,
36+
],
37+
[
38+
`{ "meaning": null }`,
39+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.meaning"><span class="q">&quot;</span>meaning<span class="q">&quot;</span></span>: <span class="null">null</span></li></ul><span class="spacer"></span>}`,
40+
],
41+
[
42+
`{ "japanese": "明日がある。" }`,
43+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.japanese"><span class="q">&quot;</span>japanese<span class="q">&quot;</span></span>: <span class="string">&quot;明日がある。&quot;</span></li></ul><span class="spacer"></span>}`,
44+
],
45+
[
46+
`{ "link": "http://jsonview.com" }`,
47+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.link"><span class="q">&quot;</span>link<span class="q">&quot;</span></span>: <a href="http://jsonview.com"><span class="q">&quot;</span>http://jsonview.com<span class="q">&quot;</span></a></li></ul><span class="spacer"></span>}`,
48+
],
49+
[
50+
`{ "notLink": "http://jsonview.com is great" }`,
51+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.notLink"><span class="q">&quot;</span>notLink<span class="q">&quot;</span></span>: <span class="string">&quot;http://jsonview.com is great&quot;</span></li></ul><span class="spacer"></span>}`,
52+
],
53+
[
54+
`{ "aZero": 0 }`,
55+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.aZero"><span class="q">&quot;</span>aZero<span class="q">&quot;</span></span>: <span class="num">0</span></li></ul><span class="spacer"></span>}`,
56+
],
57+
[
58+
`{ "emptyString": "" }`,
59+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.emptyString"><span class="q">&quot;</span>emptyString<span class="q">&quot;</span></span>: <span class="string">&quot;&quot;</span></li></ul><span class="spacer"></span>}`,
60+
],
61+
[
62+
`{"string_with_nulls":"\\u0000*\\u0000_hello"}`,
63+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.string_with_nulls"><span class="q">&quot;</span>string_with_nulls<span class="q">&quot;</span></span>: <span class="string">&quot;\\u0000*\\u0000_hello&quot;</span></li></ul><span class="spacer"></span>}`,
64+
],
65+
[
66+
`{"":"18"}`,
67+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop quoted" title=""><span class="q">&quot;</span><span class="q">&quot;</span></span>: <span class="string">&quot;18&quot;</span></li></ul><span class="spacer"></span>}`,
68+
],
69+
[`[]`, `[ ]`],
70+
[`null`, `<span class="null">null</span>`],
71+
[`true`, `<span class="bool">true</span>`],
72+
[`1`, `<span class="num">1</span>`],
73+
[
74+
`[1,2,"thr<h1>ee"]`,
75+
`<span class="collapser"></span>[<ul class="array collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="num">1</span>,</li><li><span class="spacer">&nbsp;&nbsp;</span><span class="num">2</span>,</li><li><span class="spacer">&nbsp;&nbsp;</span><span class="string">&quot;thr&lt;h1&gt;ee&quot;</span></li></ul><span class="spacer"></span>]`,
76+
],
77+
[
78+
`{"hey": "g'uy'"}`,
79+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.hey"><span class="q">&quot;</span>hey<span class="q">&quot;</span></span>: <span class="string">&quot;g&apos;uy&apos;&quot;</span></li></ul><span class="spacer"></span>}`,
80+
],
81+
[
82+
`{ "value":[ { "@some.text":"W/\\"12241774\\"" } ] }`,
83+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.value"><span class="q">&quot;</span>value<span class="q">&quot;</span></span>: <span class="collapser"></span>[<ul class="array collapsible"><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="prop quoted" title=""><span class="q">&quot;</span>@some.text<span class="q">&quot;</span></span>: <span class="string">&quot;W/\\&quot;12241774\\&quot;&quot;</span></li></ul><span class="spacer">&nbsp;&nbsp;&nbsp;&nbsp;</span>}</li></ul><span class="spacer">&nbsp;&nbsp;</span>]</li></ul><span class="spacer"></span>}`,
84+
],
85+
[
86+
`{"key":"\\"value\\u201d"}`,
87+
`<span class="collapser"></span>{<ul class="obj collapsible"><li><span class="spacer">&nbsp;&nbsp;</span><span class="prop" title="&lt;root&gt;.key"><span class="q">&quot;</span>key<span class="q">&quot;</span></span>: <span class="string">&quot;\\&quot;value”&quot;</span></li></ul><span class="spacer"></span>}`,
88+
],
89+
];
90+
91+
Object.defineProperties(globalThis, {
92+
chrome: {
93+
value: {
94+
i18n: {
95+
getMessage: (message: string) => message,
96+
},
97+
runtime: {
98+
getURL: (url: string) => url,
99+
},
100+
},
101+
},
102+
});
103+
104+
for (const [content, result] of jsonContent) {
105+
test(`valueToHTML ${content}`, () => {
106+
assert.equal(valueToHTML(JSON.parse(safeStringEncodeNums(content)), "<root>", 0), result);
107+
});
108+
}

src/jsonformatter.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function decorateWithSpan(value: any, className: string) {
7474
}
7575

7676
// Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment.
77-
function valueToHTML(value: any, path: string, indent: number) {
77+
export function valueToHTML(value: any, path: string, indent: number) {
7878
if (value === null) {
7979
return decorateWithSpan("null", "null");
8080
} else if (Array.isArray(value)) {
@@ -89,8 +89,8 @@ function valueToHTML(value: any, path: string, indent: number) {
8989
case "boolean":
9090
return decorateWithSpan(value, "bool");
9191
case "string":
92-
if (value.charCodeAt(0) === 8203 && !isNaN(parseInt(value.slice(1), 10))) {
93-
return decorateWithSpan(parseInt(value.slice(1), 10), "num");
92+
if (value.charCodeAt(0) === 8203 /* zero-width space */ && !isNaN(Number(value.slice(1)))) {
93+
return decorateWithSpan(Number(value.slice(1)), "num");
9494
} else if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
9595
return `<a href="${htmlEncode(value)}"><span class="q">&quot;</span>${jsString(
9696
value

src/manifest.chrome.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "JSONView",
4-
"version": "3.0.0",
4+
"version": "3.0.1",
55
"description": "__MSG_extensionDescription__",
66
"author": "Benjamin Hollis",
77
"homepage_url": "https://jsonview.com/",

src/manifest.firefox.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "JSONView",
4-
"version": "3.0.0",
4+
"version": "3.0.1",
55
"description": "__MSG_extensionDescription__",
66
"author": "Benjamin Hollis",
77
"homepage_url": "https://jsonview.com/",
@@ -12,6 +12,11 @@
1212
"128": "icon128.png",
1313
"256": "icon256.png"
1414
},
15+
"browser_specific_settings": {
16+
"gecko": {
17+
18+
}
19+
},
1520
"background": {
1621
"scripts": ["background.js"],
1722
"type": "module"

0 commit comments

Comments
 (0)