From 84dd04d10781b0e70314cdd7783794fa738555c9 Mon Sep 17 00:00:00 2001 From: Peter Stuifzand Date: Sun, 25 Oct 2020 15:22:49 +0100 Subject: [PATCH] Add table rendering --- editor/src/editor.js | 66 ++++++++++++++- list-editor/index.js | 186 ++++++++++++++++++++++--------------------- 2 files changed, 161 insertions(+), 91 deletions(-) diff --git a/editor/src/editor.js b/editor/src/editor.js index e91a862..69a8225 100644 --- a/editor/src/editor.js +++ b/editor/src/editor.js @@ -142,19 +142,81 @@ function renderGraphs() { }) } +function createElement(tag, children) { + let el = document.createElement(tag) + _.each(children, item => { + el.appendChild(item) + }) + return el +} function Editor(holder, input) { let scope = {} + function renderInline(cellText) { + if (!cellText) return document.createTextNode('') + + MD.options.html = true + let rendered = MD.renderInline(cellText) + let span = $(""+rendered+"") + MD.options.html = false + return span[0]; + } + const options = { - transform(text, element) { + transform(text, element, id, editor) { if (text === undefined) { return; } let converted = text - if (converted.startsWith("```", 0) || converted.startsWith("$$", 0)) { + if (converted === '{{table}}') { + editor.treeForId(id).then(tree => { + let [header, rows] = tree[0].children + let rowData = _.map(rows.children, row => { + let page = row.text.substring(2).substring(0, row.text.length-4) + return fetch('/'+page+'?format=metakv') + .then(res => res.json()) + .then(res => [page, res.meta]) + }) + + // FIXME: don't wait for promises here, but at the end + Promise.all(rowData).then(res => { + return _.fromPairs(res) + }).then(data => { + return createElement("table", [ + createElement("thead", [ + createElement("tr", [ + createElement("th", [ + document.createTextNode("Title") + ]), + ..._.map(header.children, col => { + return createElement("th", [ + document.createTextNode(col.text) + ]) + }) + ] + ), + ]), + createElement("tbody", + _.map(rows.children, row => { + let page = row.text.substring(2).substring(0, row.text.length-4) + return createElement("tr", [ + createElement("td", [renderInline(row.text)]), + ..._.map(header.children, col => { + let td = createElement("td", []); + this.transform(data[page][col.text.toLowerCase()], $(td), id, editor) + return td + }) + ]) + }) + ) + ]) + }).then(table => element.html(table)) + }) + return + } else if (converted.startsWith("```", 0) || converted.startsWith("$$", 0)) { converted = MD.render(converted) } else if (converted.startsWith("=", 0)) { try { diff --git a/list-editor/index.js b/list-editor/index.js index a0daaa7..5de414c 100644 --- a/list-editor/index.js +++ b/list-editor/index.js @@ -10,21 +10,9 @@ import Store from './store' textareaAutosizeInit($) function editor(root, inputData, options) { - root.classList.add('root') - root.setAttribute('tabindex', '-1') - let cursor = createCursor() let selection = createSelection() - - let defaults = { - transform(text, element) { - element.html(he.encode(text)) - } - } - - options = _.merge(defaults, options) - - let drake = null; + let store = createStore(inputData); function createStore(inputData) { let data = [ @@ -36,7 +24,98 @@ function editor(root, inputData, options) { return Store(data); } - let store = createStore(inputData); + function save() { + return new Promise(function (resolve, reject) { + if (store.hasChanged()) { + resolve(store.debug().result) + store.clearChanged() + } else { + reject() + } + }); + } + + function saveTree(from) { + return new Promise(function (resolve, reject) { + if (store.hasChanged()) { + resolve(store.tree(from)) + store.clearChanged() + } + }); + } + + function treeForId(id) { + return new Promise(function (resolve, reject) { + resolve(store.tree(id)) + }) + } + + function copy(element, opt) { + let item = $(element).parents('.list-item') + let id = item.data('id') + + if (opt.recursive) { + return saveTree(id) + } + + return new Promise(function (resolve, reject) { + resolve(store.value(id)); + }); + } + + function zoomin(element, opt) { + let item = $(element).parents('.list-item') + let id = item.data('id') + return new Promise(function (resolve, reject) { + resolve(id); + }); + } + + + function on(evt, handler) { + events[evt].push(handler) + } + + function trigger(event) { + let args = [...arguments] + args.splice(0, 1) + _.each(events[event], function (handler) { + handler(...args) + }) + } + + function start() { + disableDragging(drake) + render(root, store); + drake = enableDragging(root) + + cursor.set(0) + startEditing(root, store, cursor) + } + + let EDITOR = { + on, + save, + saveTree, + copy, + update, + start, + zoomin, + treeForId + }; + + root.classList.add('root') + root.setAttribute('tabindex', '-1') + + let defaults = { + transform(text, element) { + element.html(he.encode(text)) + } + } + + options = _.merge(defaults, options) + + let drake = null; let events = { change: [], @@ -61,7 +140,7 @@ function editor(root, inputData, options) { let line = $('
') let content = $('
') line.prepend(content) - options.transform(value.text, content) + options.transform(value.text, content, value.id, EDITOR) line.prepend($('')) line.prepend($('')) el.prepend(line) @@ -109,7 +188,7 @@ function editor(root, inputData, options) { .find('.content') value.hidden = value.indented >= hideLevel - options.transform(value.text, $li) + options.transform(value.text, $li, value.id, EDITOR) if (value.indented < hideLevel) { if (value.fold !== 'open') { @@ -226,7 +305,7 @@ function editor(root, inputData, options) { } let $span = $('
'); - options.transform(text, $span) + options.transform(text, $span, element.data('id'), EDITOR) element.replaceWith($span); trigger('stop-editing', currentEditor[0]) editing = false @@ -259,69 +338,6 @@ function editor(root, inputData, options) { return $textarea } - function save() { - return new Promise(function (resolve, reject) { - if (store.hasChanged()) { - resolve(store.debug().result) - store.clearChanged() - } else { - reject() - } - }); - } - - function saveTree(from) { - return new Promise(function (resolve, reject) { - if (store.hasChanged()) { - resolve(store.tree(from)) - store.clearChanged() - } - }); - } - - function copy(element, opt) { - let item = $(element).parents('.list-item') - let id = item.data('id') - - if (opt.recursive) { - return saveTree(id) - } - - return new Promise(function (resolve, reject) { - resolve(store.value(id)); - }); - } - - function zoomin(element, opt) { - let item = $(element).parents('.list-item') - let id = item.data('id') - return new Promise(function (resolve, reject) { - resolve(id); - }); - } - - - function on(evt, handler) { - events[evt].push(handler) - } - - function trigger(event) { - let args = [...arguments] - args.splice(0, 1) - _.each(events[event], function (handler) { - handler(...args) - }) - } - - function start() { - disableDragging(drake) - render(root, store); - drake = enableDragging(root) - - cursor.set(0) - startEditing(root, store, cursor) - } - $(root).on('paste', '.input-line', function (event) { let tag = event.target.tagName.toLowerCase(); if (tag === 'textarea' && currentEditor[0].value.substring(0, 3) === '```') { @@ -510,15 +526,7 @@ function editor(root, inputData, options) { } } - return { - on, - save, - saveTree, - copy, - update, - start, - zoomin - }; + return EDITOR; } export default editor