Skip to content

Commit

Permalink
feat: add json5 support for rest query manual
Browse files Browse the repository at this point in the history
Add JSON5 support for manual rest query entries with
indenting/formatting keeping comments and orig json5
codes (e.g. hex numbers).
  • Loading branch information
mbehr1 committed Apr 10, 2023
1 parent 1384e43 commit acc4218
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 13 deletions.
11 changes: 10 additions & 1 deletion src/webview/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"dompurify": "^2.4.0",
"jju": "^1.4.0",
"json5": "2.2.3",
"json-stable-stringify": "^1.0.1",
"marked": "^3.0.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-table": "^7.8.0",
"web-vitals": "^3.0.2"
"web-vitals": "^3.0.2",
"fs": "npm:[email protected]",
"assert": "npm:[email protected]"
},
"scripts": {
"start": "react-scripts start",
Expand All @@ -35,6 +38,12 @@
"react-app/jest"
]
},
"browser": {
"fs": false,
"os": false,
"path": false,
"assert": false
},
"browserslist": {
"production": [
">0.2%",
Expand Down
20 changes: 13 additions & 7 deletions src/webview/src/components/dltRestQueryManual.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import DialogActions from '@mui/material/DialogActions';
import { Button, DialogContent, DialogTitle, IconButton, TextField, Typography, Link } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import ErrorIcon from '@mui/icons-material/Error';
import JSON5 from 'json5';
import { formatJson5 } from './utils/json5';

// todo move those two functions into a util class. It's currently duplicated in docs.

Expand All @@ -26,10 +28,11 @@ const rqUriDecode = (rq) => {
if (andCnt) { toRet += ' &\n'; }
andCnt++;
try {
toRet += command + '=' + JSON.stringify(JSON.parse(commandParams), ' ', 2) + '\n';
JSON5.parse(commandParams);
toRet += command + '=' + formatJson5(commandParams) + '\n';
} catch {
if (commandParams.includes('{') || commandParams.includes('[') || commandParams.includes('"')) {
toRet += `\n<cannot parse: \n'${command}=${commandParams}'\n as JSON>`;
toRet += `\n<cannot parse: \n'${command}=${commandParams}'\n as JSON5>`;
} else {
toRet += `${command}=${commandParams}`;
}
Expand Down Expand Up @@ -59,12 +62,15 @@ const rqUriEncode = (rq) => {
const command = commandStr.slice(0, eqIdx);
const commandParam = commandStr.slice(eqIdx + 1);
try {
const commandParamEncoded = encodeURIComponent(JSON.stringify(JSON.parse(commandParam)));
// we do only check that its a valid json5 but then keep the orig data
// todo add formatting e.g. with the jju tokenizer
JSON5.parse(commandParam);
const commandParamEncoded = encodeURIComponent(formatJson5(commandParam));
toRet += `${command}=${commandParamEncoded}`;
} catch {
// if its a simple string then it's ok
if (commandParam.includes('{') || commandParam.includes('[') || commandParam.includes('"')) {
toRet += `&\n<cannot parse: \n'${command}=${commandParam}'\n as JSON>`;
toRet += `&\n<cannot parse: \n'${command}=${commandParam}'\n as JSON5>`;
ok = false;
} else {
toRet += `${command}=${commandParam}`;
Expand All @@ -84,7 +90,7 @@ const rqUriEncode = (rq) => {
*/
export default function DLTRestQueryManualDialog(props) {

console.log(`DLTRestQueryManualDialog(open=${props.open}, applyMode=${props.applyMode})`);
//console.log(`DLTRestQueryManualDialog(open=${props.open}, applyMode=${props.applyMode})`);

// const [dataSource, setDataSource] = React.useState(props.dataSource);
const [text, setText] = React.useState(props.dataSource);
Expand All @@ -110,8 +116,8 @@ export default function DLTRestQueryManualDialog(props) {
props.onClose();
}
const handleSave = () => {
console.log(`DLTRestQueryManualDialog handleSave()`);
console.log(` dataSource=${text}`);
//console.log(`DLTRestQueryManualDialog handleSave()`);
//console.log(` dataSource=${text}`);

props.onChange(text); // dont check for changes
props.onClose();
Expand Down
69 changes: 69 additions & 0 deletions src/webview/src/components/utils/json5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import jju from 'jju';

/**
* Indent/format a string representing a valid json5 expression.
*
* It's like JSON.stringify(JSON.parse(str)) but for JSON5 strings keeping
* comments, hex numbers, etc.
* The string is expected to be a valid JSON5 string already!
*
* The following rules are applied:
* - whitespace at begin of the line is ignored
* - whitespace at end of a line is removed
* - keys at begin of line are indented by 2 spaces per nested stack
* - after separator ':' a space is added
* - {} at begin of line are indented by 2 spaces per nested stack
* - literals at begin of line are indented... todo
* @param {string} json5Str
* @returns formatted string as valid json5
*/
export function formatJson5(json5Str) {
try {
// use jju tokenizer:
const tokens = jju.tokenize(json5Str);
let formattedStr = '';
let ignoreDirectNextWhitespace = false;
let nextLine = '';
for (const token of tokens) {
const atBeginOfLine = nextLine.length === 0;
if (ignoreDirectNextWhitespace && token.type !== 'whitespace') { ignoreDirectNextWhitespace = false; }
switch (token.type) {
case 'separator':
switch (token.raw) {
case '{':
case '}':
if (atBeginOfLine) { nextLine += ' '.repeat(token.stack.length); }
nextLine += token.raw;
break;
case ':':
nextLine += token.raw;
nextLine += ' ';
ignoreDirectNextWhitespace = true;
break;
default:
nextLine += token.raw;
break;
}
break;
case 'newline': formattedStr += nextLine.trimEnd(); nextLine = ''; formattedStr += '\n'; break;
case 'literal':
case 'key':
if (atBeginOfLine) {
nextLine += ' '.repeat(token.stack.length);
}
nextLine += token.raw;
break;
case 'whitespace': if (!atBeginOfLine && !ignoreDirectNextWhitespace) { nextLine += token.raw; } break;
case 'comment': nextLine += token.raw; break;
default:
console.error(`formatJson5: unknown token '${token.type}'`, token);
break;
}
}
if (nextLine.length > 0) formattedStr += nextLine;
return formattedStr;
} catch (e) {
console.error(`formatJson5: got error='${e}'`);
return json5Str;
}
}
119 changes: 114 additions & 5 deletions src/webview/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3165,6 +3165,16 @@ asap@~2.0.6:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=

"assert@npm:[email protected]":
version "2.0.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32"
integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
dependencies:
es6-object-assign "^1.1.0"
is-nan "^1.2.1"
object-is "^1.0.1"
util "^0.12.0"

ast-types-flow@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
Expand Down Expand Up @@ -3197,6 +3207,11 @@ autoprefixer@^10.4.11:
picocolors "^1.0.0"
postcss-value-parser "^4.2.0"

available-typed-arrays@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==

axe-core@^4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f"
Expand Down Expand Up @@ -4566,6 +4581,11 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"

es6-object-assign@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==

escalade@^3.1.0, escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
Expand Down Expand Up @@ -5101,6 +5121,13 @@ follow-redirects@^1.0.0:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==

for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
dependencies:
is-callable "^1.1.3"

fork-ts-checker-webpack-plugin@^6.5.0:
version "6.5.2"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340"
Expand Down Expand Up @@ -5183,6 +5210,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=

"fs@npm:[email protected]":
version "0.0.2"
resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.2.tgz#e1f244ef3933c1b2a64bd4799136060d0f5914f8"
integrity sha512-YAiVokMCrSIFZiroB1oz51hPiPRVcUtSa4x2U5RYXyhS9VAPdiFigKbPTnOSq7XY8wd3FIVPYmXpo5lMzFmxgg==

fsevents@^2.3.2, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
Expand Down Expand Up @@ -5326,6 +5358,13 @@ globby@^11.0.4, globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"

gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
dependencies:
get-intrinsic "^1.1.3"

graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
Expand Down Expand Up @@ -5674,6 +5713,14 @@ ipaddr.js@^2.0.1:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0"
integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==

is-arguments@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
dependencies:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"

is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
Expand Down Expand Up @@ -5701,16 +5748,16 @@ is-boolean-object@^1.1.0:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"

is-callable@^1.1.3, is-callable@^1.2.6:
version "1.2.7"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==

is-callable@^1.1.4, is-callable@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==

is-callable@^1.2.6:
version "1.2.7"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==

is-core-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d"
Expand Down Expand Up @@ -5755,6 +5802,13 @@ is-generator-fn@^2.0.0:
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==

is-generator-function@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
dependencies:
has-tostringtag "^1.0.0"

is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
Expand All @@ -5779,6 +5833,14 @@ is-module@^1.0.0:
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=

is-nan@^1.2.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
dependencies:
call-bind "^1.0.0"
define-properties "^1.1.3"

is-negative-zero@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
Expand Down Expand Up @@ -5879,6 +5941,17 @@ is-symbol@^1.0.3:
dependencies:
has-symbols "^1.0.2"

is-typed-array@^1.1.10, is-typed-array@^1.1.3:
version "1.1.10"
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
dependencies:
available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
for-each "^0.3.3"
gopd "^1.0.1"
has-tostringtag "^1.0.0"

is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
Expand Down Expand Up @@ -6462,6 +6535,11 @@ jest@^27.4.3:
import-local "^3.0.2"
jest-cli "^27.5.1"

jju@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a"
integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==

js-sdsl@^4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6"
Expand Down Expand Up @@ -7183,6 +7261,14 @@ object-inspect@^1.8.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==

object-is@^1.0.1:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"

object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
Expand Down Expand Up @@ -9731,6 +9817,17 @@ util.promisify@~1.0.0:
has-symbols "^1.0.1"
object.getownpropertydescriptors "^2.1.0"

util@^0.12.0:
version "0.12.5"
resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc"
integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
dependencies:
inherits "^2.0.3"
is-arguments "^1.0.4"
is-generator-function "^1.0.7"
is-typed-array "^1.1.3"
which-typed-array "^1.1.2"

utila@~0.4:
version "0.4.0"
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
Expand Down Expand Up @@ -10005,6 +10102,18 @@ which-boxed-primitive@^1.0.2:
is-string "^1.0.5"
is-symbol "^1.0.3"

which-typed-array@^1.1.2:
version "1.1.9"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
dependencies:
available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
for-each "^0.3.3"
gopd "^1.0.1"
has-tostringtag "^1.0.0"
is-typed-array "^1.1.10"

which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
Expand Down

0 comments on commit acc4218

Please sign in to comment.