2022-07-01 13:46:27 +00:00
|
|
|
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
|
|
|
|
import { html as htmlLang } from "@codemirror/lang-html";
|
|
|
|
import { javascript } from "@codemirror/lang-javascript";
|
|
|
|
import { python } from "@codemirror/lang-python";
|
|
|
|
import { xml } from "@codemirror/lang-xml";
|
|
|
|
import {
|
|
|
|
LanguageSupport,
|
|
|
|
StreamLanguage,
|
|
|
|
defaultHighlightStyle,
|
|
|
|
syntaxHighlighting,
|
|
|
|
} from "@codemirror/language";
|
|
|
|
import * as yamlMode from "@codemirror/legacy-modes/mode/yaml";
|
2022-07-02 21:07:09 +00:00
|
|
|
import { Compartment, EditorState, Extension } from "@codemirror/state";
|
2023-02-06 10:37:11 +00:00
|
|
|
import { oneDark } from "@codemirror/theme-one-dark";
|
2023-03-25 21:31:48 +00:00
|
|
|
import { ViewUpdate } from "@codemirror/view";
|
2022-10-16 11:55:53 +00:00
|
|
|
import { EditorView, drawSelection, keymap, lineNumbers } from "@codemirror/view";
|
2023-03-10 16:33:03 +00:00
|
|
|
import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
|
2022-09-14 22:05:21 +00:00
|
|
|
import { AKElement } from "@goauthentik/elements/Base";
|
2021-09-21 09:31:37 +00:00
|
|
|
import YAML from "yaml";
|
|
|
|
|
2021-11-04 21:34:48 +00:00
|
|
|
import { customElement, property } from "lit/decorators.js";
|
2020-11-21 17:32:34 +00:00
|
|
|
|
2023-03-09 22:17:53 +00:00
|
|
|
import { UiThemeEnum } from "@goauthentik/api";
|
|
|
|
|
2020-12-05 21:08:42 +00:00
|
|
|
@customElement("ak-codemirror")
|
2023-01-02 15:13:07 +00:00
|
|
|
export class CodeMirrorTextarea<T> extends AKElement {
|
2021-08-03 15:52:21 +00:00
|
|
|
@property({ type: Boolean })
|
2020-12-01 08:15:41 +00:00
|
|
|
readOnly = false;
|
2020-11-21 17:32:34 +00:00
|
|
|
|
|
|
|
@property()
|
2020-12-01 08:15:41 +00:00
|
|
|
mode = "yaml";
|
2020-11-21 17:32:34 +00:00
|
|
|
|
2021-03-29 10:16:32 +00:00
|
|
|
@property()
|
|
|
|
name?: string;
|
|
|
|
|
2023-01-10 21:00:34 +00:00
|
|
|
@property({ type: Boolean })
|
|
|
|
parseValue = true;
|
|
|
|
|
2022-07-01 13:46:27 +00:00
|
|
|
editor?: EditorView;
|
2021-03-30 16:20:48 +00:00
|
|
|
|
2021-04-03 10:08:46 +00:00
|
|
|
_value?: string;
|
|
|
|
|
2022-07-02 21:07:09 +00:00
|
|
|
theme: Compartment;
|
|
|
|
|
|
|
|
themeLight: Extension;
|
|
|
|
themeDark: Extension;
|
|
|
|
|
2021-03-29 10:16:32 +00:00
|
|
|
@property()
|
2021-04-09 12:19:31 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types
|
2023-01-02 15:13:07 +00:00
|
|
|
set value(v: T | string) {
|
2021-04-09 12:19:31 +00:00
|
|
|
if (v === null || v === undefined) return;
|
|
|
|
// Value might be an object if within an iron-form, as that calls the getter of value
|
|
|
|
// in the beginning and the calls this setter on reset
|
|
|
|
let textValue = v;
|
|
|
|
if (!(typeof v === "string" || v instanceof String)) {
|
|
|
|
switch (this.mode.toLowerCase()) {
|
|
|
|
case "yaml":
|
|
|
|
textValue = YAML.stringify(v);
|
|
|
|
break;
|
|
|
|
case "javascript":
|
|
|
|
textValue = JSON.stringify(v);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
textValue = v.toString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-03-31 20:18:40 +00:00
|
|
|
if (this.editor) {
|
2022-07-01 13:46:27 +00:00
|
|
|
this.editor.dispatch({
|
2023-01-02 15:13:07 +00:00
|
|
|
changes: { from: 0, to: this.editor.state.doc.length, insert: textValue as string },
|
2022-07-01 13:46:27 +00:00
|
|
|
});
|
2021-04-03 10:08:46 +00:00
|
|
|
} else {
|
2023-01-02 15:13:07 +00:00
|
|
|
this._value = textValue as string;
|
2021-03-31 20:18:40 +00:00
|
|
|
}
|
2021-03-30 16:20:48 +00:00
|
|
|
}
|
2021-03-29 10:16:32 +00:00
|
|
|
|
2023-01-02 15:13:07 +00:00
|
|
|
get value(): T | string {
|
2023-01-10 21:00:34 +00:00
|
|
|
if (!this.parseValue) {
|
|
|
|
return this.getInnerValue();
|
|
|
|
}
|
2021-04-09 12:19:31 +00:00
|
|
|
try {
|
|
|
|
switch (this.mode.toLowerCase()) {
|
|
|
|
case "yaml":
|
|
|
|
return YAML.parse(this.getInnerValue());
|
|
|
|
case "javascript":
|
|
|
|
return JSON.parse(this.getInnerValue());
|
|
|
|
default:
|
|
|
|
return this.getInnerValue();
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return this.getInnerValue();
|
2021-03-30 16:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-02 21:07:09 +00:00
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.theme = new Compartment();
|
2022-07-08 20:55:57 +00:00
|
|
|
this.themeLight = EditorView.theme(
|
|
|
|
{
|
|
|
|
"&": {
|
|
|
|
backgroundColor: "var(--pf-global--BackgroundColor--light-300)",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ dark: false },
|
|
|
|
);
|
2023-02-06 10:37:11 +00:00
|
|
|
this.themeDark = oneDark;
|
2022-07-02 21:07:09 +00:00
|
|
|
}
|
|
|
|
|
2021-03-30 16:20:48 +00:00
|
|
|
private getInnerValue(): string {
|
2021-03-31 20:32:28 +00:00
|
|
|
if (!this.editor) {
|
2021-03-30 16:20:48 +00:00
|
|
|
return "";
|
|
|
|
}
|
2022-07-01 13:46:27 +00:00
|
|
|
return this.editor.state.doc.toString();
|
2021-03-30 16:20:48 +00:00
|
|
|
}
|
2020-11-21 17:32:34 +00:00
|
|
|
|
2022-07-01 13:46:27 +00:00
|
|
|
getLanguageExtension(): LanguageSupport | undefined {
|
|
|
|
switch (this.mode.toLowerCase()) {
|
|
|
|
case "xml":
|
|
|
|
return xml();
|
|
|
|
case "javascript":
|
|
|
|
return javascript();
|
|
|
|
case "html":
|
|
|
|
return htmlLang();
|
|
|
|
case "python":
|
|
|
|
return python();
|
|
|
|
case "yaml":
|
|
|
|
return new LanguageSupport(StreamLanguage.define(yamlMode.yaml));
|
|
|
|
}
|
|
|
|
return undefined;
|
2020-11-21 17:32:34 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
firstUpdated(): void {
|
2023-03-10 16:33:03 +00:00
|
|
|
this.addEventListener(EVENT_THEME_CHANGE, ((ev: CustomEvent<UiThemeEnum>) => {
|
2023-03-09 22:17:53 +00:00
|
|
|
if (ev.detail === UiThemeEnum.Dark) {
|
|
|
|
this.editor?.dispatch({
|
|
|
|
effects: this.theme.reconfigure(this.themeDark),
|
|
|
|
});
|
2022-07-02 21:07:09 +00:00
|
|
|
} else {
|
2023-03-09 22:17:53 +00:00
|
|
|
this.editor?.dispatch({
|
|
|
|
effects: this.theme.reconfigure(this.themeLight),
|
|
|
|
});
|
2022-07-02 21:07:09 +00:00
|
|
|
}
|
2023-03-09 22:17:53 +00:00
|
|
|
}) as EventListener);
|
2022-07-01 13:46:27 +00:00
|
|
|
const extensions = [
|
|
|
|
history(),
|
|
|
|
keymap.of([...defaultKeymap, ...historyKeymap]),
|
|
|
|
syntaxHighlighting(defaultHighlightStyle),
|
|
|
|
this.getLanguageExtension(),
|
|
|
|
lineNumbers(),
|
2022-10-16 11:55:53 +00:00
|
|
|
drawSelection(),
|
2022-07-01 13:46:27 +00:00
|
|
|
EditorView.lineWrapping,
|
2023-03-25 21:31:48 +00:00
|
|
|
EditorView.updateListener.of((v: ViewUpdate) => {
|
|
|
|
if (!v.docChanged) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.dispatchEvent(
|
|
|
|
new CustomEvent("change", {
|
|
|
|
detail: v,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}),
|
2022-07-01 13:46:27 +00:00
|
|
|
EditorState.readOnly.of(this.readOnly),
|
|
|
|
EditorState.tabSize.of(2),
|
2023-03-10 19:11:02 +00:00
|
|
|
this.theme.of(this.activeTheme === UiThemeEnum.Dark ? this.themeDark : this.themeLight),
|
2022-07-01 13:46:27 +00:00
|
|
|
];
|
|
|
|
this.editor = new EditorView({
|
|
|
|
extensions: extensions.filter((p) => p) as Extension[],
|
|
|
|
root: this.shadowRoot || document,
|
|
|
|
doc: this._value,
|
2020-11-21 17:32:34 +00:00
|
|
|
});
|
2022-07-01 13:46:27 +00:00
|
|
|
this.shadowRoot?.appendChild(this.editor.dom);
|
2021-03-29 10:16:32 +00:00
|
|
|
}
|
2020-11-21 17:32:34 +00:00
|
|
|
}
|