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) {
|
function Editor(holder, input) {
|
||||||
let scope = {}
|
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 = {
|
const options = {
|
||||||
transform(text, element) {
|
transform(text, element, id, editor) {
|
||||||
if (text === undefined) {
|
if (text === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let converted = text
|
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)
|
converted = MD.render(converted)
|
||||||
} else if (converted.startsWith("=", 0)) {
|
} else if (converted.startsWith("=", 0)) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -10,21 +10,9 @@ import Store from './store'
|
||||||
textareaAutosizeInit($)
|
textareaAutosizeInit($)
|
||||||
|
|
||||||
function editor(root, inputData, options) {
|
function editor(root, inputData, options) {
|
||||||
root.classList.add('root')
|
|
||||||
root.setAttribute('tabindex', '-1')
|
|
||||||
|
|
||||||
let cursor = createCursor()
|
let cursor = createCursor()
|
||||||
let selection = createSelection()
|
let selection = createSelection()
|
||||||
|
let store = createStore(inputData);
|
||||||
let defaults = {
|
|
||||||
transform(text, element) {
|
|
||||||
element.html(he.encode(text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options = _.merge(defaults, options)
|
|
||||||
|
|
||||||
let drake = null;
|
|
||||||
|
|
||||||
function createStore(inputData) {
|
function createStore(inputData) {
|
||||||
let data = [
|
let data = [
|
||||||
|
@ -36,7 +24,98 @@ function editor(root, inputData, options) {
|
||||||
return Store(data);
|
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 = {
|
let events = {
|
||||||
change: [],
|
change: [],
|
||||||
|
@ -61,7 +140,7 @@ function editor(root, inputData, options) {
|
||||||
let line = $('<div class="line">')
|
let line = $('<div class="line">')
|
||||||
let content = $('<div class="content">')
|
let content = $('<div class="content">')
|
||||||
line.prepend(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="marker"></span>'))
|
||||||
line.prepend($('<span class="fold">▶</span>'))
|
line.prepend($('<span class="fold">▶</span>'))
|
||||||
el.prepend(line)
|
el.prepend(line)
|
||||||
|
@ -109,7 +188,7 @@ function editor(root, inputData, options) {
|
||||||
.find('.content')
|
.find('.content')
|
||||||
value.hidden = value.indented >= hideLevel
|
value.hidden = value.indented >= hideLevel
|
||||||
|
|
||||||
options.transform(value.text, $li)
|
options.transform(value.text, $li, value.id, EDITOR)
|
||||||
|
|
||||||
if (value.indented < hideLevel) {
|
if (value.indented < hideLevel) {
|
||||||
if (value.fold !== 'open') {
|
if (value.fold !== 'open') {
|
||||||
|
@ -226,7 +305,7 @@ function editor(root, inputData, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let $span = $('<div class="content">');
|
let $span = $('<div class="content">');
|
||||||
options.transform(text, $span)
|
options.transform(text, $span, element.data('id'), EDITOR)
|
||||||
element.replaceWith($span);
|
element.replaceWith($span);
|
||||||
trigger('stop-editing', currentEditor[0])
|
trigger('stop-editing', currentEditor[0])
|
||||||
editing = false
|
editing = false
|
||||||
|
@ -259,69 +338,6 @@ function editor(root, inputData, options) {
|
||||||
return $textarea
|
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) {
|
$(root).on('paste', '.input-line', function (event) {
|
||||||
let tag = event.target.tagName.toLowerCase();
|
let tag = event.target.tagName.toLowerCase();
|
||||||
if (tag === 'textarea' && currentEditor[0].value.substring(0, 3) === '```') {
|
if (tag === 'textarea' && currentEditor[0].value.substring(0, 3) === '```') {
|
||||||
|
@ -510,15 +526,7 @@ function editor(root, inputData, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return EDITOR;
|
||||||
on,
|
|
||||||
save,
|
|
||||||
saveTree,
|
|
||||||
copy,
|
|
||||||
update,
|
|
||||||
start,
|
|
||||||
zoomin
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default editor
|
export default editor
|
||||||
|
|
Loading…
Reference in New Issue
Block a user