Skip to content

Commit a10aae5

Browse files
authored
Merge pull request #217 from bhollis/fix-floats
Fixed a regression where floating-point numbers were truncated to integers
2 parents bf7a463 + a6692b8 commit a10aae5

File tree

8 files changed

+128
-7
lines changed

8 files changed

+128
-7
lines changed

.vscode/settings.json

Lines changed: 0 additions & 1 deletion
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 108 additions & 0 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 6 additions & 1 deletion
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)