import {LitElement, html, unsafeHTML} from './lit-all.min.js'; import * as tfrpc from '/static/tfrpc.js'; import * as commonmark from './commonmark.min.js'; class TfWikiDocElement extends LitElement { static get properties() { return { whoami: {type: String}, wiki: {type: String}, value: {type: Object}, blob: {type: String}, blob_original: {type: String}, blob_for_value: {type: String}, is_editing: {type: Boolean}, }; } constructor() { super(); } markdown(md) { var reader = new commonmark.Parser({safe: true}); var writer = new commonmark.HtmlRenderer(); var parsed = reader.parse(md || ''); let walker = parsed.walker(); let event; while ((event = walker.next())) { let node = event.node; if (event.entering) { if (node.type === 'link') { if (node.destination.indexOf(':') == -1 && node.destination.indexOf('/') == -1) { node.destination = `#${this.wiki?.name}/${node.destination}`; } } } } return writer.render(parsed); } async load_blob() { let blob = await tfrpc.rpc.get_blob(this.value?.blob); if (blob.endsWith('.box')) { let d = await tfrpc.rpc.try_decrypt(this.whoami, blob); if (d) { blob = d; } } this.blob = blob; this.blob_original = blob; } on_edit(event) { this.blob = event.srcElement.value; } on_discard(event) { this.blob = this.blob_original; this.is_editing = false; } async append_message(draft) { let blob = this.blob; if (draft) { blob = await tfrpc.rpc.encrypt(this.whoami, this.value.editors, blob); } let id = await tfrpc.rpc.store_blob(blob); let message = { type: 'wiki-doc', key: this.value.id, parent: this.value.parent, blob: id, }; if (draft) { message.recps = this.value.editors; print(message); message = await tfrpc.rpc.encrypt(this.whoami, this.value.editors, JSON.stringify(message)); } print(message); await tfrpc.rpc.appendMessage(this.whoami, message); this.is_editing = false; } async on_save_draft() { return this.append_message(true); } async on_publish() { return this.append_message(false); } render() { let value = JSON.stringify(this.value); if (this.blob_for_value != value) { this.blob_for_value = value; this.blob = undefined; this.blob_original = undefined; this.load_blob(); } let self = this; return html` <div style="display: inline-flex; flex-direction: row"> <button ?disabled=${!this.whoami || this.is_editing} @click=${() => self.is_editing = true}>Edit</button> <button ?disabled=${this.blob == this.blob_original} @click=${this.on_save_draft}>Save Draft</button> <button ?disabled=${this.blob == this.blob_original && !this.value?.draft} @click=${this.on_publish}>Publish</button> <button ?disabled=${!this.is_editing} @click=${this.on_discard}>Discard</button> </div> <div style="display: flex; flex-direction: row"> <textarea ?hidden=${!this.is_editing} style="flex: 1 1; min-height: 10em" @input=${this.on_edit} .value=${this.blob ?? ''}></textarea> <div style="flex: 1 1">${unsafeHTML(this.markdown(this.blob))}</div> </div> `; } } customElements.define('tf-wiki-doc', TfWikiDocElement);