Skip to content

Commit a6ef18b

Browse files
authored
Merge pull request #3556 from obsidian-tasks-group/fix-isLinkTo
fix: `Link.isLinkTo()` now works when passed `TasksFile` objects
2 parents 8265289 + ecd2c30 commit a6ef18b

File tree

11 files changed

+181
-12
lines changed

11 files changed

+181
-12
lines changed

resources/sample_vaults/Tasks-Demo/How To/Access links.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ filter by function task.outlinks.some(link => link.destinationPath === query.fil
102102

103103
This should match one task, in [[Link to Access links file]].
104104

105-
There is a bug: this does not yet find the task it should do.
106-
107105
````text
108106
```tasks
109107
filter by function task.outlinks.some(link => link.isLinkTo(query.file))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# link_in_task_wikilink_different_case
2+
3+
- [ ] #task Task in 'link_in_task_wikilink_different_case' [[liNk_in_YaMl]]

src/Task/Link.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ export class Link {
9595
return false;
9696
}
9797

98-
return this.isLinkTo(destination.path);
98+
// Links only match if they resolve to the full path,
99+
// thus distinguishing between multiple identically named files
100+
// in different folders in the vault.
101+
return this.destinationPath === destination.path;
99102
}
100103
}

tests/Obsidian/AllCacheSampleData.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import link_in_heading from './__test_data__/link_in_heading.json';
4747
import link_in_task_html from './__test_data__/link_in_task_html.json';
4848
import link_in_task_markdown_link from './__test_data__/link_in_task_markdown_link.json';
4949
import link_in_task_wikilink from './__test_data__/link_in_task_wikilink.json';
50+
import link_in_task_wikilink_different_case from './__test_data__/link_in_task_wikilink_different_case.json';
5051
import link_in_yaml from './__test_data__/link_in_yaml.json';
5152
import link_is_broken from './__test_data__/link_is_broken.json';
5253
import links_everywhere from './__test_data__/links_everywhere.json';
@@ -144,6 +145,7 @@ export function allCacheSampleData(): SimulatedFile[] {
144145
link_in_task_html,
145146
link_in_task_markdown_link,
146147
link_in_task_wikilink,
148+
link_in_task_wikilink_different_case,
147149
link_in_yaml,
148150
link_is_broken,
149151
links_everywhere,
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
{
2+
"cachedMetadata": {
3+
"headings": [
4+
{
5+
"heading": "link_in_task_wikilink_different_case",
6+
"level": 1,
7+
"position": {
8+
"end": {
9+
"col": 38,
10+
"line": 0,
11+
"offset": 38
12+
},
13+
"start": {
14+
"col": 0,
15+
"line": 0,
16+
"offset": 0
17+
}
18+
}
19+
}
20+
],
21+
"links": [
22+
{
23+
"displayText": "liNk_in_YaMl",
24+
"link": "liNk_in_YaMl",
25+
"original": "[[liNk_in_YaMl]]",
26+
"position": {
27+
"end": {
28+
"col": 75,
29+
"line": 2,
30+
"offset": 115
31+
},
32+
"start": {
33+
"col": 59,
34+
"line": 2,
35+
"offset": 99
36+
}
37+
}
38+
}
39+
],
40+
"listItems": [
41+
{
42+
"parent": -2,
43+
"position": {
44+
"end": {
45+
"col": 75,
46+
"line": 2,
47+
"offset": 115
48+
},
49+
"start": {
50+
"col": 0,
51+
"line": 2,
52+
"offset": 40
53+
}
54+
},
55+
"task": " "
56+
}
57+
],
58+
"sections": [
59+
{
60+
"position": {
61+
"end": {
62+
"col": 38,
63+
"line": 0,
64+
"offset": 38
65+
},
66+
"start": {
67+
"col": 0,
68+
"line": 0,
69+
"offset": 0
70+
}
71+
},
72+
"type": "heading"
73+
},
74+
{
75+
"position": {
76+
"end": {
77+
"col": 75,
78+
"line": 2,
79+
"offset": 115
80+
},
81+
"start": {
82+
"col": 0,
83+
"line": 2,
84+
"offset": 40
85+
}
86+
},
87+
"type": "list"
88+
}
89+
],
90+
"tags": [
91+
{
92+
"position": {
93+
"end": {
94+
"col": 11,
95+
"line": 2,
96+
"offset": 51
97+
},
98+
"start": {
99+
"col": 6,
100+
"line": 2,
101+
"offset": 46
102+
}
103+
},
104+
"tag": "#task"
105+
}
106+
]
107+
},
108+
"fileContents": "# link_in_task_wikilink_different_case\n\n- [ ] #task Task in 'link_in_task_wikilink_different_case' [[liNk_in_YaMl]]\n",
109+
"filePath": "Test Data/link_in_task_wikilink_different_case.md",
110+
"getAllTags": [
111+
"#task"
112+
],
113+
"parseFrontMatterTags": null,
114+
"resolveLinkToPath": {
115+
"liNk_in_YaMl": "Test Data/link_in_yaml.md"
116+
}
117+
}

tests/Obsidian/__test_data__/metadataCache/resolvedLinks.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"Functions/Custom Filters With Simple Caching.md": {},
1717
"Functions/Custom Sorting.md": {},
1818
"Functions/Fields for Functions - Demo.md": {},
19-
"How To/Access links.md": {},
19+
"How To/Access links.md": {
20+
"Test Attachments/Link to Access links file.md": 2
21+
},
2022
"How To/Access properties in frontmatter.md": {},
2123
"How To/Find properties not read by Obsidian 1.9.x/README.md": {},
2224
"How To/Find tasks in notes with particular tag.md": {},
@@ -127,6 +129,9 @@
127129
"Styling/Theme - Minimal Theme.md": {},
128130
"Styling/Theme - Things Theme.md": {},
129131
"Tasks.md": {},
132+
"Test Attachments/Link to Access links file.md": {
133+
"How To/Access links.md": 1
134+
},
130135
"Test Attachments/markdownLink.md": {
131136
"Test Data/all_link_types.md": 1
132137
},
@@ -207,6 +212,9 @@
207212
"Test Data/multiple_headings.md": 1,
208213
"Test Attachments/a_pdf_file.pdf": 1
209214
},
215+
"Test Data/link_in_task_wikilink_different_case.md": {
216+
"Test Data/link_in_yaml.md": 1
217+
},
210218
"Test Data/link_in_yaml.md": {
211219
"Test Data/yaml_tags_is_empty.md": 1
212220
},

tests/Obsidian/__test_data__/metadataCache/unresolvedLinks.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"Styling/Theme - Minimal Theme.md": {},
102102
"Styling/Theme - Things Theme.md": {},
103103
"Tasks.md": {},
104+
"Test Attachments/Link to Access links file.md": {},
104105
"Test Attachments/markdownLink.md": {},
105106
"Test Attachments/wikilink.md": {},
106107
"Test Data/all_link_types.md": {},
@@ -153,6 +154,7 @@
153154
"|": 2,
154155
"|alias": 1
155156
},
157+
"Test Data/link_in_task_wikilink_different_case.md": {},
156158
"Test Data/link_in_yaml.md": {},
157159
"Test Data/link_is_broken.md": {
158160
"broken link - do not fix me": 1

tests/Task/Link.test.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import type { Reference } from 'obsidian';
22
import { TasksFile } from '../../src/Scripting/TasksFile';
33
import { Link } from '../../src/Task/Link';
44
import internal_heading_links from '../Obsidian/__test_data__/internal_heading_links.json';
5+
import link_in_heading from '../Obsidian/__test_data__/link_in_heading.json';
56
import link_in_task_markdown_link from '../Obsidian/__test_data__/link_in_task_markdown_link.json';
67
import link_in_task_wikilink from '../Obsidian/__test_data__/link_in_task_wikilink.json';
8+
import link_is_broken from '../Obsidian/__test_data__/link_is_broken.json';
79

810
import link_in_file_body from '../Obsidian/__test_data__/link_in_file_body.json';
911
import links_everywhere from '../Obsidian/__test_data__/links_everywhere.json';
@@ -13,11 +15,12 @@ import { addBackticks, formatToRepresentType } from '../Scripting/ScriptingTestH
1315
import { getTasksFileFromMockData } from '../TestingTools/MockDataHelpers';
1416
import { verifyMarkdown } from '../TestingTools/VerifyMarkdown';
1517
import { LinkResolver } from '../../src/Task/LinkResolver';
16-
import { getFirstLinkpathDest } from '../__mocks__/obsidian';
18+
import { getFirstLinkpathDest, getFirstLinkpathDestFromData } from '../__mocks__/obsidian';
1719

1820
function getLink(data: any, index: number) {
1921
const rawLink = data.cachedMetadata.links[index];
20-
return new Link(rawLink, data.filePath);
22+
const destinationPath = getFirstLinkpathDestFromData(data, rawLink);
23+
return new Link(rawLink, data.filePath, destinationPath);
2124
}
2225

2326
describe('linkClass', () => {
@@ -33,6 +36,18 @@ describe('linkClass', () => {
3336
expect(link.isLinkTo('link_in_file_body.md')).toEqual(true);
3437
});
3538

39+
describe('getLink() configures Link.destinationPath automatically', () => {
40+
it('should set the full path for a resolved link', () => {
41+
const link = getLink(link_in_heading, 0);
42+
expect(link.destinationPath).toEqual('Test Data/multiple_headings.md');
43+
});
44+
45+
it('should not set the full path for a broken/unresolved link', () => {
46+
const link = getLink(link_is_broken, 0);
47+
expect(link.destinationPath).toEqual(null);
48+
});
49+
});
50+
3651
describe('return markdown to navigate to a link', () => {
3752
// These links are useful
3853
it('should return the filename if simple [[filename]]', () => {
@@ -300,12 +315,12 @@ describe('linkClass', () => {
300315
expect(linkToAFolder.isLinkTo('Test Data/link_in_task_wikilink.md')).toEqual(true);
301316
});
302317

303-
it('matches TasksFile', () => {
318+
it('matches TasksFile - only exact paths match', () => {
304319
const linkToAFolder = getLink(link_in_task_wikilink, 2);
305320
expect(linkToAFolder.originalMarkdown).toMatchInlineSnapshot('"[[Test Data/link_in_task_wikilink]]"');
306321

307322
expect(linkToAFolder.isLinkTo(new TasksFile('Test Data/link_in_task_wikilink.md'))).toEqual(true);
308-
expect(linkToAFolder.isLinkTo(new TasksFile('link_in_task_wikilink.md'))).toEqual(true);
323+
expect(linkToAFolder.isLinkTo(new TasksFile('link_in_task_wikilink.md'))).toEqual(false);
309324
expect(linkToAFolder.isLinkTo(new TasksFile('Wrong Test Data/link_in_task_wikilink.md'))).toEqual(false);
310325
expect(linkToAFolder.isLinkTo(new TasksFile('something_obviously_different.md'))).toEqual(false);
311326
});

tests/Task/Link.test.visualise_links_note_bodies.approved.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,14 @@
380380
`link.destinationPath      `: `'null'`
381381
`link.displayText          `: `'| > alias'`
382382

383+
## Test Data/link_in_task_wikilink_different_case.md
384+
385+
`link.originalMarkdown     `: `'[[liNk_in_YaMl]]'`
386+
`link.markdown             `: `'[[liNk_in_YaMl]]'`
387+
`link.destination          `: `'liNk_in_YaMl'`
388+
`link.destinationPath      `: `'Test Data/link_in_yaml.md'`
389+
`link.displayText          `: `'liNk_in_YaMl'`
390+
383391
## Test Data/link_is_broken.md
384392

385393
`link.originalMarkdown     `: `'[[broken link - do not fix me]]'`

tests/Task/Link.test.visualise_links_outlinks.approved.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@
400400
`link.destinationPath      `: `'null'`
401401
`link.displayText          `: `'| > alias'`
402402

403+
## Test Data/link_in_task_wikilink_different_case.md
404+
405+
`link.originalMarkdown     `: `'[[liNk_in_YaMl]]'`
406+
`link.markdown             `: `'[[liNk_in_YaMl]]'`
407+
`link.destination          `: `'liNk_in_YaMl'`
408+
`link.destinationPath      `: `'Test Data/link_in_yaml.md'`
409+
`link.displayText          `: `'liNk_in_YaMl'`
410+
403411
## Test Data/link_in_yaml.md
404412

405413
`link.originalMarkdown     `: `'[[yaml_tags_is_empty]]'`

0 commit comments

Comments
 (0)