Implemented queries for tables (#729)
parent
aaad3dbf0a
commit
4056c4f2f2
|
@ -104,6 +104,12 @@ functions:
|
|||
events:
|
||||
- editor:complete
|
||||
|
||||
# Tables
|
||||
indexTables:
|
||||
path: "table.ts:indexTables"
|
||||
events:
|
||||
- page:index
|
||||
|
||||
# Headers
|
||||
indexHeaders:
|
||||
path: header.ts:indexHeaders
|
||||
|
@ -126,7 +132,6 @@ functions:
|
|||
events:
|
||||
- page:index
|
||||
|
||||
|
||||
# Hashtags
|
||||
indexTags:
|
||||
path: tags.ts:indexTags
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import { CompleteEvent, IndexTreeEvent, ObjectValue } from "$type/types.ts";
|
||||
import { collectNodesMatching, ParseTree } from "$lib/tree.ts";
|
||||
import { indexObjects } from "./api.ts";
|
||||
import { collectNodesOfType } from "$lib/tree.ts";
|
||||
|
||||
type TableRowObject =
|
||||
& ObjectValue<{
|
||||
tableref: string;
|
||||
page: string;
|
||||
pos: number;
|
||||
}>
|
||||
& Record<string, any>;
|
||||
|
||||
/**
|
||||
* Replace any invalid characters in a string so it can serve as indexed field name in a query
|
||||
* @param str the input string
|
||||
* @returns All lowercase string with special chars replaced with underscore
|
||||
*/
|
||||
function cleanHeaderFieldName(str: string): string {
|
||||
return str.replace(/[\W_]+/g, "_").toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat text properties of all child nodes
|
||||
* @param nodes
|
||||
* @returns
|
||||
*/
|
||||
function concatChildrenTexts(nodes: ParseTree[]): string {
|
||||
return nodes.map((c) => c.text).join("").trim();
|
||||
}
|
||||
|
||||
export async function indexTables({ name: pageName, tree }: IndexTreeEvent) {
|
||||
console.log(`Indexing tables in '${pageName}'`);
|
||||
const result: ObjectValue<TableRowObject>[] = [];
|
||||
|
||||
collectNodesMatching(tree, (t) => !!t.type?.startsWith("Table")).forEach(
|
||||
(table) => {
|
||||
const rows = collectNodesOfType(table, "TableRow");
|
||||
const header = collectNodesOfType(table, "TableHeader")[0]; //Use first header. As per markdown spec there can only be exactly one
|
||||
const headerLabels = collectNodesOfType(header, "TableCell").map((cell) =>
|
||||
concatChildrenTexts(cell.children!)
|
||||
).map(cleanHeaderFieldName);
|
||||
//console.log("Header labels", headerLabels);
|
||||
|
||||
for (const row of rows) {
|
||||
const tags = new Set<string>();
|
||||
collectNodesOfType(row, "Hashtag").forEach((h) => {
|
||||
// Push tag to the list, removing the initial #
|
||||
tags.add(h.children![0].text!.substring(1));
|
||||
});
|
||||
|
||||
const cells = collectNodesOfType(row, "TableCell");
|
||||
|
||||
const tableRow: TableRowObject = {
|
||||
tableref: `${pageName}@${table.from}`,
|
||||
ref: `${pageName}@${row.from}`,
|
||||
tag: "table",
|
||||
tags: [...tags],
|
||||
page: pageName,
|
||||
pos: row.from!,
|
||||
};
|
||||
cells.forEach((c, i) => {
|
||||
const content = concatChildrenTexts(c.children!);
|
||||
const label = headerLabels[i];
|
||||
tableRow[label!] = content;
|
||||
});
|
||||
result.push(tableRow);
|
||||
|
||||
//console.log("Cells", cells);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
console.log("Found", result.length, "row(s)");
|
||||
await indexObjects(pageName, result);
|
||||
}
|
|
@ -37,6 +37,22 @@ Note that you can also query this page using the `example-tag` directly:
|
|||
example-tag
|
||||
```
|
||||
|
||||
## table
|
||||
Markdown table rows are indexed using the `table` tag, any additional tags can be added using [[Tags]] in any of its cells.
|
||||
|
||||
| Title | Description Text |
|
||||
| --- | ----- |
|
||||
| This is some key | The value contains a #table-tag |
|
||||
| Some Row | This is an example row in between two others |
|
||||
| Another key | This time without a tag |
|
||||
|
||||
|
||||
```query
|
||||
table
|
||||
```
|
||||
|
||||
Table headers will be normalized by converting them to lowercase and replacing all non alphanumeric characters with `_`.
|
||||
|
||||
## task
|
||||
|
||||
task
|
||||
|
|
Loading…
Reference in New Issue