mirror of
https://github.com/idanlib/ObsidianFastForwardLinkPlugin.git
synced 2026-07-22 11:30:28 +00:00
Compare commits
27 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
309d6b95e1 | ||
|
|
aa1d2be2a3 | ||
|
|
410283d24c | ||
|
|
2660b8c365 | ||
|
|
e510be4afb | ||
|
|
91432db0ec | ||
|
|
e95bc5b1ba | ||
|
|
d65390304b | ||
|
|
789c1a830e | ||
|
|
198807bfbc | ||
|
|
4a297bc369 | ||
|
|
b1bc22c320 | ||
|
|
3eeee6f8fd | ||
|
|
6b00b25ad8 | ||
|
|
e5fe53026c | ||
|
|
8d11eb166c | ||
|
|
b8c84add70 | ||
|
|
6f34effaf5 | ||
|
|
3453fe0fa9 | ||
|
|
98e43c3002 | ||
|
|
dd4989d8cd | ||
|
|
cd09e45843 | ||
|
|
03f6af966f | ||
|
|
a07976b0f7 | ||
|
|
51e7c7ba35 | ||
|
|
677d5c5264 | ||
|
|
8c1632f513 |
8 changed files with 280 additions and 146 deletions
35
.github/workflows/release.yml
vendored
Normal file
35
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
name: Release Obsidian plugin
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "18.x"
|
||||||
|
|
||||||
|
- name: Build plugin
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
tag="${GITHUB_REF#refs/tags/}"
|
||||||
|
|
||||||
|
gh release create "$tag" \
|
||||||
|
--title="$tag" \
|
||||||
|
--draft \
|
||||||
|
main.js manifest.json styles.css
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Idan Liberman
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
119
README.md
119
README.md
|
|
@ -1,79 +1,128 @@
|
||||||
# FastForwardLink
|
# FastForwardLink
|
||||||
|
|
||||||
Fast-forward from multiple links to a single target note.
|
Obsidian lets you link notes. Great.
|
||||||
|
|
||||||
<img src="fastforwardlink.jpeg" alt="Girl in a jacket" width="400">
|
But real people don't always use the same terms consistently:
|
||||||
|
- abbreviations
|
||||||
|
- acronyms
|
||||||
|
- nicknames
|
||||||
|
- alternate spellings
|
||||||
|
- inside jokes
|
||||||
|
|
||||||
## Introduction
|
So you might write:
|
||||||
|
- `javascript`
|
||||||
|
- `js`
|
||||||
|
- `ecmascript`
|
||||||
|
|
||||||
FastForwardLink helps you write faster, keep your notes interconnected, and reduce navigation friction in your vault. This plugin allows you to set multiple links to open a single target note, effectively creating synonymous links. Use custom link abbreviations to type faster, establish conceptual connections between terms, navigate between notes quicker, and keep your vault organized.
|
...while meaning the exact same thing.
|
||||||
|
|
||||||
For example, when discussing photo editing software, `ps` is often shorthand for `photoshop`. Without FastForwardLink, the link `[[ps]]` would navigate to a note titled `ps`. But with FastForwardLink, the `[[ps]]` link forwards you directly to your target note `photoshop` (or any other specified note).
|
By default, Obsidian treats these as separate notes.
|
||||||
|
|
||||||
Here are some examples of how you might set up FastForwardLink:
|
Over time, that creates:
|
||||||
|
- duplicate notes
|
||||||
|
- fragmented knowledge base
|
||||||
|
- inconsistent linking
|
||||||
|
- friction while writing naturally
|
||||||
|
|
||||||
- `ps` > `photoshop`
|
FastForwardLink solves this by turning alias notes into lightweight redirects.
|
||||||
- `js` > `javascript`
|
|
||||||
- `tay tay` > `taylor swift`
|
|
||||||
- `46` > `joe biden`
|
|
||||||
- `e=mc2` > `Einstein's special theory of relativity`
|
|
||||||
- `favorite film` > `bill and ted's bogus journey`
|
|
||||||
|
|
||||||
> Press `Ctrl + Alt + R` to quickly create a forwarding link.
|
Write naturally. Land on the right note — fast.
|
||||||
|
|
||||||
### FastForwardLink Plugin Demo
|
<img src="fastforwardlink.jpeg" alt="FastForwardLink mascot" width="400">
|
||||||
|
|
||||||
|
## FastForwardLink Plugin Demo
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
FastForwardLink lets multiple note names point to the same canonical note. Write naturally without fragmenting your vault structure:
|
||||||
|
|
||||||
|
- `js` → `javascript`
|
||||||
|
- `ps` → `photoshop`
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
Suppose you have a note called `javascript`.
|
||||||
|
|
||||||
|
Elsewhere in your vault, you naturally write:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[[js]]
|
||||||
|
```
|
||||||
|
Normally, Obsidian would create a brand-new js note. But with FastForwardLink:
|
||||||
|
- Create a note called `js`
|
||||||
|
- Add redirect syntax inside it
|
||||||
|
- Opening `js` automatically forwards to `javascript`
|
||||||
|
|
||||||
|
Here are some examples of how you might set up FastForwardLink:
|
||||||
|
|
||||||
|
- `ps` > `photoshop`
|
||||||
|
- `js` > `javascript`
|
||||||
|
- `tay tay` > `taylor swift`
|
||||||
|
- `e=mc2` > `Einstein's special theory of relativity`
|
||||||
|
- `favorite film` > `bill and ted's bogus journey`
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Multiple Links, One Target**: Set multiple links to redirect to a single target note for quick navigation between related topics or abbreviations. Organize synonyms or alternate spellings for easier access.
|
- **Multiple Links, One Target**: Set multiple links to redirect to a single target note for quick navigation between related topics or abbreviations. Organize synonyms or alternate spellings for easier access.
|
||||||
|
|
||||||
- **Quick Keyboard Shortcut**: Press `Ctrl + Alt + R` to quickly create a forwarding link. Set target notes on the fly without breaking your writing flow.
|
- **Quick-Paste Command**: Set target notes on the fly without breaking your writing flow. In the Obsidian command palette, select **Paste redirect syntax onto selection** to quickly create a forwarding link.
|
||||||
|
|
||||||
- **Organized Vault**: Streamline vault navigation by unifying concepts, perfect for efficient, clutter-free notes.
|
- **Organized Vault**: Streamline vault navigation by unifying concepts, perfect for efficient, clutter-free notes.
|
||||||
|
|
||||||
- **Easy Management**: Forwarding notes are automatically moved to a designated folder for easy review, management, or removal.
|
- **Easy Management**: Forwarding notes are automatically moved to a designated folder for easy review, management, or removal.
|
||||||
|
|
||||||
- **Flexible Forwarding Options**:
|
- **Flexible Forwarding Options**:
|
||||||
|
- Open the target note in the same tab.
|
||||||
|
- Open the target note in a new tab while remaining on the original note.
|
||||||
|
- Open the target note in a new tab and switch to it automatically.
|
||||||
|
|
||||||
- Open the target note in the same tab.
|
- **Remove Forwarding Notes in One Click**: Easily delete all redirecting notes with a single click using plugin settings.
|
||||||
- Open the target note in a new tab while remaining on the original note.
|
|
||||||
- Open the target note in a new tab and switch to it automatically.
|
|
||||||
|
|
||||||
- **Remove Forwarding Notes in One Click**: Easily delete all redirecting notes with a single click using plugin settings.
|
## Installation
|
||||||
|
|
||||||
## Installation and Use
|
Download the plugin directly from Obsidian's community plugins. Just search for FastForwardLink.
|
||||||
|
|
||||||
### Installing FastForwardLink
|
You can also install manually by doing the following:
|
||||||
|
|
||||||
To manually install FastForwardLink:
|
|
||||||
|
|
||||||
1. [Download the following plugin files](https://github.com/IdanLib/ObsidianFastForwardLinkPlugin):
|
1. [Download the following plugin files](https://github.com/IdanLib/ObsidianFastForwardLinkPlugin):
|
||||||
|
|
||||||
- `data.json`
|
- `data.json`
|
||||||
- `main.js`
|
- `main.js`
|
||||||
- `manifest.json`
|
- `manifest.json`
|
||||||
|
|
||||||
2. Copy these file to your vault's plugins folder at `{VaultFolder}/.obsidian/plugins/FastForwardLink`.
|
2. Copy these files to your vault's plugins folder at `{VaultFolder}/.obsidian/plugins/FastForwardLink`.
|
||||||
3. In Obsidian, go to **Settings** > **Community Plugins** and enable **FastForwardLink**.
|
3. In Obsidian, go to **Settings** > **Community Plugins** and enable **FastForwardLink**.
|
||||||
|
|
||||||
The plugin is now ready for use.
|
The plugin is now ready for use.
|
||||||
|
|
||||||
### Setting Up a Fast-Forward Link
|
## Create a Fast-Forward Link
|
||||||
|
|
||||||
To set up a fast-forwarding link:
|
To create a fast-forwarding link:
|
||||||
|
|
||||||
1. Create or open the note you want to fast-forward to a target note. For example, a note titled `ps`.
|
1. Create or open the note you want to fast-forward to a target note. For example, a note titled `ps`.
|
||||||
2. In the note, type the target note's title wrapped in the forwarding syntax: `::>[[target-note]]`. For example, to forward from `ps` to `photoshop`, include `::>[[photoshop]]` in the `ps` note.
|
2. In the note, type the target note's title wrapped in the forwarding syntax: `::>[[target-note]]`. For example, to forward from `ps` to `photoshop`, include `::>[[photoshop]]` in the `ps` note.
|
||||||
|
|
||||||
Clicking the `ps` link in any note now opens the `photoshop` note.
|
Clicking the `ps` link in any note now opens the `photoshop` note.
|
||||||
|
|
||||||
### Keyboard Shortcut
|
## Quick-Paste Syntax
|
||||||
|
|
||||||
Yup, typing sucks. Fortunately, there's a keyboard shortcut to make it easier to create a forwarding note.
|
Yup, typing sucks. Fortunately, there's a command to help you quickly paste the redirect syntax into your code:
|
||||||
|
|
||||||
Press `Ctrl + Alt + R` (PC) or `Cmd + Opt + R` (macOS) to wrap selected text in the fast-forward syntax.
|
1. Press `Ctrl + P` to open the Obsidian command palette.
|
||||||
|
2. Search for and select the command **Paste Redirect Syntax onto Selection**.
|
||||||
|
|
||||||
|
The command wraps the selected text in the fast-forward syntax.
|
||||||
|
|
||||||
|
> [!TIP] > [Add a hotkey](https://help.obsidian.md/User+interface/Hotkeys#Setting+hotkeys) to trigger this command! We recommend `Ctrl + Alt + R` (PC) or `Cmd + Opt + R` (macOS).
|
||||||
|
|
||||||
|
## Version Updates
|
||||||
|
|
||||||
|
### Version 1.1
|
||||||
|
|
||||||
|
Some improvements include:
|
||||||
|
|
||||||
|
- You can now temporarily bypass forwarding with a designated command. In Obsidian's command palette, search for "FastForwardLink".
|
||||||
|
- Source code refactored and better organized for future contributors.
|
||||||
|
- Better robust event and error handling and messaging.
|
||||||
|
|
||||||
## Bugs and Contact
|
## Bugs and Contact
|
||||||
|
|
||||||
|
|
@ -83,7 +132,7 @@ Please open an issue in the [plugin's GitHub repository](https://github.com/Idan
|
||||||
|
|
||||||
### Known Bugs
|
### Known Bugs
|
||||||
|
|
||||||
- When "Open the target note in a new tab" is enabled and the fast-forwarding note has not yet been moved to the `_forwards_` folder, some additional tabs are opened. This is likely due to internal timing issues in the Obsidian-OS interaction.
|
- When "Open the target note in a new tab" is enabled and the fast-forwarding note has not yet been moved to the `_forwards_` folder, some additional tabs are opened. This is likely due to internal timing issues in the Obsidian-OS interaction.
|
||||||
|
|
||||||
When the fast-forwarding note is in the `_forwards` folder, plugin behavior is as expected.
|
When the fast-forwarding note is in the `_forwards` folder, plugin behavior is as expected.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export default class RedirectSettingsTab extends PluginSettingTab {
|
||||||
});
|
});
|
||||||
|
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName("Delete the _forwards Folder")
|
.setName("Delete the _forwards folder")
|
||||||
.setDesc(
|
.setDesc(
|
||||||
"Before uninstalling the plugin, manually delete the `_forwards` folder to remove unnecessary files. This cannot be undone."
|
"Before uninstalling the plugin, manually delete the `_forwards` folder to remove unnecessary files. This cannot be undone."
|
||||||
)
|
)
|
||||||
|
|
@ -49,7 +49,7 @@ export default class RedirectSettingsTab extends PluginSettingTab {
|
||||||
button.setButtonText("Delete");
|
button.setButtonText("Delete");
|
||||||
button.setTooltip("Delete the _forwards folder.");
|
button.setTooltip("Delete the _forwards folder.");
|
||||||
button.setWarning();
|
button.setWarning();
|
||||||
button.onClick((evt) => {
|
button.onClick(async (evt) => {
|
||||||
const forwardsFolder =
|
const forwardsFolder =
|
||||||
this.app.vault.getFolderByPath("_forwards");
|
this.app.vault.getFolderByPath("_forwards");
|
||||||
if (!forwardsFolder) {
|
if (!forwardsFolder) {
|
||||||
|
|
@ -61,7 +61,7 @@ export default class RedirectSettingsTab extends PluginSettingTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.app.vault.delete(forwardsFolder, true);
|
await this.app.fileManager.trashFile(forwardsFolder);
|
||||||
new Notice(
|
new Notice(
|
||||||
"_forwards folder deleted successfully.",
|
"_forwards folder deleted successfully.",
|
||||||
2000
|
2000
|
||||||
|
|
|
||||||
236
main.ts
236
main.ts
|
|
@ -1,6 +1,7 @@
|
||||||
import { getLinkpath, Plugin, Notice, TFolder, TFile } from "obsidian";
|
import { getLinkpath, Plugin, Notice, TFolder, TFile } from "obsidian";
|
||||||
import RedirectSettingsTab from "components/Settings";
|
import RedirectSettingsTab from "components/Settings";
|
||||||
|
|
||||||
|
// --- Setup ---
|
||||||
interface RedirectSettings {
|
interface RedirectSettings {
|
||||||
openInNewTab: boolean;
|
openInNewTab: boolean;
|
||||||
switchToNewTab: boolean;
|
switchToNewTab: boolean;
|
||||||
|
|
@ -11,10 +12,64 @@ const DEFAULT_SETTINGS: RedirectSettings = {
|
||||||
switchToNewTab: false,
|
switchToNewTab: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Main Plugin Class ---
|
||||||
export default class RedirectPlugin extends Plugin {
|
export default class RedirectPlugin extends Plugin {
|
||||||
|
// --- Properties ---
|
||||||
settings: RedirectSettings;
|
settings: RedirectSettings;
|
||||||
redirectsFolder: TFolder | null;
|
redirectsFolder: TFolder | null = null;
|
||||||
redirectRef = async (file: TFile) => {
|
isMovingNote = false;
|
||||||
|
isBypassRedirect = false;
|
||||||
|
|
||||||
|
// --- Lifecycle methods and commands---
|
||||||
|
async onload() {
|
||||||
|
await this.loadSettings();
|
||||||
|
|
||||||
|
this.addSettingTab(new RedirectSettingsTab(this.app, this));
|
||||||
|
|
||||||
|
this.app.workspace.onLayoutReady(async () => {
|
||||||
|
await this.createRedirectsFolder();
|
||||||
|
await this.redirect();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.app.workspace.on("file-open", this.handleFileOpen);
|
||||||
|
|
||||||
|
this.addCommand({
|
||||||
|
id: "paste-redirect-syntax",
|
||||||
|
name: "Paste redirect syntax onto selection",
|
||||||
|
editorCallback: (editor, view) => {
|
||||||
|
const selection = editor.getSelection();
|
||||||
|
editor.replaceSelection(`::>[[${selection}]]`);
|
||||||
|
const { ch, line } = editor.getCursor();
|
||||||
|
if (!selection) {
|
||||||
|
editor.setCursor({
|
||||||
|
ch: ch - 2,
|
||||||
|
line: line,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addCommand({
|
||||||
|
id: "bypass-forwarding",
|
||||||
|
name: "Bypass forwarding to target note",
|
||||||
|
callback: () => {
|
||||||
|
this.isBypassRedirect = true;
|
||||||
|
new Notice("Bypassing redirects.");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onunload() {
|
||||||
|
this.app.workspace.off("file-open", this.handleFileOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Event Handlers ---
|
||||||
|
handleFileOpen = async (file: TFile) => {
|
||||||
|
if (this.isMovingNote) return;
|
||||||
|
if (this.isBypassRedirect) {
|
||||||
|
this.isBypassRedirect = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
await this.redirect();
|
await this.redirect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -24,51 +79,96 @@ export default class RedirectPlugin extends Plugin {
|
||||||
await this.saveSettings();
|
await this.saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createRedirectsFolder() {
|
// --- Core Logic ---
|
||||||
const currentRedirectsFolder =
|
private async redirect(): Promise<void> {
|
||||||
this.app.vault.getAbstractFileByPath("_forwards");
|
const fileAndContent = await this.getCurrentFile();
|
||||||
|
if (!fileAndContent) return;
|
||||||
|
|
||||||
try {
|
const { currentFile, content } = fileAndContent;
|
||||||
this.redirectsFolder = await this.app.vault.createFolder(
|
const targetNoteFile = this.getTargetFile(content);
|
||||||
"/_forwards"
|
if (!targetNoteFile) return;
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.redirectsFolder = currentRedirectsFolder as TFolder;
|
await this.moveRedirectNote(currentFile);
|
||||||
|
await this.openTargetNote(targetNoteFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async redirect() {
|
// --- Helper functions ---
|
||||||
const currentFile = this.app.workspace.getActiveFile();
|
|
||||||
|
|
||||||
if (!currentFile) {
|
private async moveRedirectNote(
|
||||||
|
redirectingNote: TFile | null
|
||||||
|
): Promise<TFile | void> {
|
||||||
|
if (
|
||||||
|
!redirectingNote ||
|
||||||
|
redirectingNote.path === `_forwards/${redirectingNote.name}`
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentFileContent = (await this.getCurrentFileContent(
|
new Notice(
|
||||||
currentFile
|
`Moving ${redirectingNote.name} to the _forwards folder.`,
|
||||||
)) as string;
|
2000
|
||||||
|
);
|
||||||
|
|
||||||
const targetNoteFile = this.getTargetFile(currentFileContent);
|
if (!this.redirectsFolder) {
|
||||||
|
await this.createRedirectsFolder();
|
||||||
if (!targetNoteFile) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.isMovingNote = true;
|
||||||
|
const redirectingNoteInFolder = await this.app.vault.copy(
|
||||||
|
redirectingNote,
|
||||||
|
`/_forwards/${redirectingNote.name}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.settings.openInNewTab) {
|
||||||
|
await this.openTargetNote(redirectingNoteInFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay deletion to avoid race condition where the original note is deleted before the new note is fully opened in the UI.
|
||||||
|
setTimeout(async () => {
|
||||||
|
await this.deleteNote(redirectingNote);
|
||||||
|
this.isMovingNote = false;
|
||||||
|
}, 500);
|
||||||
|
} catch (error) {
|
||||||
|
this.isMovingNote = false;
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async openTargetNote(targetNoteFile: TFile) {
|
||||||
await this.app.workspace.openLinkText(
|
await this.app.workspace.openLinkText(
|
||||||
targetNoteFile.name,
|
targetNoteFile.name,
|
||||||
targetNoteFile.path,
|
targetNoteFile.path,
|
||||||
this.settings.openInNewTab,
|
this.settings.openInNewTab,
|
||||||
{ active: this.settings.switchToNewTab }
|
{ active: this.settings.switchToNewTab }
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentFile.path === `_forwards/${currentFile.name}`) {
|
private async createRedirectsFolder() {
|
||||||
new Notice(`${currentFile.name} is in the _forwards folder.`, 2000);
|
try {
|
||||||
return;
|
this.redirectsFolder = await this.app.vault.createFolder(
|
||||||
|
"/_forwards"
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(
|
||||||
|
"`_forwards` folder not created or already exists.",
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await this.moveRedirectNote(currentFile);
|
private async getCurrentFile(): Promise<{
|
||||||
|
currentFile: TFile;
|
||||||
|
content: string;
|
||||||
|
} | null> {
|
||||||
|
const currentFile = this.app.workspace.getActiveFile();
|
||||||
|
if (!currentFile) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
currentFile: currentFile,
|
||||||
|
content: (await this.getCurrentFileContent(currentFile)) || "",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getCurrentFileContent(
|
private async getCurrentFileContent(
|
||||||
|
|
@ -78,15 +178,13 @@ export default class RedirectPlugin extends Plugin {
|
||||||
return await this.app.vault.read(currentFile);
|
return await this.app.vault.read(currentFile);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
new Notice(`Cannot read ${currentFile}.`);
|
new Notice(`Cannot read ${currentFile}.`);
|
||||||
console.error(
|
console.error(`Failed to read ${currentFile} content: `, error);
|
||||||
console.error(`Failed to read ${currentFile} content: `, error)
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTargetFile(currentFileContent: string): TFile | null {
|
private getTargetFile(currentFileContent: string): TFile | null {
|
||||||
const linkTextRegex = /::>\[\[(.*[\w\s]*)\]\]/i;
|
const linkTextRegex = /::>\[\[(.*?)\]\]/i;
|
||||||
const targetNoteName = currentFileContent.match(linkTextRegex)?.at(1);
|
const targetNoteName = currentFileContent.match(linkTextRegex)?.at(1);
|
||||||
|
|
||||||
if (!targetNoteName) {
|
if (!targetNoteName) {
|
||||||
|
|
@ -111,48 +209,9 @@ export default class RedirectPlugin extends Plugin {
|
||||||
return targetNoteFile;
|
return targetNoteFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async moveRedirectNote(
|
|
||||||
redirectingNote: TFile | null
|
|
||||||
): Promise<TFile | void> {
|
|
||||||
let redirectingNoteInFolder = null;
|
|
||||||
|
|
||||||
if (!redirectingNote) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.redirectsFolder) {
|
|
||||||
await this.createRedirectsFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
redirectingNoteInFolder = await this.app.vault.copy(
|
|
||||||
redirectingNote,
|
|
||||||
`/_forwards/${redirectingNote.name}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.settings.openInNewTab) {
|
|
||||||
// Turn off event handler to avoid opening the target note twice
|
|
||||||
this.app.workspace.off("file-open", this.redirectRef);
|
|
||||||
|
|
||||||
await this.app.workspace
|
|
||||||
.getLeaf(this.settings.openInNewTab)
|
|
||||||
.openFile(redirectingNoteInFolder, {
|
|
||||||
active: this.settings.switchToNewTab,
|
|
||||||
});
|
|
||||||
this.app.workspace.getLeaf().detach();
|
|
||||||
|
|
||||||
this.app.workspace.on("file-open", this.redirectRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.deleteNote(redirectingNote);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async deleteNote(orgRedirectingNote: TFile): Promise<void> {
|
private async deleteNote(orgRedirectingNote: TFile): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.app.vault.delete(orgRedirectingNote);
|
await this.app.fileManager.trashFile(orgRedirectingNote);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
new Notice(
|
new Notice(
|
||||||
"Failed to delete directing note from original location. Please delete manually.",
|
"Failed to delete directing note from original location. Please delete manually.",
|
||||||
|
|
@ -162,40 +221,7 @@ export default class RedirectPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onload() {
|
// --- Settings Persistence ---
|
||||||
await this.loadSettings();
|
|
||||||
|
|
||||||
this.addSettingTab(new RedirectSettingsTab(this.app, this));
|
|
||||||
|
|
||||||
this.app.workspace.onLayoutReady(async () => {
|
|
||||||
await this.createRedirectsFolder();
|
|
||||||
await this.redirect();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.app.workspace.on("file-open", this.redirectRef);
|
|
||||||
|
|
||||||
this.addCommand({
|
|
||||||
id: "paste-redirect-syntax",
|
|
||||||
name: "Paste Redirect Syntax onto Selection",
|
|
||||||
hotkeys: [{ key: "r", modifiers: ["Ctrl", "Alt"] }],
|
|
||||||
editorCallback: (editor, view) => {
|
|
||||||
const selection = editor.getSelection();
|
|
||||||
editor.replaceSelection(`::>[[${selection}]]`);
|
|
||||||
const { ch, line } = editor.getCursor();
|
|
||||||
if (!selection) {
|
|
||||||
editor.setCursor({
|
|
||||||
ch: ch - 2,
|
|
||||||
line: line,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onunload() {
|
|
||||||
this.app.workspace.off("file-open", this.redirectRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
try {
|
try {
|
||||||
this.settings = Object.assign(
|
this.settings = Object.assign(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "fast-forward-link",
|
"id": "fast-forward-link",
|
||||||
"name": "FastForwardLink",
|
"name": "FastForwardLink",
|
||||||
"version": "1.0.0",
|
"version": "1.1.2",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "Fast-forward multiple links to a single target note. Create custom link shorthands (like `ps` > `photoshop`) to create synonyms, streamline navigation, and keep your vault organized.",
|
"description": "Fast-forward multiple links to a single target note. Create custom link shorthands (like `ps` > `photoshop`) to create synonyms, streamline navigation, and keep your vault organized.",
|
||||||
"author": "Idan Liberman",
|
"author": "Idan Liberman",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "fast-forward-link",
|
"name": "fast-forward-link",
|
||||||
"version": "1.0.0",
|
"version": "1.1.2",
|
||||||
"description": "Forward multiple links to a single note with ease.",
|
"description": "Forward multiple links to a single note with ease.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
{
|
{
|
||||||
"1.0.0": "0.15.0"
|
"1.0.0": "0.15.0",
|
||||||
|
"1.1.0": "0.15.0",
|
||||||
|
"1.1.1": "0.15.0",
|
||||||
|
"1.1.2": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue