Skip to content

Commit dcab441

Browse files
committed
feat: exclude by globs
closes #11
1 parent c939aec commit dcab441

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ If both exclude *from* and *to* are set to `B`, the the output will be:
9494
1 [[X]]
9595
```
9696

97+
**Exclude links from paths** and **Exclude links to paths** works similarly to filename exclusion, but accept glob patterns. Check [picomatch docs](https://www.npmjs.com/package/picomatch#globbing-features) for detailed information. Useful, when you want to exclude some directories, for example, exclude everything from directory *Dailies* is `Dailies/**/*`.
98+
9799

98100
## Compatibility
99101
v0.0.1 was developed against Obsidian v0.9.12, but it may work in earlier versions (v0.9.7+).

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
"@rollup/plugin-node-resolve": "^9.0.0",
2020
"@rollup/plugin-typescript": "^6.0.0",
2121
"@types/node": "^14.14.8",
22+
"@types/picomatch": "^2.2.1",
2223
"obsidian": "https://github.com/obsidianmd/obsidian-api/tarball/master",
2324
"rollup": "^2.33.2",
2425
"standard-version": "^9.0.0",
2526
"tslib": "^2.0.3",
2627
"typescript": "^4.0.3"
2728
},
2829
"dependencies": {
29-
"deepmerge": "^4.2.2"
30+
"deepmerge": "^4.2.2",
31+
"picomatch": "^2.2.2"
3032
}
3133
}

src/main.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import deepmerge from 'deepmerge';
2+
import picomatch from 'picomatch';
23
import { Plugin, PluginSettingTab, Setting, Vault, normalizePath, TFile, getLinkpath, ReferenceCache, Notice } from 'obsidian';
34

45
interface IndexNode {
@@ -63,7 +64,7 @@ export default class LinkIndexer extends Plugin {
6364

6465
const files = this.app.vault.getMarkdownFiles();
6566
files.forEach((f) => {
66-
if (this.isExcluded(f, preset.excludeFromFilenames)) return;
67+
if (this.isExcluded(f, preset.excludeFromFilenames, preset.excludeFromGlobs)) return;
6768
this.grabLinks(uniqueLinks, f, this.app.metadataCache.getFileCache(f).links, preset)
6869
if (preset.includeEmbeds) {
6970
this.grabLinks(uniqueLinks, f, this.app.metadataCache.getFileCache(f).embeds, preset)
@@ -81,15 +82,18 @@ export default class LinkIndexer extends Plugin {
8182
}
8283
}
8384

84-
isExcluded(f: TFile, filenamePatterns: string[]) {
85-
return this.globalExcludes.find((g) => pathEqual(g, f.path)) || filenamePatterns.some((p) => new RegExp(p).test(f.name));
85+
isExcluded(f: TFile, filenamePatterns: string[], globPatterns: string[]) {
86+
const isGloballyExcluded = this.globalExcludes.some((g) => pathEqual(g, f.path));
87+
const isFilenameExcluded = filenamePatterns.some((p) => new RegExp(p).test(f.name));
88+
const isGlobExcluded = picomatch.isMatch(f.path, globPatterns);
89+
return isGloballyExcluded || isFilenameExcluded || isGlobExcluded;
8690
}
8791

8892
grabLinks(uniqueLinks: Record<string, IndexNode>, f: TFile, links: ReferenceCache[], preset: UsedLinks) {
8993
links?.forEach((l) => {
9094
const link = getLinkpath(l.link);
9195
const originFile = this.app.metadataCache.getFirstLinkpathDest(link, f.path);
92-
if (originFile && (preset.nonexistentOnly || this.isExcluded(originFile, preset.excludeToFilenames))) {
96+
if (originFile && (preset.nonexistentOnly || this.isExcluded(originFile, preset.excludeToFilenames, preset.excludeToGlobs))) {
9397
return;
9498
}
9599
const origin = originFile ? originFile.path : link;
@@ -114,7 +118,9 @@ class UsedLinks {
114118
linkToFiles = true;
115119
nonexistentOnly = false;
116120
excludeToFilenames: string[] = [];
121+
excludeToGlobs: string[] = [];
117122
excludeFromFilenames: string[] = [];
123+
excludeFromGlobs: string[] = [];
118124

119125
constructor() {
120126
this.name = Date.now().toString();
@@ -228,6 +234,18 @@ class LinkIndexerSettingTab extends PluginSettingTab {
228234
})
229235
);
230236

237+
new Setting(containerEl)
238+
.setName('Exclude links from paths')
239+
.setDesc('Expects path globs. Checks for file path including filename.')
240+
.addTextArea((text) =>
241+
text
242+
.setValue(report.excludeFromGlobs.join('\n'))
243+
.onChange(async (value) => {
244+
report.excludeFromGlobs = value.split('\n').filter((v) => v);
245+
await this.saveData({ refreshUI: false });
246+
})
247+
);
248+
231249
new Setting(containerEl)
232250
.setName('Exclude links to files')
233251
.setDesc('Expects regex patterns. Checks for filename without path.')
@@ -240,6 +258,18 @@ class LinkIndexerSettingTab extends PluginSettingTab {
240258
})
241259
);
242260

261+
new Setting(containerEl)
262+
.setName('Exclude links to paths')
263+
.setDesc('Expects path globs. Checks for file path including filename.')
264+
.addTextArea((text) =>
265+
text
266+
.setValue(report.excludeToGlobs.join('\n'))
267+
.onChange(async (value) => {
268+
report.excludeToGlobs = value.split('\n').filter((v) => v);
269+
await this.saveData({ refreshUI: false });
270+
})
271+
);
272+
243273
const deleteButton = new Setting(containerEl).addButton((extra) => {
244274
return extra.setButtonText('Delete preset').onClick(async() => {
245275
const index = plugin.settings.usedLinks.findIndex((r) => r.name === report.name);

0 commit comments

Comments
 (0)