Allow search query results in tables

This commit is contained in:
Peter Stuifzand 2020-11-08 17:01:47 +01:00
parent f3737f96bd
commit 8513e4b96c
2 changed files with 146 additions and 75 deletions

View File

@ -142,6 +142,37 @@ function showSearchResultsExtended(element, template, searchTool, query, input,
})
}
function formatLineResult(hit) {
return [
{
text: "[[" + hit.title + "]]",
indented: 0,
fold: 'open',
hidden: false,
fleeting: true
},
{
text: hit.line,
indented: 1,
fold: 'open',
hidden: false,
fleeting: true
}
]
}
function formatTitleResult(hit) {
return [
{
text: "[[" + hit.title + "]]",
indented: 0,
fold: 'open',
hidden: false,
fleeting: true
}
]
}
function renderGraphs() {
$('code.language-dot').each(function (i, code) {
if (!code.innerText) {
@ -163,11 +194,23 @@ function renderGraphs() {
function el(tag, children = []) {
let el = document.createElement(tag)
_.each(children, item => {
el.appendChild(item)
if (item !== undefined) el.appendChild(item)
})
return el
}
function mflatten(rowData) {
return Promise.all(rowData.reduce(function (a, b) {
return a.concat(b);
}, []));
}
function flatten(rowData) {
return rowData.reduce(function (a, b) {
return a.concat(b);
}, []);
}
function Editor(holder, input) {
function renderInline(cellText) {
if (!cellText) return document.createTextNode('')
@ -179,38 +222,57 @@ function Editor(holder, input) {
return span[0];
}
function promiseMapAll(p, f) {
return p.then(all => Promise.all(_.map(all, f)))
}
function transformTable(editor, id, element) {
editor.treeForId(id).then(tree => {
let header = _.find(tree[0].children, c => c.text === 'headers') || []
let rows = _.find(tree[0].children, c => c.text === 'rows') || []
editor.treeForId(id)
.then(tree => {
let header = _.find(tree[0].children, c => c.text === 'headers') || []
let rows = _.find(tree[0].children, c => c.text === 'rows') || []
let rowData = _.map(rows.children, row => {
// FIXME: Use a real parse link function
let page = row.text.substring(2).substring(0, row.text.length - 4)
return fetch('/' + page + '?format=metakv')
.then(res => res.json())
.then(res => res.meta)
.then(rowData => {
return el("tr", [
el("td", [renderInline(row.text)]),
..._.map(header.children, col => {
let td = el("td")
let value = rowData[_.snakeCase(_.trim(col.text))];
if (col.children && col.children.length > 0) {
value = col.children[0].text
}
transform(value ? value.replace(/^:/, '=') : '', $(td), id, editor, rowData)
return td
})
])
let collection = _.map(rows.children, child => {
let res = child.text.match(/{{query(!?):\s*([^}]+)}}/)
if (res && res[1] === '!') {
return search.startQuery(res[2])
.then(hits => _.uniqBy(_.flatMap(hits, formatTitleResult), _.property('text')))
}
return Promise.resolve().then(() => [child])
});
Promise.all(collection)
.then(_.flatten)
.then(_.partialRight(_.map, _.property('text')))
.then(_.uniq)
.then(rowTexts => {
return _.map(rowTexts, rowText => {
let page = rowText.substring(2).substring(0, rowText.length - 4)
return fetch('/' + page + '?format=metakv')
.then(res => res.ok ? res.json() : {meta: {}})
.then(res => res.meta)
.then(rowData => {
rowData.title = rowData.title || rowText
return el("tr", [
el("td", [renderInline(rowText)]),
..._.map(header.children, col => {
let td = el("td")
let value = rowData[_.snakeCase(_.trim(col.text))];
if (col.children && col.children.length > 0) {
value = col.children[0].text
}
transform(value ? value.replace(/^:/, '=') : '', $(td), id, editor, rowData)
return td
})
])
})
})
})
})
Promise.all(rowData)
.then(trs => {
return el("table", [
el("thead", [
el("tr", [
.then(mflatten)
.then(trs => {
return el("table", [
el("thead", [
el("tr", [
el("th", [
document.createTextNode("Title")
]),
@ -219,13 +281,21 @@ function Editor(holder, input) {
document.createTextNode(col.text)
])
})
]
),
]),
el("tbody", trs)
])
}).then(table => element.html(table))
})
]),
]),
el("tbody", trs)
])
})
.then(table => {
table.classList.add('table')
table.classList.add('wiki-table')
let div = el('div', [table])
div.classList.add('table-wrapper')
return element.html(div);
})
})
}
function transformMathExpression(converted, scope) {
@ -242,7 +312,7 @@ function Editor(holder, input) {
if (parsedExpr.isAssignmentNode) {
converted = parsedExpr.object.name + " = <i>" + evaluated.toString() + "</i>"
} else {
converted = expr + " = <i>" + evaluated.toString() + "</i>"
converted = "<span class='expression'>" + expr + " = </span><i>" + evaluated.toString() + "</i>"
}
} catch (e) {
converted = converted + ' <span style="background: red; color: white;">' + e.message + '</span>';
@ -331,11 +401,11 @@ function Editor(holder, input) {
).save().then(() => indicator.done())
})
// editor.on('rendered', function () {
// PrismJS.highlightAll()
// mermaid.init()
// renderGraphs();
// })
// editor.on('rendered', function () {
// PrismJS.highlightAll()
// mermaid.init()
// renderGraphs();
// })
menu.connectContextMenu(editor)
@ -522,47 +592,45 @@ function Editor(holder, input) {
editor.on('stop-editing', function (input, id) {
let $input = $(input);
$input.parents('.list-item').removeClass('active');
$input.parents('.list-item').removeClass('active')
$('#link-complete').off()
// PrismJS.highlightAll()
// mermaid.init()
// renderGraphs();
if ($input.val()) {
let query = $input.val();
let res = query.match(/{{query: ([^}]+)}}/)
if (res) {
search.startQuery(res[1])
.then(hits => {
let results = _.flatMap(hits, hit => {
return [
{
text: "[[" + hit.title + "]]",
indented: 0,
fold: 'open',
hidden: false,
fleeting: true
},
{
text: hit.line,
indented: 1,
fold: 'open',
hidden: false,
fleeting: true
}
]
})
editor.replaceChildren(id, results)
})
.then(function () {
editor.render()
})
}
}
if (!$input.val()) return
let query = $input.val()
Promise.any([
match(query, /{{query(!?):\s*([^}]+)}}/)
])
.then(res => {
if (res[1] === '!') {
return search.startQuery(res[2])
.then(hits => _.uniqBy(_.flatMap(hits, formatTitleResult), _.property('text')))
.then(results => editor.replaceChildren(id, results))
.finally(() => editor.render())
} else {
return search.startQuery(res[2])
.then(hits => _.flatMap(hits, formatLineResult))
.then(results => editor.replaceChildren(id, results))
.finally(() => editor.render())
}
})
.catch(() => console.log('match error'))
});
return editor
})
}
function match(s, re) {
return new Promise((resolve, reject) => {
let res = s.match(re)
if (res) resolve(res)
else reject()
});
}
let searchInput = document.getElementById('search-input');
_.tap(search.search(searchInput), searcher => {

View File

@ -457,6 +457,9 @@ input.input-line, input.input-line:active {
width: 400px;
}
}
.wiki-table .expression {
display: none;
}
.todo--todo {
}