diff --git a/package.json b/package.json index 4e31824..c1bf758 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,15 @@ "devDependencies": { "@babel/core": "^7.16.7", "@babel/eslint-parser": "^7.16.5", - "@babel/plugin-syntax-import-assertions": "^7.16.7", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-decorators": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-syntax-import-assertions": "^7.16.7", "@babel/plugin-transform-runtime": "^7.16.8", "@babel/preset-env": "^7.16.8", "@types/file-saver": "^2.0.4", + "@types/hjson": "^2.4.3", + "@types/js-yaml": "^4.0.5", "@types/prismjs": "^1.16.6", "@types/uikit": "^3.3.2", "@typescript-eslint/eslint-plugin": "^5.9.1", @@ -41,6 +43,8 @@ "file-saver": "^2.0.5", "hjson": "^3.2.2", "i18next": "^21.6.5", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", "normalize.css": "^8.0.1", "preact": "^10.6.4", "preact-router": "^4.0.0", diff --git a/src/main.tsx b/src/main.tsx index 57c37f8..d04177a 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -12,8 +12,10 @@ UIkit.use(Icons); import Prism from "prismjs"; // Don't Sort These! import "prismjs/components/prism-hcl"; -import "prismjs/components/prism-javascript"; import "prismjs/components/prism-json"; +import "prismjs/components/prism-json5"; +import "prismjs/components/prism-javascript"; +import "prismjs/components/prism-yaml"; Prism.highlightAll(); /* eslint-enable */ diff --git a/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx b/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx index 5449142..a55290e 100644 --- a/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx +++ b/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx @@ -4,30 +4,42 @@ import { DefaultPageProps } from "../../../../types/DefaultPageProps"; import { SecretTitleElement } from "../SecretTitleElement"; import { setErrorText } from "../../../../pageUtils"; import { sortedObjectMap } from "../../../../utils"; -import Hjson from "hjson"; -import i18next from "i18next"; import { InputWithTitle } from "../../../elements/InputWithTitle"; +import Hjson from "hjson"; +import JSON5 from "json5"; +import yaml from "js-yaml"; +import i18next from "i18next"; +// todo: put this in settings +const defaultIndent = 2; -function parseJSON(data: string, hJSON = false): Record { - if (hJSON) { - return Hjson.parse(data); - } else { +function parseData(data: string, syntax: string = "json"): Record { + if (syntax == "json") { return JSON.parse(data); + } else if (syntax == "json5") { + return JSON5.parse(data); + } else if (syntax == "hjson") { + return Hjson.parse(data); + } else if (syntax == "yaml") { + return yaml.load(data) as Record; } } -function dumpJSON(data: Record, space: number = 0, hJSON = false): string { - if (hJSON) { - return Hjson.stringify(data, null, space); - } else { +function dumpData(data: Record, space: number = defaultIndent, syntax: string = "json"): string { + if (syntax == "json") { return JSON.stringify(data, null, space); + } else if (syntax == "json5") { + return JSON5.stringify(data, null, space); + } else if (syntax == "hjson") { + return Hjson.stringify(data, { space: space }); + } else if (syntax == "yaml") { + return yaml.dump(data, { indent: space }); } } -export function isValidJSON(str: string, hJSON = false): boolean { +export function validateData(str: string, syntax: string = "json"): boolean { try { - parseJSON(str, hJSON); + parseData(str, syntax); } catch (e) { return false; } @@ -43,22 +55,22 @@ export type KVEditProps = DefaultPageProps & { type KVEditState = | { dataLoaded: false; - useHJSON: boolean; + syntax: string; } | { dataLoaded: true; kvData: Record; code: string; - useHJSON: boolean; + syntax: string; }; export class KVEditor extends Component { constructor() { super(); - // TODO: add a global use Hjson option to settings for default + // TODO: add a global syntax option to settings for default this.state = { dataLoaded: false, - useHJSON: false, + syntax: "json", }; } @@ -66,7 +78,7 @@ export class KVEditor extends Component { if (!this.state.dataLoaded) return; const editorContent = this.state.code; - if (!isValidJSON(editorContent, this.state.useHJSON)) { + if (!validateData(editorContent, this.state.syntax)) { setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); return; } @@ -75,7 +87,7 @@ export class KVEditor extends Component { this.props.baseMount, this.props.secretPath.map((e) => e + "/"), this.props.secretItem, - parseJSON(editorContent, this.hJSONToggleRef.current.checked), + parseData(editorContent, this.state.syntax), ); window.history.back(); } @@ -106,28 +118,45 @@ export class KVEditor extends Component { } getStringKVData(data: Record): string { - return dumpJSON(Object.fromEntries(sortedObjectMap(data)), 4, this.state.useHJSON); + return dumpData(Object.fromEntries(sortedObjectMap(data)), defaultIndent, this.state.syntax); } - hJSONToggleRef = createRef() + syntaxSelectRef = createRef() render(): JSX.Element { if (!this.state.dataLoaded) { return

{i18next.t("content_loading")}

; } + let codeEditorLanguage: string; + + if (this.state.syntax == "json") { + codeEditorLanguage = "json" + } else if (this.state.syntax == "json5") { + codeEditorLanguage = "json5" + }else if (this.state.syntax == "hjson") { + codeEditorLanguage = "js" + } else if (this.state.syntax == "yaml") { + codeEditorLanguage = "yaml" + } + return (
- - { - this.setState({useHJSON: this.hJSONToggleRef.current.checked}) - }} /> + +

this.onCodeUpdate(code)} />