Skip to content

Commit c663f62

Browse files
committed
feat: add tables to file metadata
1 parent b878580 commit c663f62

File tree

6 files changed

+56
-2
lines changed

6 files changed

+56
-2
lines changed

docs/docs/annotation/metadata-pages.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Dataview automatically adds a large amount of metadata to each page. These impli
2525
| `file.aliases` | List | A list of all aliases for the note as defined via the [YAML frontmatter](https://help.obsidian.md/How+to/Add+aliases+to+note). |
2626
| `file.tasks` | List | A list of all tasks (I.e., `| [ ] some task`) in this file. |
2727
| `file.lists` | List | A list of all list elements in the file (including tasks); these elements are effectively tasks and can be rendered in task views. |
28+
| `file.tables` | List | A list of all table in this file. |
2829
| `file.frontmatter` | List | Contains the raw values of all frontmatter in form of `key | value` text values; mainly useful for checking raw frontmatter values or for dynamically listing frontmatter keys. |
2930
| `file.day` | Date | Only available if the file has a date inside its file name (of form `yyyy-mm-dd` or `yyyymmdd`), or has a `Date` field/inline field. |
3031
| `file.starred` | Boolean | If this file has been bookmarked via the Obsidian Core Plugin "Bookmarks". |

src/data-import/markdown-file.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export function parsePage(path: string, contents: string, stat: FileStats, metad
7878
links,
7979
lists: markdownData.lists,
8080
fields: finalizeInlineFields(fields),
81+
tables: markdownData.tables,
8182
frontmatter: frontmatter,
8283
ctime: DateTime.fromMillis(stat.ctime),
8384
mtime: DateTime.fromMillis(stat.mtime),
@@ -136,11 +137,13 @@ export function parseMarkdown(
136137
contents: string[],
137138
metadata: CachedMetadata,
138139
linksByLine: Record<number, Link[]>
139-
): { fields: Map<string, Literal[]>; lists: ListItem[] } {
140+
): { fields: Map<string, Literal[]>; lists: ListItem[], tables: any } {
140141
let fields: Map<string, Literal[]> = new Map();
141142

142143
// Extract task data and append the global data extracted from them to our fields.
143144
let [lists, extraData] = parseLists(path, contents, metadata, linksByLine);
145+
let tables = parseTables(contents, metadata);
146+
144147
for (let [key, values] of extraData.entries()) {
145148
if (!fields.has(key)) fields.set(key, values);
146149
else fields.set(key, fields.get(key)!!.concat(values));
@@ -176,7 +179,7 @@ export function parseMarkdown(
176179
}
177180
}
178181

179-
return { fields, lists };
182+
return { fields, lists, tables };
180183
}
181184

182185
// TODO: Consider using an actual parser in leiu of a more expensive regex.
@@ -304,6 +307,42 @@ export function parseLists(
304307
return [Object.values(cache), literals];
305308
}
306309

310+
/**
311+
* Parse table from content and meta data. The implementation will not include column spans. It only work for
312+
* one column/one cell value.
313+
*/
314+
export function parseTables(
315+
content: string[],
316+
metadata: CachedMetadata,
317+
): Map<string, any>[] {
318+
const result: Map<string, any>[] = [];
319+
metadata.sections?.forEach(section => {
320+
if (section.type === 'table') {
321+
const headers = content[section.position.start.line]
322+
.split('|')
323+
.map(header => header.trim())
324+
.filter(header => header);
325+
let rows = content
326+
.slice(section.position.start.line + 2, section.position.end.line + 1)
327+
.map(row => row
328+
.split('|')
329+
.map(val => val.trim())
330+
.filter(row => row));
331+
// don't support expand column at the moment.
332+
if (rows.length === headers.length) {
333+
rows.forEach(row => {
334+
const record = headers.reduce((prev, key, index) => {
335+
prev[key] = row[index];
336+
return prev;
337+
}, {} as any);
338+
result.push(record);
339+
});
340+
}
341+
}
342+
});
343+
return result;
344+
}
345+
307346
/** Attempt to find a date associated with the given page from metadata or filenames. */
308347
function findDate(file: string, fields: Map<string, Literal>): DateTime | undefined {
309348
for (let key of fields.keys()) {

src/data-model/markdown.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ export class PageMetadata {
3333
/** The raw frontmatter for this document. */
3434
public frontmatter: Record<string, Literal>;
3535

36+
public tables: Map<string, any>[];
37+
3638
public constructor(path: string, init?: Partial<PageMetadata>) {
3739
this.path = path;
3840
this.fields = new Map<string, Literal>();
3941
this.frontmatter = {};
4042
this.tags = new Set<string>();
4143
this.aliases = new Set<string>();
4244
this.links = [];
45+
this.tables = [];
4346

4447
Object.assign(this, init);
4548

@@ -136,6 +139,7 @@ export class PageMetadata {
136139
aliases: Array.from(this.aliases),
137140
lists: this.lists.map(l => realCache.get(l.line)),
138141
tasks: this.lists.filter(l => !!l.task).map(l => realCache.get(l.line)),
142+
tables: this.tables,
139143
ctime: this.ctime,
140144
cday: stripTime(this.ctime),
141145
mtime: this.mtime,

src/data-model/serialized/markdown.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface SMarkdownPage {
1717
aliases: string[];
1818
lists: SListItem[];
1919
tasks: STask[];
20+
tables: Map<string, any>[];
2021
ctime: DateTime;
2122
cday: DateTime;
2223
mtime: DateTime;

test-vault/example read tables.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
```dataview
3+
TABLE file.tables WHERE length(file.tables) > 0
4+
```

test-vault/tables/git commands.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
| Command | Description |
3+
| --- | --- |
4+
| `git status` | List all *new or modified* files |
5+
| `git diff` | Show file differences that **haven't been** staged |

0 commit comments

Comments
 (0)