aboutsummaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2024-09-15 14:32:48 +0700
committerShulhan <ms@kilabit.info>2024-09-15 14:32:48 +0700
commitd1e96e09438b4a5c7580b86c469e817a61be991f (patch)
tree4d81fb2fd62207bbb9162b81083c721ec8fd8e29 /editor
parent1cc9c9dd68a3a59c685505228336430624608852 (diff)
downloadpakakeh.ts-d1e96e09438b4a5c7580b86c469e817a61be991f.tar.xz
all: commit all generate JavaScript files
This is to simplify development on third party where they can clone and include the file directly without installing or running anything to build the files.
Diffstat (limited to 'editor')
-rw-r--r--editor/editor.js205
-rw-r--r--editor/example.js65
2 files changed, 270 insertions, 0 deletions
diff --git a/editor/editor.js b/editor/editor.js
new file mode 100644
index 0000000..e80e147
--- /dev/null
+++ b/editor/editor.js
@@ -0,0 +1,205 @@
+// SPDX-FileCopyrightText: 2021 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+const WUI_EDITOR_CLASS = "wui_editor";
+const WUI_EDITOR_CLASS_LINE_NUMBER = "wui_editor_line_number";
+const WUI_EDITOR_CLASS_CONTENT = "wui_editor_content";
+export class WuiEditor {
+ constructor(opts) {
+ this.opts = opts;
+ this.content = "";
+ this.totalLine = 0;
+ this.elLineNumber = document.createElement("div");
+ this.elContent = document.createElement("div");
+ this.isKeyControl = false;
+ this.id = opts.id;
+ this.isEditable = opts.isEditable;
+ const el = document.getElementById(opts.id);
+ if (!el) {
+ console.error("WuiEditor: element ID not found:", opts.id);
+ return;
+ }
+ this.el = el;
+ this.initStyle();
+ this.initLineNumber();
+ this.initContent();
+ this.el.classList.add(WUI_EDITOR_CLASS);
+ }
+ // getContent return content of file.
+ getContent() {
+ let content = "";
+ let el;
+ let line;
+ this.elContent.childNodes.forEach((node) => {
+ switch (node.nodeType) {
+ case Node.ELEMENT_NODE:
+ el = node;
+ line = el.innerText;
+ break;
+ case Node.TEXT_NODE:
+ line = node.nodeValue || "";
+ break;
+ }
+ line = line.trimEnd();
+ content += line + "\n";
+ });
+ content = content.trim();
+ return content;
+ }
+ // open the node for editing.
+ // The content MUST be encoded in base64.
+ open(node) {
+ this.content = atob(node.content);
+ this.content = this.content.replace("\r\n", "\n");
+ this.render(this.content);
+ }
+ setEditable(yes) {
+ this.isEditable = yes;
+ if (yes) {
+ this.elContent.setAttribute("contenteditable", "true");
+ }
+ else {
+ this.elContent.setAttribute("contenteditable", "false");
+ }
+ }
+ addNewLine() {
+ this.totalLine++;
+ const elLine = document.createElement("div");
+ elLine.innerText = `${this.totalLine}`;
+ this.elLineNumber.appendChild(elLine);
+ }
+ initLineNumber() {
+ this.elLineNumber.classList.add(WUI_EDITOR_CLASS_LINE_NUMBER);
+ this.el.appendChild(this.elLineNumber);
+ }
+ initContent() {
+ if (this.opts.isEditable) {
+ this.elContent.setAttribute("contenteditable", "true");
+ this.elContent.setAttribute("spellcheck", "false");
+ this.elContent.addEventListener("paste", (ev) => {
+ var _a;
+ ev.preventDefault();
+ let text = ((_a = ev.clipboardData) === null || _a === void 0 ? void 0 : _a.getData("text/plain")) || "";
+ if (!text) {
+ console.error(`on paste: text is ${text}`);
+ return;
+ }
+ const selection = window.getSelection();
+ if (!selection || !selection.rangeCount) {
+ console.error(`on paste: failed to get selection`);
+ return;
+ }
+ text = text.trimEnd();
+ selection.deleteFromDocument();
+ selection.getRangeAt(0).insertNode(document.createTextNode(text));
+ selection.collapseToEnd();
+ this.renderLineNumber(this.getContent());
+ });
+ this.elContent.onkeydown = (ev) => {
+ this.onKeydownDocument(this, ev);
+ };
+ this.elContent.onkeyup = (ev) => {
+ this.onKeyupDocument(this, ev);
+ };
+ this.elContent.addEventListener("blur", () => {
+ this.isKeyControl = false;
+ });
+ }
+ this.elContent.classList.add(WUI_EDITOR_CLASS_CONTENT);
+ this.el.appendChild(this.elContent);
+ }
+ initStyle() {
+ const style = document.createElement("style");
+ style.type = "text/css";
+ style.innerText = `
+ [contenteditable] {
+ outline: 0px solid transparent;
+ }
+ .${WUI_EDITOR_CLASS} {
+ background-color: cornsilk;
+ border: 1px solid brown;
+ font-family: monospace;
+ line-height: 1.6em;
+ overflow-y: scroll;
+ width: 100%;
+ }
+ .${WUI_EDITOR_CLASS_LINE_NUMBER} {
+ background-color: bisque;
+ border-right: 1px dashed brown;
+ color: dimgrey;
+ display: inline-block;
+ font-family: monospace;
+ margin-right: 4px;
+ padding: 0px 8px;
+ position: sticky;
+ text-align: right;
+ width: 3em;
+ }
+ .${WUI_EDITOR_CLASS_CONTENT} {
+ caret-color: red;
+ display: inline-block;
+ padding: 0px 8px 0 0;
+ vertical-align: top;
+ white-space: pre;
+ width: calc(100% - 10em);
+ word-wrap: normal;
+ }
+ `;
+ document.head.appendChild(style);
+ }
+ onKeydownDocument(ed, ev) {
+ switch (ev.key) {
+ case "Control":
+ ed.isKeyControl = true;
+ break;
+ case "Enter":
+ if (ed.isKeyControl) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ if (ed.opts.onSave) {
+ const content = ed.getContent();
+ ed.opts.onSave(content);
+ ed.render(content);
+ }
+ return false;
+ }
+ this.addNewLine();
+ return false;
+ }
+ return true;
+ }
+ onKeyupDocument(ed, ev) {
+ switch (ev.key) {
+ case "Control":
+ ed.isKeyControl = false;
+ return true;
+ }
+ return true;
+ }
+ render(content) {
+ const lines = content.split("\n");
+ this.elContent.innerText = "";
+ this.elLineNumber.innerText = "";
+ lines.forEach((line, x) => {
+ const el = document.createElement("div");
+ el.innerText = `${x + 1}`;
+ this.elLineNumber.appendChild(el);
+ const div = document.createElement("div");
+ div.innerText = line;
+ if (line == "") {
+ div.appendChild(document.createElement("br"));
+ }
+ this.elContent.appendChild(div);
+ });
+ this.totalLine = lines.length;
+ }
+ renderLineNumber(content) {
+ const lines = content.split("\n");
+ this.elLineNumber.innerText = "";
+ lines.forEach((_, x) => {
+ const el = document.createElement("div");
+ el.innerText = `${x + 1}`;
+ this.elLineNumber.appendChild(el);
+ });
+ this.totalLine = lines.length;
+ }
+}
diff --git a/editor/example.js b/editor/example.js
new file mode 100644
index 0000000..cbda425
--- /dev/null
+++ b/editor/example.js
@@ -0,0 +1,65 @@
+// SPDX-FileCopyrightText: 2019 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+import { WuiEditor } from "./editor.js";
+const nodeFile = {
+ name: "Test",
+ path: "/test",
+ is_dir: false,
+ content_type: "text/plain",
+ mod_time: 0,
+ size: 0,
+ mode: "",
+ childs: [],
+ content: btoa(`mkdir -p \${HOME}/aur/stackdriver-collectd
+
+git -C \${HOME}/aur/stackdriver-collectd clone \\
+ ssh://aur@aur.archlinux.org/stackdriver-collectd.git .
+
+sh -c "cd \${HOME}/aur/stackdriver-collectd; \\
+ makepkg --force --install --noconfirm"
+pacman -Ql stackdriver-collectd
+
+sudo systemctl enable stackdriver-collectd
+
+#put! {{.BaseDir}}/_template/etc/collectd-influxdb.conf /opt/collectd/etc/collectd.conf
+
+sudo systemctl restart stackdriver-collectd
+sudo systemctl status stackdriver-collectd
+
+##---- Connect telegraf with collectd
+
+{{.Val "influxdb::dir"}}/bin/influx bucket create \\
+ --name stackdriver_collectd \\
+ --description "stackdriver collectd" \\
+ --org {{.Val "influxdb::org"}} \\
+ --token {{.Val "influxdb:telegraf:token"}} \\
+ --retention "3d"
+
+#put: {{.BaseDir}}/_template/etc/telegraf/telegraf.d/stackdriver-collectd.conf \\
+ {{.Val "influxdb::dir"}}/etc/telegraf/telegraf.d/stackdriver-collectd.conf
+
+sudo systemctl restart telegraf
+sudo systemctl status telegraf
+`),
+};
+const opts = {
+ id: "editor",
+ isEditable: true,
+ onSave: (content) => {
+ const lines = content.split("\n");
+ lines.forEach((line, x) => {
+ console.log(`${x}: ${line}`);
+ });
+ },
+};
+const wuiEditor = new WuiEditor(opts);
+wuiEditor.open(nodeFile);
+const optsro = {
+ id: "editor-readonly",
+ isEditable: false,
+ onSave: (content) => {
+ console.log("OnSave: ", content);
+ },
+};
+const edro = new WuiEditor(optsro);
+edro.open(nodeFile);