aboutsummaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
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);