├── README.md ├── README.png ├── data.json ├── main.js ├── manifest.json └── styles.css /README.md: -------------------------------------------------------------------------------- 1 | # symlinks-obsidian 2 | 3 | A plugin that refreshes symlinks in an obsidian vault, allowing them to be used. 4 | 5 | ## Installation 6 | 7 | Clone or copy the contents of this repo to the Obsidian plugins folder, found on the "Community Plugins" page: 8 | 9 | ![](./README.png) 10 | 11 | ``` 12 | cd {{ PLUGIN_FOLDER_PATH }} 13 | git clone https://github.com/chrisdmacrae/symlinks-obsidian.git 14 | ``` 15 | 16 | > Replace `{{ PLUGIN_FOLDER_PATH }}` with the full path to the plugins folder. 17 | 18 | Or head to the Obsidian third-party plugins section of the settings, browse "Community plugins", and install "Symlink Refresher". 19 | -------------------------------------------------------------------------------- /README.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisdmacrae/symlinks-obsidian/202942ff944607097f096a9c06896cb3a293b2cf/README.png -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const obsidian = require('obsidian'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | 7 | class SymlinkRefresher extends obsidian.Plugin { 8 | constructor() { 9 | super(...arguments); 10 | } 11 | 12 | excludedFileNames = [ 13 | ".git", 14 | ".obsidian" 15 | ] 16 | 17 | async onload() { 18 | console.log("Loading Obsidian Symlink Refresher Plugin"); 19 | 20 | this.registerInterval(setInterval(() => { 21 | this.run(); 22 | }, 30 * 1000)); 23 | 24 | setTimeout(() => { 25 | this.run(); 26 | }, 2.5 * 1000) 27 | } 28 | 29 | async run() { 30 | const fileNames = this.getFileNames(this.app.vault.adapter.basePath); 31 | 32 | return this.refreshSymlinks(fileNames, this.app.vault.adapter.basePath); 33 | } 34 | 35 | refreshSymlinks(filePaths, basePath) { 36 | const directories = []; 37 | 38 | for (const fileRelPath of filePaths) { 39 | const filePath = path.join(basePath, fileRelPath); 40 | const tmpPath = filePath.replace(fileRelPath, `~${fileRelPath}`); 41 | const stats = fs.lstatSync(filePath); 42 | 43 | if (!stats.isSymbolicLink(filePath) && stats.isDirectory(filePath)) { 44 | directories.push(filePath); 45 | 46 | continue; 47 | } 48 | 49 | try { 50 | fs.accessSync(filePath) 51 | 52 | const isSymlink = stats.isSymbolicLink(filePath); 53 | const exists = fs.existsSync(filePath); 54 | const hasTemp = fs.existsSync(tmpPath); 55 | 56 | if (!isSymlink) continue; 57 | 58 | console.log(`Refreshing ${filePath}`); 59 | 60 | if (exists && hasTemp) { 61 | fs.unlinkSync(tmpPath); 62 | } 63 | else if (exists && !hasTemp) { 64 | fs.renameSync(filePath, tmpPath); 65 | fs.renameSync(tmpPath, filePath); 66 | } 67 | else if (!exists && hasTemp) { 68 | fs.renameSync(tmpPath, filePath); 69 | } 70 | else if (!exists && !hasTemp) { 71 | throw new Error(`Uh oh! ${filePath} is missing!`); 72 | } 73 | } catch (error) { 74 | console.warn(error.message, { error }); 75 | 76 | continue; 77 | } 78 | } 79 | 80 | for (const directory of directories) { 81 | try { 82 | const directoryPath = path.resolve(basePath, directory); 83 | const fileNames = fs.readdirSync(directoryPath); 84 | 85 | this.refreshSymlinks(fileNames, directoryPath); 86 | } catch (error) { 87 | console.warn(error.message, { error }); 88 | 89 | continue; 90 | } 91 | } 92 | } 93 | 94 | getFileNames(directory) { 95 | return fs.readdirSync(directory).filter(fileName => !this.excludedFileNames.includes(fileName)); 96 | } 97 | } 98 | 99 | module.exports = SymlinkRefresher; -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "obsidian-symlink-refresher", 3 | "name": "Symlink Refresher", 4 | "version": "0.2.0", 5 | "description": "Refreshes symlinks periodically to ensure obisidan reads their contents", 6 | "isDesktopOnly": false, 7 | "js": "main.js", 8 | "css": "style.css" 9 | } -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisdmacrae/symlinks-obsidian/202942ff944607097f096a9c06896cb3a293b2cf/styles.css --------------------------------------------------------------------------------