1
0
Fork 0

allow using JSON, JSON5, Hjson and YAML in KeyValueEdit

This commit is contained in:
ChaotiCryptidz 2022-01-13 18:31:19 +00:00
parent 0547d2398f
commit b461169f2c
3 changed files with 63 additions and 28 deletions

View file

@ -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",

View file

@ -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 */

View file

@ -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<string, unknown> {
if (hJSON) {
return Hjson.parse(data);
} else {
function parseData(data: string, syntax: string = "json"): Record<string, unknown> {
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<string, unknown>;
}
}
function dumpJSON(data: Record<string, unknown>, space: number = 0, hJSON = false): string {
if (hJSON) {
return Hjson.stringify(data, null, space);
} else {
function dumpData(data: Record<string, unknown>, 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<string, unknown>;
code: string;
useHJSON: boolean;
syntax: string;
};
export class KVEditor extends Component<KVEditProps, KVEditState> {
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<KVEditProps, KVEditState> {
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<KVEditProps, KVEditState> {
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<KVEditProps, KVEditState> {
}
getStringKVData(data: Record<string, unknown>): string {
return dumpJSON(Object.fromEntries(sortedObjectMap(data)), 4, this.state.useHJSON);
return dumpData(Object.fromEntries(sortedObjectMap(data)), defaultIndent, this.state.syntax);
}
hJSONToggleRef = createRef<HTMLInputElement>()
syntaxSelectRef = createRef<HTMLSelectElement>()
render(): JSX.Element {
if (!this.state.dataLoaded) {
return <p>{i18next.t("content_loading")}</p>;
}
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 (
<div>
<InputWithTitle title="Use Hjson">
<input ref={this.hJSONToggleRef} type="checkbox" class="uk-checkbox" onChange={() => {
this.setState({useHJSON: this.hJSONToggleRef.current.checked})
}} />
<InputWithTitle title="Syntax">
<select ref={this.syntaxSelectRef} class="uk-select uk-form-width-medium" onChange={() => {
this.setState({ syntax: this.syntaxSelectRef.current.value })
}}>
<option label="JSON" value="json" />
<option label="JSON5" value="json5" />
<option label="Hjson" value="hjson" />
<option label="Yaml" value="yaml" />
</select>
</InputWithTitle>
<p class="uk-text-danger" id="errorText" />
<CodeEditor
language="js"
tabSize={4}
language={codeEditorLanguage}
tabSize={defaultIndent}
code={this.getStringKVData(this.state.kvData)}
onUpdate={(code) => this.onCodeUpdate(code)}
/>