allow using JSON, JSON5, Hjson and YAML in KeyValueEdit
This commit is contained in:
parent
0547d2398f
commit
b461169f2c
|
@ -2,13 +2,15 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.7",
|
"@babel/core": "^7.16.7",
|
||||||
"@babel/eslint-parser": "^7.16.5",
|
"@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-class-properties": "^7.16.7",
|
||||||
"@babel/plugin-proposal-decorators": "^7.16.7",
|
"@babel/plugin-proposal-decorators": "^7.16.7",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^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/plugin-transform-runtime": "^7.16.8",
|
||||||
"@babel/preset-env": "^7.16.8",
|
"@babel/preset-env": "^7.16.8",
|
||||||
"@types/file-saver": "^2.0.4",
|
"@types/file-saver": "^2.0.4",
|
||||||
|
"@types/hjson": "^2.4.3",
|
||||||
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/prismjs": "^1.16.6",
|
"@types/prismjs": "^1.16.6",
|
||||||
"@types/uikit": "^3.3.2",
|
"@types/uikit": "^3.3.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
||||||
|
@ -41,6 +43,8 @@
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"hjson": "^3.2.2",
|
"hjson": "^3.2.2",
|
||||||
"i18next": "^21.6.5",
|
"i18next": "^21.6.5",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"json5": "^2.2.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"preact": "^10.6.4",
|
"preact": "^10.6.4",
|
||||||
"preact-router": "^4.0.0",
|
"preact-router": "^4.0.0",
|
||||||
|
|
|
@ -12,8 +12,10 @@ UIkit.use(Icons);
|
||||||
import Prism from "prismjs";
|
import Prism from "prismjs";
|
||||||
// Don't Sort These!
|
// Don't Sort These!
|
||||||
import "prismjs/components/prism-hcl";
|
import "prismjs/components/prism-hcl";
|
||||||
import "prismjs/components/prism-javascript";
|
|
||||||
import "prismjs/components/prism-json";
|
import "prismjs/components/prism-json";
|
||||||
|
import "prismjs/components/prism-json5";
|
||||||
|
import "prismjs/components/prism-javascript";
|
||||||
|
import "prismjs/components/prism-yaml";
|
||||||
|
|
||||||
Prism.highlightAll();
|
Prism.highlightAll();
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
|
|
@ -4,30 +4,42 @@ import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { setErrorText } from "../../../../pageUtils";
|
import { setErrorText } from "../../../../pageUtils";
|
||||||
import { sortedObjectMap } from "../../../../utils";
|
import { sortedObjectMap } from "../../../../utils";
|
||||||
import Hjson from "hjson";
|
|
||||||
import i18next from "i18next";
|
|
||||||
import { InputWithTitle } from "../../../elements/InputWithTitle";
|
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> {
|
function parseData(data: string, syntax: string = "json"): Record<string, unknown> {
|
||||||
if (hJSON) {
|
if (syntax == "json") {
|
||||||
return Hjson.parse(data);
|
|
||||||
} else {
|
|
||||||
return JSON.parse(data);
|
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 {
|
function dumpData(data: Record<string, unknown>, space: number = defaultIndent, syntax: string = "json"): string {
|
||||||
if (hJSON) {
|
if (syntax == "json") {
|
||||||
return Hjson.stringify(data, null, space);
|
|
||||||
} else {
|
|
||||||
return JSON.stringify(data, null, space);
|
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 {
|
try {
|
||||||
parseJSON(str, hJSON);
|
parseData(str, syntax);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -43,22 +55,22 @@ export type KVEditProps = DefaultPageProps & {
|
||||||
type KVEditState =
|
type KVEditState =
|
||||||
| {
|
| {
|
||||||
dataLoaded: false;
|
dataLoaded: false;
|
||||||
useHJSON: boolean;
|
syntax: string;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
dataLoaded: true;
|
dataLoaded: true;
|
||||||
kvData: Record<string, unknown>;
|
kvData: Record<string, unknown>;
|
||||||
code: string;
|
code: string;
|
||||||
useHJSON: boolean;
|
syntax: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class KVEditor extends Component<KVEditProps, KVEditState> {
|
export class KVEditor extends Component<KVEditProps, KVEditState> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// TODO: add a global use Hjson option to settings for default
|
// TODO: add a global syntax option to settings for default
|
||||||
this.state = {
|
this.state = {
|
||||||
dataLoaded: false,
|
dataLoaded: false,
|
||||||
useHJSON: false,
|
syntax: "json",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +78,7 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
|
||||||
if (!this.state.dataLoaded) return;
|
if (!this.state.dataLoaded) return;
|
||||||
const editorContent = this.state.code;
|
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"));
|
setErrorText(i18next.t("kv_sec_edit_invalid_json_err"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +87,7 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
|
||||||
this.props.baseMount,
|
this.props.baseMount,
|
||||||
this.props.secretPath.map((e) => e + "/"),
|
this.props.secretPath.map((e) => e + "/"),
|
||||||
this.props.secretItem,
|
this.props.secretItem,
|
||||||
parseJSON(editorContent, this.hJSONToggleRef.current.checked),
|
parseData(editorContent, this.state.syntax),
|
||||||
);
|
);
|
||||||
window.history.back();
|
window.history.back();
|
||||||
}
|
}
|
||||||
|
@ -106,28 +118,45 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
getStringKVData(data: Record<string, unknown>): string {
|
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 {
|
render(): JSX.Element {
|
||||||
if (!this.state.dataLoaded) {
|
if (!this.state.dataLoaded) {
|
||||||
return <p>{i18next.t("content_loading")}</p>;
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<InputWithTitle title="Use Hjson">
|
<InputWithTitle title="Syntax">
|
||||||
<input ref={this.hJSONToggleRef} type="checkbox" class="uk-checkbox" onChange={() => {
|
<select ref={this.syntaxSelectRef} class="uk-select uk-form-width-medium" onChange={() => {
|
||||||
this.setState({useHJSON: this.hJSONToggleRef.current.checked})
|
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>
|
</InputWithTitle>
|
||||||
<p class="uk-text-danger" id="errorText" />
|
<p class="uk-text-danger" id="errorText" />
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
language="js"
|
language={codeEditorLanguage}
|
||||||
tabSize={4}
|
tabSize={defaultIndent}
|
||||||
code={this.getStringKVData(this.state.kvData)}
|
code={this.getStringKVData(this.state.kvData)}
|
||||||
onUpdate={(code) => this.onCodeUpdate(code)}
|
onUpdate={(code) => this.onCodeUpdate(code)}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Reference in a new issue