Compare commits

...

21 commits
1.6.8 ... main

Author SHA1 Message Date
Michael Naumov
b016ba5af8 chore: update libs 2026-07-21 19:18:15 -06:00
Michael Naumov
877db481cd chore: release 1.6.11 2026-07-20 18:39:46 -06:00
Michael Naumov
a3c2a3763b chore: update libs 2026-07-20 18:38:21 -06:00
Michael Naumov
259f6c2b58 chore: release 1.6.10 2026-07-20 14:51:11 -06:00
Michael Naumov
cd847532c7 chore: update libs 2026-07-20 14:50:32 -06:00
Michael Naumov
5547b20570 chore(demo-vault): drop committed Invocables placeholder
The Demo Vault Helper (obsidian-dev-utils `bootstrapDemoVault`) now creates the
CodeScript Toolkit invocable-scripts folder at runtime, so the vault no longer
commits an otherwise-empty `Invocables/.gitkeep` placeholder.
2026-07-20 14:37:55 -06:00
Michael Naumov
f58b8b91f4 fix(demo-vault): export invoke() from startup script; add Invocables folder
CodeScript Toolkit runs the startup script via `startupScript.invoke(app)`, so a
top-level script with no `invoke` export threw `this.startupScript.invoke is not
a function` on vault open. Wrap the body in an exported `invoke(app)`. Also add an
empty `Invocables/` folder so every demo vault has the same CodeScript Toolkit
layout regardless of whether it ships invocable scripts.
2026-07-20 14:12:45 -06:00
Michael Naumov
633e49a849 chore: release 1.6.9 2026-07-20 12:50:26 -06:00
Michael Naumov
fc770c4818 docs: standardize demo-vault README 2026-07-20 11:08:11 -06:00
Michael Naumov
34aab9a63b docs: drop per-plugin demo-vault setup notes (bootstrap covered by ODU harness) 2026-07-20 10:46:40 -06:00
Michael Naumov
5e424f6fb1 docs: unnumber demo-vault setup notes 2026-07-20 10:18:08 -06:00
Michael Naumov
284ec28dcb Merge branch 'T107-renumber': number Backlink Full Path demo vault example notes (S2) 2026-07-20 09:04:58 -06:00
Michael Naumov
83f2bd105c docs: number demo vault example notes 2026-07-20 09:01:39 -06:00
Michael Naumov
696e59f268 Merge branch 'T107': create the Backlink Full Path demo vault (S2)
Bumps obsidian-dev-utils across the 86->87 major (no source fallout), registers
the Open demo vault command, and ships a curated demo-vault/ where three same-named
notes make the full-path Backlinks feature visible, with a static demo-vault
coverage suite. Bootstrapped by the release-injected demo-vault-helper.
2026-07-20 02:24:23 -06:00
Michael Naumov
3e27a6af52 feat: add demo vault
Ship a curated demo-vault/ for Backlink Full Path, bootstrapped by the
release-injected obsidian-dev-utils demo-vault-helper. Three same-named Meeting
notes in different folders link to a shared note so the Backlinks pane shows each
one's full path; a Settings note documents every option. Add a static
registerDemoVaultCoverageSuite no-app test, the project dprint.json (excludes
demo-vault), and the README demo vault access section.
2026-07-20 02:23:55 -06:00
Michael Naumov
b2d243c06f feat: register the open demo vault command
Add OpenDemoVaultCommandHandler (87.0.3 pluginId/pluginVersion signature) so the
plugin exposes the "Open demo vault" command; assert it is registered in the
plugin test.
2026-07-20 02:23:48 -06:00
Michael Naumov
4f3aed400d chore: update obsidian-dev-utils to 87.1.0
Bump across the 86 -> 87 major with no source fallout; unlocks the S2 demo-vault
mechanism (release-injected helper, coverage suite, demo-vault-safe lint runner).
2026-07-20 02:17:37 -06:00
Michael Naumov
a5753c14c9 chore: update libs 2026-07-15 01:16:47 -06:00
Michael Naumov
4e902f316d chore: update libs 2026-07-15 00:46:00 -06:00
Michael Naumov
8bde799cea docs: update 2026-07-15 00:22:48 -06:00
Michael Naumov
f80fd3b489 docs: migrate to AGENTS.md 2026-07-14 15:14:19 -06:00
29 changed files with 471 additions and 347 deletions

1
AGENTS.md Normal file
View file

@ -0,0 +1 @@
# AGENTS.md

View file

@ -1,5 +1,26 @@
# CHANGELOG
## 1.6.11
- chore: update libs
## 1.6.10
- chore: update libs
- chore(demo-vault): drop committed Invocables placeholder
- fix(demo-vault): export invoke() from startup script; add Invocables folder
## 1.6.9
- docs: standardize demo-vault README
- docs: drop per-plugin demo-vault setup notes (bootstrap covered by ODU harness)
- docs: unnumber demo-vault setup notes
- Merge branch 'T107-renumber': number Backlink Full Path demo vault example notes (S2)
- Merge branch 'T107': create the Backlink Full Path demo vault (S2)
- chore: update libs
- docs: update
- docs: migrate to AGENTS.md
## 1.6.8
- chore: update libs

View file

@ -1,5 +0,0 @@
# CLAUDE.md
## Known Issues
None.

View file

@ -17,6 +17,14 @@ This plugin shows the full name helping to identify the backlinks better
![Full path](./images/full-path.png)
## Demo vault
A demo vault with usage examples ships with every release. You can access it via any of the following:
1. Running the **Backlink Full Path: Open demo vault** command.
2. Downloading `backlink-full-path.demo-vault.zip` from the [Releases](https://github.com/mnaoumov/obsidian-backlink-full-path/releases).
3. Browsing its source in [`demo-vault/`](./demo-vault/README.md) in this repository.
## Installation
The plugin is available in [the official Community Plugins repository](https://obsidian.md/plugins?id=backlink-full-path).
@ -39,7 +47,7 @@ To show them, run the following command:
window.DEBUG.enable('backlink-full-path');
```
For more details, refer to the [documentation](https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/debugging.md).
For more details, refer to the [documentation](https://mnaoumov.dev/obsidian-dev-utils/guides/debugging/).
## Support

View file

@ -9,6 +9,8 @@
"dictionaryDefinitions": [],
"dictionaries": [],
"words": [
"Invocables",
"unnumber",
"backlink",
"backlinks",
"dblclick",

13
demo-vault/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
# Churny / runtime-generated Obsidian state.
.obsidian/workspace.json
.obsidian/hotkeys.json
# Built plugins are release-injected by archivePluginDemoVault at release time —
# both the plugin under test AND the obsidian-dev-utils-owned Demo Vault Helper
# bootstrap plugin (which installs, configures, and enables CodeScript Toolkit at
# runtime). Nothing helper-related is committed; commit only the baked settings
# file for the plugin under test.
.obsidian/plugins/*
!.obsidian/plugins/backlink-full-path/
.obsidian/plugins/backlink-full-path/*
!.obsidian/plugins/backlink-full-path/data.json

View file

@ -0,0 +1,12 @@
{
// Scoped markdownlint config for the demo vault. The notes are an Obsidian
// vault, so two default rules are inherently incompatible and disabled here;
// every other rule still applies so the notes stay clean.
"config": {
// Notes intentionally open with a `[Docs](...)` link, not a heading.
"MD041": false,
// `[[wikilinks]]` are Obsidian's native link syntax; markdownlint parses
// them as undefined shortcut reference links.
"MD052": false
}
}

8
demo-vault/.obsidian/app.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"attachmentFolderPath": "_assets/attachments",
"newLinkFormat": "shortest",
"useMarkdownLinks": false,
"showUnsupportedFiles": true,
"defaultViewMode": "source",
"livePreview": true
}

View file

@ -0,0 +1,4 @@
[
"demo-vault-helper",
"backlink-full-path"
]

8
demo-vault/00 Start.md Normal file
View file

@ -0,0 +1,8 @@
Welcome to the [Backlink Full Path](https://github.com/mnaoumov/obsidian-backlink-full-path/) demo vault. Obsidian's core **Backlinks** pane shows only each linking note's file name - so several notes that share a name (three different `Meeting` notes, say) look identical. **Backlink Full Path** adds each note's folder path to that pane so you can tell them apart, with plenty of options for how the path is shown.
**How to see it:** open [[Shared topic]], then open the **Backlinks** pane (the link icon in the right sidebar, or the "Backlinks" view). Three notes all named `Meeting` link here - with the plugin enabled, each backlink shows its full folder path.
## Feature
- [[01 Backlink full path]]
- [[02 Settings]]

View file

@ -0,0 +1,18 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Backlink full path
Open [[Shared topic]] and look at its **Backlinks** pane. Three different notes link to it, and all three are named `Meeting`:
- [[Projects/Alpha/Meeting]]
- [[Projects/Beta/Meeting]]
- [[Notes/Meeting]]
Without this plugin, the Backlinks pane lists three identical `Meeting` entries. With it enabled, each one shows its folder path (`Projects/Alpha`, `Projects/Beta`, `Notes`) so you know which is which.
## Try it
1. Open [[Shared topic]].
2. Open the **Backlinks** pane (right sidebar link icon, or the command **Backlinks: Show backlinks**).
3. Notice each backlink now carries its full path.
4. Head to [[02 Settings]] and tweak how the path is rendered - depth, highlighting, extension, ordering, and more.

20
demo-vault/02 Settings.md Normal file
View file

@ -0,0 +1,20 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Settings
Open **Settings -> Community plugins -> Backlink Full Path** to configure the pane. Each option below lists the setting key stored in the plugin's `data.json`.
## Which path to show
- `pathDepth` - how many parent folders to include (0 shows the whole path).
- `rootPaths` - folders to treat as roots; paths under them are shown relative to the root.
- `shouldReversePathParts` - render the path from the file outwards instead of from the root inwards.
- `shouldShowEllipsisForSkippedPathParts` - show an ellipsis where parts were trimmed by `pathDepth` or a root.
## How it looks
- `shouldHighlightFileName` - visually emphasize the file name within the full path.
- `shouldIncludeExtension` - keep the `.md` (or other) extension in the shown name.
- `shouldDisplayParentPathOnSeparateLine` - put the folder path on its own line above the file name.
Change any of these and watch the Backlinks pane of [[Shared topic]] update live.

View file

@ -0,0 +1,7 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Meeting (general notes)
A general meeting note. Related to [[Shared topic]].
The third note named `Meeting`; the Backlinks pane shows its path as `Notes`.

View file

@ -0,0 +1,7 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Meeting (Project Alpha)
Notes from the Alpha project meeting. Related to [[Shared topic]].
This note is named `Meeting`, like two others in the vault - the Backlinks pane of [[Shared topic]] shows its full path, `Projects/Alpha`, to keep it distinct.

View file

@ -0,0 +1,7 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Meeting (Project Beta)
Notes from the Beta project meeting. Related to [[Shared topic]].
Also named `Meeting`; in the Backlinks pane of [[Shared topic]] it is shown as `Projects/Beta` so you can tell it apart from the others.

8
demo-vault/README.md Normal file
View file

@ -0,0 +1,8 @@
This is an [Obsidian](https://obsidian.md/) vault demonstrating features of the [Backlink Full Path](https://github.com/mnaoumov/obsidian-backlink-full-path) plugin.
## Opening this vault
- **If you already have the plugin installed**, run the **Backlink Full Path: Open demo vault** command — it downloads and opens the latest demo vault automatically.
- **Otherwise**, download `backlink-full-path.demo-vault.zip` from the [plugin releases](https://github.com/mnaoumov/obsidian-backlink-full-path/releases), unzip it, and in Obsidian choose `Manage vaults...``Open folder as vault` → select the unzipped folder.
On first open, Obsidian treats the vault as untrusted — choose **Trust author and enable plugins** (or enable Community plugins manually), then open [00 Start](<./00 Start.md>).

View file

@ -0,0 +1,5 @@
[Docs](https://github.com/mnaoumov/obsidian-backlink-full-path/)
# Shared topic
This is the note whose backlinks the demo inspects. Open the **Backlinks** pane and look at the three `Meeting` notes that link here - each one shows its full folder path thanks to [[01 Backlink full path]].

View file

@ -0,0 +1,17 @@
// Per-vault startup script, run by the universal Demo Vault Helper plugin (via CodeScript
// Toolkit's require) once CodeScript Toolkit is installed and enabled. This is where each
// plugin's demo vault does its own startup setup. Here it just opens the landing note.
import type { App } from 'obsidian';
const START_NOTE_PATH = '00 Start.md';
// Run by CodeScript Toolkit on load (its `startupScriptPath` setting, which the Demo Vault Helper
// points here). CST calls the exported `invoke` — a top-level script with no `invoke` export throws
// `this.startupScript.invoke is not a function`.
export async function invoke(app: App): Promise<void> {
const startNote = app.vault.getFileByPath(START_NOTE_PATH);
if (startNote) {
await app.workspace.getLeaf(false).openFile(startNote);
}
}

10
dprint.json Normal file
View file

@ -0,0 +1,10 @@
{
"extends": "./node_modules/obsidian-dev-utils/dist/templates/dprint.json",
"excludes": [
"dist",
"**/node_modules",
"**/*-lock.json",
"**/*.md",
"demo-vault"
]
}

View file

@ -6,6 +6,6 @@
"id": "backlink-full-path",
"isDesktopOnly": false,
"name": "Backlink Full Path",
"version": "1.6.8",
"version": "1.6.11",
"minAppVersion": "1.12.7"
}

572
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "backlink-full-path",
"version": "1.6.8",
"version": "1.6.11",
"description": "Shows the backlink's full path in the backlinks panel.",
"keywords": [],
"homepage": "https://github.com/mnaoumov/obsidian-backlink-full-path#readme",
@ -49,7 +49,7 @@
"@commitlint/cli": "^21.2.1",
"@commitlint/config-conventional": "^21.2.0",
"@commitlint/types": "^21.2.0",
"@obsidian-typings/obsidian-public-latest": "^6.22.0",
"@obsidian-typings/obsidian-public-latest": "^6.25.0",
"@total-typescript/ts-reset": "^0.6.1",
"@tsconfig/strictest": "^2.0.8",
"@types/node": "^26.1.1",
@ -62,8 +62,8 @@
"jsdom": "^29.1.1",
"nano-staged": "^1.0.2",
"obsidian": "^1.13.1",
"obsidian-dev-utils": "^85.1.0",
"obsidian-integration-testing": "^6.2.0",
"obsidian-dev-utils": "^87.3.0",
"obsidian-integration-testing": "^9.1.0",
"obsidian-test-mocks": "^3.6.0",
"sass-embedded": "^1.100.0",
"vitest": "^4.1.10"

View file

@ -60,7 +60,7 @@ export const config = defineConfig({
test: {
environment: 'node',
fileParallelism: false,
globalSetup: ['obsidian-integration-testing/vitest-global-setup'],
globalSetup: ['obsidian-integration-testing/vitest-global-setup-plugin'],
hookTimeout: BIG_TIMEOUT_IN_MILLISECONDS * HOOK_TIMEOUT_MULTIPLIER,
include: ['src/**/*.desktop.integration.test.ts'],
name: 'integration-tests:desktop',
@ -72,7 +72,7 @@ export const config = defineConfig({
test: {
environment: 'node',
fileParallelism: false,
globalSetup: ['obsidian-integration-testing/vitest-global-setup'],
globalSetup: ['obsidian-integration-testing/vitest-global-setup-plugin'],
hookTimeout: PERFORMANCE_TIMEOUT_IN_MILLISECONDS,
include: ['src/**/*.desktop-performance.integration.test.ts'],
name: 'integration-tests:desktop-performance',
@ -91,7 +91,7 @@ export const config = defineConfig({
}
},
fileParallelism: false,
globalSetup: ['obsidian-integration-testing/vitest-global-setup'],
globalSetup: ['obsidian-integration-testing/vitest-global-setup-plugin'],
hookTimeout: ANDROID_TIMEOUT_IN_MILLISECONDS * HOOK_TIMEOUT_MULTIPLIER,
include: ['src/**/*.android.integration.test.ts'],
name: 'integration-tests:android',

View file

@ -0,0 +1,21 @@
import process from 'node:process';
import { registerDemoVaultCoverageSuite } from 'obsidian-dev-utils/script-utils/demo-vault-coverage';
import { getRootFolder } from 'obsidian-dev-utils/script-utils/root';
// Keeps the in-repo `demo-vault/` in sync with the plugin's public surface WITHOUT
// Launching Obsidian: it reflects the real config from source and asserts every
// Setting is documented in a note, and that the guard note/member still exist
// (rename drift). Backlink Full Path enhances the core Backlinks pane and exposes
// No public API interface, so only the PluginSettings config class is reflected;
// The plugin's runtime behavior is covered by the other integration tests.
registerDemoVaultCoverageSuite({
configInterfaces: [{ interfaceName: 'PluginSettings', sourcePath: 'src/plugin-settings.ts' }],
interfaces: [],
nonTrivialGuard: {
expectDemoNote: '02 Settings.md',
expectMember: 'pathDepth',
interfaceName: 'PluginSettings',
sourcePath: 'src/plugin-settings.ts'
},
rootFolder: getRootFolder() ?? process.cwd()
});

View file

@ -1,4 +1,4 @@
import { getTempVault } from 'obsidian-integration-testing/vitest-global-setup';
import { getTempVault } from 'obsidian-integration-testing/vitest-global-setup-plugin';
import {
describe,
expect,

View file

@ -1,4 +1,4 @@
import { getTempVault } from 'obsidian-integration-testing/vitest-global-setup';
import { getTempVault } from 'obsidian-integration-testing/vitest-global-setup-plugin';
import {
describe,
expect,

View file

@ -120,5 +120,12 @@ describe('Plugin', () => {
const plugin = await createLoadedPlugin();
expect(castTo<SettingTabsHolder>(plugin).settingTabs__).toHaveLength(1);
});
it('should register the open demo vault command', async () => {
const plugin = new Plugin(app, manifest);
const addCommandSpy = vi.spyOn(plugin, 'addCommand');
await plugin.onload();
expect(addCommandSpy).toHaveBeenCalledWith(expect.objectContaining({ id: 'open-demo-vault' }));
});
});
/* eslint-enable @typescript-eslint/no-extraneous-class -- End of test file. */

View file

@ -1,3 +1,4 @@
import { OpenDemoVaultCommandHandler } from 'obsidian-dev-utils/obsidian/command-handlers/open-demo-vault-command-handler';
import { PluginSettingsTabComponent } from 'obsidian-dev-utils/obsidian/components/plugin-settings-tab-component';
import { PluginDataHandler } from 'obsidian-dev-utils/obsidian/data-handler';
import { PluginBase } from 'obsidian-dev-utils/obsidian/plugin/plugin';
@ -32,5 +33,14 @@ export class Plugin extends PluginBase {
pluginSettingsComponent
})
);
this.commandHandlerComponent.registerCommandHandlers([
new OpenDemoVaultCommandHandler({
app: this.app,
pluginId: this.manifest.id,
pluginNoticeComponent: this.pluginNoticeComponent,
pluginVersion: this.manifest.version
})
]);
}
}

View file

@ -37,5 +37,8 @@
"1.6.5": "1.12.7",
"1.6.6": "1.12.7",
"1.6.7": "1.12.7",
"1.6.8": "1.12.7"
"1.6.8": "1.12.7",
"1.6.9": "1.12.7",
"1.6.10": "1.12.7",
"1.6.11": "1.12.7"
}