diff options
| author | Shulhan <ms@kilabit.info> | 2024-09-15 14:32:48 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2024-09-15 14:32:48 +0700 |
| commit | d1e96e09438b4a5c7580b86c469e817a61be991f (patch) | |
| tree | 4d81fb2fd62207bbb9162b81083c721ec8fd8e29 /editor | |
| parent | 1cc9c9dd68a3a59c685505228336430624608852 (diff) | |
| download | pakakeh.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.js | 205 | ||||
| -rw-r--r-- | editor/example.js | 65 |
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); |
