Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a regression where floating-point numbers were truncated to integers #217

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"jest.jestCommandLine": "pnpm test --",
"[javascript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "never"
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## JSONView 3.0.1

- Fixed a regression where floating-point numbers were truncated to integers.

## JSONView 3.0.0

- JSONView is now compatible with Manifest V3, which is required in Chrome.
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [Install for Firefox](https://addons.mozilla.org/en-US/firefox/addon/jsonview/)
- [Install for Chrome](https://chrome.google.com/webstore/detail/jsonview/gmegofmjomhknnokphhckolhcffdaihd)
- [Install for Edge](https://microsoftedge.microsoft.com/addons/detail/jsonview/kmpfgkgaimakokfhgdahhiaaiidiphco)
- There is no version for Safari because it costs $100/year to publish a free extension to the Mac App Store.

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.

Expand Down Expand Up @@ -49,3 +50,7 @@ pnpm start
```

`jsonview-chrome.zip` and `jsonview-firefox.zip` can then be manually uploaded to the extension sites.

- Chrome: https://chrome.google.com/webstore/devconsole/
- Firefox: https://addons.mozilla.org/en-US/developers/addons
- Edge: https://partner.microsoft.com/en-us/dashboard/microsoftedge/overview
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "jsonview@brh.numbera.com",
"version": "3.0.0",
"version": "3.0.1",
"name": "jsonview",
"title": "JSONView",
"description": "View JSON documents in the browser.",
Expand Down
108 changes: 108 additions & 0 deletions src/jsonformatter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { valueToHTML } from "./jsonformatter.js";
import { safeStringEncodeNums } from "./safe-encode-numbers.js";

const jsonContent = [
[`{}`, `{ }`],
[
`{ "hey": "guy" }`,
`<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>}`,
],
[
`{ "float": 10.5 }`,
`<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>}`,
],
[
`{ "10.5": "hello" }`,
`<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>}`,
],
[
// bigger than max safe integer
`{ "anumber": 9117199254740991 }`,
`<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>}`,
],
[
`{ "anobject": {"whoa": "nuts","anarray": [1,2,"thr<h1>ee"], "more":"stuff"} }`,
`<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>}`,
],
[
`{ "awesome": true }`,
`<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>}`,
],
[
`{ "bogus": false }`,
`<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>}`,
],
[
`{ "meaning": null }`,
`<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>}`,
],
[
`{ "japanese": "明日がある。" }`,
`<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>}`,
],
[
`{ "link": "http://jsonview.com" }`,
`<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>}`,
],
[
`{ "notLink": "http://jsonview.com is great" }`,
`<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>}`,
],
[
`{ "aZero": 0 }`,
`<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>}`,
],
[
`{ "emptyString": "" }`,
`<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>}`,
],
[
`{"string_with_nulls":"\\u0000*\\u0000_hello"}`,
`<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>}`,
],
[
`{"":"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><span class="q">&quot;</span></span>: <span class="string">&quot;18&quot;</span></li></ul><span class="spacer"></span>}`,
],
[`[]`, `[ ]`],
[`null`, `<span class="null">null</span>`],
[`true`, `<span class="bool">true</span>`],
[`1`, `<span class="num">1</span>`],
[
`[1,2,"thr<h1>ee"]`,
`<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>]`,
],
[
`{"hey": "g'uy'"}`,
`<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>}`,
],
[
`{ "value":[ { "@some.text":"W/\\"12241774\\"" } ] }`,
`<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>}`,
],
[
`{"key":"\\"value\\u201d"}`,
`<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>}`,
],
];

Object.defineProperties(globalThis, {
chrome: {
value: {
i18n: {
getMessage: (message: string) => message,
},
runtime: {
getURL: (url: string) => url,
},
},
},
});

for (const [content, result] of jsonContent) {
test(`valueToHTML ${content}`, () => {
assert.equal(valueToHTML(JSON.parse(safeStringEncodeNums(content)), "<root>", 0), result);
});
}
6 changes: 3 additions & 3 deletions src/jsonformatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function decorateWithSpan(value: any, className: string) {
}

// Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment.
function valueToHTML(value: any, path: string, indent: number) {
export function valueToHTML(value: any, path: string, indent: number) {
if (value === null) {
return decorateWithSpan("null", "null");
} else if (Array.isArray(value)) {
Expand All @@ -89,8 +89,8 @@ function valueToHTML(value: any, path: string, indent: number) {
case "boolean":
return decorateWithSpan(value, "bool");
case "string":
if (value.charCodeAt(0) === 8203 && !isNaN(parseInt(value.slice(1), 10))) {
return decorateWithSpan(parseInt(value.slice(1), 10), "num");
if (value.charCodeAt(0) === 8203 /* zero-width space */ && !isNaN(Number(value.slice(1)))) {
return decorateWithSpan(Number(value.slice(1)), "num");
} else if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
return `<a href="${htmlEncode(value)}"><span class="q">&quot;</span>${jsString(
value
Expand Down
2 changes: 1 addition & 1 deletion src/manifest.chrome.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "JSONView",
"version": "3.0.0",
"version": "3.0.1",
"description": "__MSG_extensionDescription__",
"author": "Benjamin Hollis",
"homepage_url": "https://jsonview.com/",
Expand Down
7 changes: 6 additions & 1 deletion src/manifest.firefox.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "JSONView",
"version": "3.0.0",
"version": "3.0.1",
"description": "__MSG_extensionDescription__",
"author": "Benjamin Hollis",
"homepage_url": "https://jsonview.com/",
Expand All @@ -12,6 +12,11 @@
"128": "icon128.png",
"256": "icon256.png"
},
"browser_specific_settings": {
"gecko": {
"id": "jsonview@brh.numbera.com"
}
},
"background": {
"scripts": ["background.js"],
"type": "module"
Expand Down
Loading