Add table rendering
This commit is contained in:
parent
0db1197daa
commit
84dd04d107
|
@ -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 = $("<span>"+rendered+"</span>")
|
||||
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 {
|
||||
|
|
|
@ -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 = $('<div class="line">')
|
||||
let content = $('<div class="content">')
|
||||
line.prepend(content)
|
||||
options.transform(value.text, content)
|
||||
options.transform(value.text, content, value.id, EDITOR)
|
||||
line.prepend($('<span class="marker"></span>'))
|
||||
line.prepend($('<span class="fold">▶</span>'))
|
||||
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 = $('<div class="content">');
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user