Skip to content

Commit 9c55aaa

Browse files
authored
Merge pull request #3526 from obsidian-tasks-group/feat-frontmatter-outlinks
feat: Add `outlinksInProperties` and `outlinksInBody` - `outlinks` returns both
2 parents 755f69b + 764adb2 commit 9c55aaa

File tree

5 files changed

+352
-31
lines changed

5 files changed

+352
-31
lines changed

src/Scripting/TasksFile.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,23 @@ export class TasksFile {
5151
}
5252

5353
/**
54-
* Return an array of {@link Link} in the body of the file.
54+
* Return an array of {@link Link} all the links in the file - both in frontmatter and in the file body.
5555
*/
5656
get outlinks(): Link[] {
57+
return [...this.outlinksInProperties, ...this.outlinksInBody];
58+
}
59+
60+
/**
61+
* Return an array of {@link Link} in the file's properties/frontmatter.
62+
*/
63+
get outlinksInProperties(): Link[] {
64+
return this.cachedMetadata.frontmatterLinks?.map((link) => new Link(link, this.filenameWithoutExtension)) ?? [];
65+
}
66+
67+
/**
68+
* Return an array of {@link Link} in the body of the file.
69+
*/
70+
get outlinksInBody(): Link[] {
5771
return this.cachedMetadata?.links?.map((link) => new Link(link, this.filenameWithoutExtension)) ?? [];
5872
}
5973

tests/Obsidian/Cache.test.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -755,21 +755,9 @@ describe('accessing links in file', function () {
755755

756756
const cachedMetadata: CachedMetadata = task.file.cachedMetadata;
757757

758-
/**
759-
* I am thinking of the following, to evantually make links accessible to users.
760-
* 1. Provide a class or interface called Link, with fields:
761-
* - displayText, e.g. "link_in_yaml"
762-
* - link, e.g. "link_in_yaml"
763-
* - original, e.g. "[[link_in_yaml]]"
764-
* 2. Add some getters that construct the relevant Link objects from cached metadata on demand, such as:
765-
* - task.file.linksInBody
766-
* - task.file.linksInFrontMatter
767-
* - task.file.allLinks
768-
* - task.links
769-
* 3. Consider the vocabulary - some dataview users talk about inlines and outlinks.
770-
* The above are all outlinks - but do we want to name them as such, to prepare
771-
* for if or when inlinks are also supported?
772-
*/
758+
// Usability note:
759+
// These tests are for visualising how Obsidian caches link properties.
760+
// See TasksFile and ListItem classes for accessing links via the Link class in Tasks cvode
773761

774762
it('see source', () => {
775763
expect(data.fileContents).toMatchInlineSnapshot(`
@@ -788,7 +776,7 @@ describe('accessing links in file', function () {
788776
`);
789777
});
790778

791-
it('should access links in frontmatter', () => {
779+
it('visualise raw links in frontmatter', () => {
792780
const frontMatterLinks = cachedMetadata['frontmatterLinks'];
793781
expect(frontMatterLinks).toBeDefined();
794782

@@ -804,7 +792,7 @@ describe('accessing links in file', function () {
804792
`);
805793
});
806794

807-
it('should access links in file body', () => {
795+
it('visualise raw links in file body', () => {
808796
const fileBodyLinks = cachedMetadata.links;
809797

810798
const originalLinkText = fileBodyLinks?.map((link) => link.original).join('\n');
@@ -836,7 +824,7 @@ describe('accessing links in file', function () {
836824
`);
837825
});
838826

839-
it('should access links in task line', () => {
827+
it('visualise raw links in task line', () => {
840828
const fileBodyLinks = cachedMetadata.links;
841829
const linksOnTask = fileBodyLinks?.filter((link) => link.position.start.line === task.lineNumber);
842830

tests/Scripting/TasksFile.test.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,37 @@ describe('TasksFile - reading frontmatter', () => {
239239
});
240240

241241
describe('TasksFile - accessing links', () => {
242-
it('should return all links in the file body', () => {
242+
it('should access all links in the file - both properties and body', () => {
243243
const tasksFile = getTasksFileFromMockData(links_everywhere);
244-
expect(tasksFile.outlinks.length).toEqual(3);
245-
expect(tasksFile.outlinks[0].originalMarkdown).toEqual('[[link_in_file_body]]');
244+
expect(tasksFile.outlinks.length).toEqual(5);
245+
expect(tasksFile.outlinks.map((link) => link.originalMarkdown)).toMatchInlineSnapshot(`
246+
[
247+
"[[link_in_yaml]]",
248+
"[[#A link in a link_in_heading]]",
249+
"[[link_in_file_body]]",
250+
"[[link_in_heading]]",
251+
"[[link_in_task_wikilink]]",
252+
]
253+
`);
254+
});
255+
256+
it('should access all links in the file body', () => {
257+
{
258+
const tasksFile = getTasksFileFromMockData(links_everywhere);
259+
expect(tasksFile.outlinksInBody.length).toEqual(3);
260+
expect(tasksFile.outlinksInBody[0].originalMarkdown).toEqual('[[link_in_file_body]]');
261+
}
262+
263+
{
264+
const tasksFile = getTasksFileFromMockData(link_in_yaml);
265+
expect(tasksFile.outlinksInBody.length).toEqual(0);
266+
}
246267
});
247268

248-
it('should return no yaml links', () => {
269+
it('should access all links in properties', () => {
249270
const tasksFile = getTasksFileFromMockData(link_in_yaml);
250-
expect(tasksFile.outlinks.length).toEqual(0);
271+
expect(tasksFile.outlinksInProperties.length).toEqual(1);
272+
expect(tasksFile.outlinksInProperties[0].originalMarkdown).toEqual('[[yaml_tags_is_empty]]');
251273
});
252274
});
253275

tests/Task/Link.test.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,21 +246,27 @@ describe('visualise links', () => {
246246

247247
it('note bodies', () => {
248248
let output = '';
249-
allCacheSampleData().map((file) => {
249+
allCacheSampleData().forEach((file) => {
250250
const tasksFile = getTasksFileFromMockData(file);
251-
output += visualiseLinks(tasksFile.outlinks, file);
251+
output += visualiseLinks(tasksFile.outlinksInBody, file);
252252
});
253253
verifyMarkdown(output);
254254
});
255255

256256
it('properties', () => {
257257
let output = '';
258-
allCacheSampleData().map((file) => {
258+
allCacheSampleData().forEach((file) => {
259+
const tasksFile = getTasksFileFromMockData(file);
260+
output += visualiseLinks(tasksFile.outlinksInProperties, file);
261+
});
262+
verifyMarkdown(output);
263+
});
264+
265+
it('outlinks', () => {
266+
let output = '';
267+
allCacheSampleData().forEach((file) => {
259268
const tasksFile = getTasksFileFromMockData(file);
260-
const frontmatterLinks = tasksFile.cachedMetadata.frontmatterLinks;
261-
const links =
262-
frontmatterLinks?.map((rawLink) => new Link(rawLink, tasksFile.filenameWithoutExtension)) ?? [];
263-
output += visualiseLinks(links, file);
269+
output += visualiseLinks(tasksFile.outlinks, file);
264270
});
265271
verifyMarkdown(output);
266272
});

0 commit comments

Comments
 (0)