diff --git a/package.json b/package.json
index f2c1483..dcbcd62 100644
--- a/package.json
+++ b/package.json
@@ -40,5 +40,8 @@
"tslib": "2.4.0",
"typescript": "5.8.3",
"typescript-eslint": "^8.29.1"
+ },
+ "dependencies": {
+ "minimatch": "^10.1.1"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2e07327..93b3546 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -7,6 +7,10 @@ settings:
importers:
.:
+ dependencies:
+ minimatch:
+ specifier: ^10.1.1
+ version: 10.1.1
devDependencies:
'@eslint/js':
specifier: ^9.24.0
@@ -287,6 +291,14 @@ packages:
resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
engines: {node: '>=18.18'}
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.0':
+ resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
+ engines: {node: 20 || >=22}
+
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
@@ -435,36 +447,43 @@ packages:
resolution: {integrity: sha512-FX2FV7vpLE/+Z0NZX9/1pwWud5Wocm/2PgpUXbT5aSV3QEB10kBPJAzssOQylvdj8mOHoKl5pVkXpbCwww/T2g==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-arm64-musl@1.5.0':
resolution: {integrity: sha512-+gF97xst1BZb28T3nwwzEtq2ewCoMDGKsenYsZuvpmNrW0019G1iUAunZN+FG55L21y+uP7zsGX06OXDQ/viKw==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@unrs/resolver-binding-linux-ppc64-gnu@1.5.0':
resolution: {integrity: sha512-5bEmVcQw9js8JYM2LkUBw5SeELSIxX+qKf9bFrfFINKAp4noZ//hUxLpbF7u/3gTBN1GsER6xOzIZlw/VTdXtA==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-riscv64-gnu@1.5.0':
resolution: {integrity: sha512-GGk/8TPUsf1Q99F+lzMdjE6sGL26uJCwQ9TlvBs8zR3cLQNw/MIumPN7zrs3GFGySjnwXc8gA6J3HKbejywmqA==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-s390x-gnu@1.5.0':
resolution: {integrity: sha512-5uRkFYYVNAeVaA4W/CwugjFN3iDOHCPqsBLCCOoJiMfFMMz4evBRsg+498OFa9w6VcTn2bD5aI+RRayaIgk2Sw==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-x64-gnu@1.5.0':
resolution: {integrity: sha512-j905CZH3nehYy6NimNqC2B14pxn4Ltd7guKMyPTzKehbFXTUgihQS/ZfHQTdojkMzbSwBOSgq1dOrY+IpgxDsA==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@unrs/resolver-binding-linux-x64-musl@1.5.0':
resolution: {integrity: sha512-dmLevQTuzQRwu5A+mvj54R5aye5I4PVKiWqGxg8tTaYP2k2oTs/3Mo8mgnhPk28VoYCi0fdFYpgzCd4AJndQvQ==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@unrs/resolver-binding-wasm32-wasi@1.5.0':
resolution: {integrity: sha512-LtJMhwu7avhoi+kKfAZOKN773RtzLBVVF90YJbB0wyMpUj9yQPeA+mteVUI9P70OG/opH47FeV5AWeaNWWgqJg==}
@@ -853,8 +872,8 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
- minimatch@10.0.1:
- resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==}
+ minimatch@10.1.1:
+ resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
minimatch@3.1.2:
@@ -1328,6 +1347,12 @@ snapshots:
'@humanwhocodes/retry@0.4.2': {}
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.0':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
+
'@jridgewell/gen-mapping@0.3.8':
dependencies:
'@jridgewell/set-array': 1.2.1
@@ -1685,7 +1710,7 @@ snapshots:
eslint-import-resolver-node: 0.3.9
get-tsconfig: 4.10.0
is-glob: 4.0.3
- minimatch: 10.0.1
+ minimatch: 10.1.1
semver: 7.7.1
stable-hash: 0.0.5
tslib: 2.8.1
@@ -1925,9 +1950,9 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
- minimatch@10.0.1:
+ minimatch@10.1.1:
dependencies:
- brace-expansion: 2.0.1
+ '@isaacs/brace-expansion': 5.0.0
minimatch@3.1.2:
dependencies:
diff --git a/src/components/Path.svelte b/src/components/Path.svelte
deleted file mode 100644
index 6face12..0000000
--- a/src/components/Path.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
diff --git a/src/components/SettingsPaths.svelte b/src/components/SettingsPaths.svelte
index 644a282..b6d9d25 100644
--- a/src/components/SettingsPaths.svelte
+++ b/src/components/SettingsPaths.svelte
@@ -1,10 +1,11 @@
+
+
+
+
diff --git a/src/components/path/SinglePath.svelte b/src/components/path/SinglePath.svelte
new file mode 100644
index 0000000..a320fe3
--- /dev/null
+++ b/src/components/path/SinglePath.svelte
@@ -0,0 +1,29 @@
+
+
+
+
+{#key type}
+
+{/key}
diff --git a/src/main.ts b/src/main.ts
index 41f5967..b399fe1 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -2,9 +2,10 @@ import type { WorkspaceLeaf } from 'obsidian'
import { type TFile } from 'obsidian'
import { FileView, Notice, Plugin, setIcon } from 'obsidian'
import type { Settings } from './settings'
-import { DEFAULT_SETTINGS, PrivacyMode, SettingsTab } from './settings'
+import { DEFAULT_SETTINGS, PrivacyMode, ProtectedPathType, SettingsTab } from './settings'
import { RequirePasswordModal } from './modals'
import { modifySearchLeaf } from './search'
+import { normalizePath, pathComparer } from './utils'
const STR_RIBBON_LOCKED = 'Vault is locked'
const STR_RIBBON_UNLOCKED = 'Vault is unlocked'
@@ -124,10 +125,9 @@ export default class SimplePassword extends Plugin {
}
isPathLocked(testPath: string): boolean {
- for (const _p of this.settings.protectedPaths) {
- const p = decodeURIComponent(new URL(_p, 'file://').pathname)
-
- if (('/' + testPath).startsWith(p)) {
+ testPath = normalizePath(testPath)
+ for (const pp of this.settings.protectedPaths) {
+ if (pathComparer[pp.type](pp.content, testPath)) {
return true
}
}
@@ -263,6 +263,27 @@ export default class SimplePassword extends Plugin {
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData())
+ await this.migrateSettings()
+ }
+
+ async migrateSettings() {
+ let changed = false
+ if (this.settings.protectedPaths.length != 0) {
+ this.settings.protectedPaths = this.settings.protectedPaths.map(v => {
+ if (typeof v == "string") {
+ changed = true
+ return {
+ type: ProtectedPathType.PREFIX,
+ content: v
+ }
+ }
+ return v
+ })
+ }
+
+ if (changed) {
+ await this.saveSettings()
+ }
}
async saveSettings() {
diff --git a/src/settings.ts b/src/settings.ts
index d87a147..a5cdbf3 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -12,19 +12,35 @@ export enum PrivacyMode {
NONE = ''
}
+export enum ProtectedPathType {
+ PREFIX = 'prefix',
+ EXACT = 'exact',
+ GLOB = 'glob',
+}
+
+export interface ProtectedPath {
+ type: ProtectedPathType
+ content: string
+}
+
export interface Settings {
autoLockMinutes: number
privacyMode: PrivacyMode
- protectedPaths: string[]
hint: string
password: string
blockGraph: boolean
+ protectedPaths: ProtectedPath[]
}
export const DEFAULT_SETTINGS: Settings = {
autoLockMinutes: 15,
privacyMode: PrivacyMode.BLUR,
- protectedPaths: ['/'],
+ protectedPaths: [
+ {
+ type: ProtectedPathType.PREFIX,
+ content: '/'
+ }
+ ],
hint: '',
password: '',
blockGraph: true
@@ -214,22 +230,3 @@ export class SettingsTab extends PluginSettingTab {
super.hide()
}
}
-
-export class PathSuggestions extends AbstractInputSuggest {
- protected getSuggestions(query: string): string[] {
- const p = new URL(query, 'file://').pathname
-
- return this.app.vault
- .getAllFolders(true)
- .filter((v) => {
- if (('/' + v.path).startsWith(p)) {
- return true
- }
- })
- .map((v) => v.path)
- }
-
- renderSuggestion(value: string, el: HTMLElement): void {
- el.setText(value)
- }
-}
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..bc9722d
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,18 @@
+import { minimatch } from "minimatch"
+import { ProtectedPathType } from "./settings"
+
+export function normalizePath(str: string) {
+ return decodeURIComponent(new URL(str, 'file://').pathname)
+}
+
+export const pathComparer: Record boolean> = {
+ [ProtectedPathType.PREFIX]: (content, realPath) => {
+ return realPath.startsWith(content)
+ },
+ [ProtectedPathType.EXACT]: (content, realPath) => {
+ return normalizePath(content) == normalizePath(realPath)
+ },
+ [ProtectedPathType.GLOB]: (content, realPath) => {
+ return minimatch(realPath, content)
+ }
+}