mirror of
https://github.com/al0cam/AutoMover.git
synced 2026-07-22 12:10:26 +00:00
feat: project rules implemented, readme remaining
This commit is contained in:
parent
7135c5181e
commit
3927556663
9 changed files with 76 additions and 71 deletions
|
|
@ -55,6 +55,10 @@ Other examples could include:
|
|||
2. 00:00:05 -> triggers every five seconds
|
||||
3. 72:30:00 -> triggers every 3 days and 30 minutes (if your Device is online and obsidian runnning for that long)
|
||||
|
||||
### Project Rules UI
|
||||
From patch 1.0.7 onwards, you can use project rules to group moving rules together.
|
||||
And to move files based on the project they belong to.
|
||||
Project rules take precedence over the normal moving rules considering they are way more specific.
|
||||
|
||||
### Tag rules UI
|
||||
From patch 1.0.6 onwards, you can move files using tags.
|
||||
|
|
@ -210,5 +214,5 @@ Thank you!
|
|||
- [x] Add Project moving rules
|
||||
- [x] Project name and destination path
|
||||
- [x] Subfield that contain the moving rules for the project
|
||||
- [ ] Add project rules UI
|
||||
- [ ] Project rules business logic
|
||||
- [x] Add project rules UI
|
||||
- [x] Project rules business logic
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export function projectSection(containerEl: HTMLElement, plugin: AutoMoverPlugin
|
|||
value: rule.folder,
|
||||
cls: "rule_input",
|
||||
}).onchange = (e) => {
|
||||
project.folder = (e.target as HTMLInputElement).value;
|
||||
rule.folder = (e.target as HTMLInputElement).value;
|
||||
project.rules.map((r) => (r === rule ? rule : r));
|
||||
plugin.saveData(plugin.settings);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { ProjectRule } from "Models/ProjectRule";
|
||||
import type { TFile } from "obsidian";
|
||||
import propertyUtil from "./PropertyUtil";
|
||||
|
||||
class ProjectMatcherUtil {
|
||||
private static instance: ProjectMatcherUtil;
|
||||
|
|
@ -17,29 +15,34 @@ class ProjectMatcherUtil {
|
|||
/**
|
||||
* Returns the first project rule that matches the file
|
||||
* If no rule matches, returns null
|
||||
* @param file
|
||||
* @param projectName
|
||||
* @param projectRules
|
||||
* @returns ProjectRule | null
|
||||
*/
|
||||
public getMatchingProjectRule(file: TFile, projectRules: ProjectRule[]): ProjectRule | null {
|
||||
propertyUtil.getPropertiesFromFile(file);
|
||||
for (const rule of projectRules) {
|
||||
if (rule.projectName == null || rule.projectName === "") {
|
||||
console.error("Project Rule does not have a project name: ", rule);
|
||||
continue;
|
||||
}
|
||||
if (rule.folder == null || rule.folder === "") {
|
||||
console.error("Project Rule does not have a destination folder: ", rule);
|
||||
continue;
|
||||
}
|
||||
// Check if the file path contains the project name as a wiki link or plain text
|
||||
const wikiLink = `[[${rule.projectName}]]`;
|
||||
if (file.path.includes(wikiLink) || file.path.includes(rule.projectName)) {
|
||||
return rule;
|
||||
public getMatchingProjectRule(projectName: string, projectRules: ProjectRule[]): ProjectRule | null {
|
||||
for (const projectRule of projectRules) {
|
||||
if (projectRule.projectName === projectName) {
|
||||
return projectRule;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends the project folder to the destination path
|
||||
* and checks whether the project folder ends with a slash
|
||||
*
|
||||
* @param projectRule
|
||||
* @param subPath
|
||||
* @returns string
|
||||
*/
|
||||
public constructProjectDestinationPath(projectRule: ProjectRule, subPath: string): string {
|
||||
let projectFolder = projectRule.folder;
|
||||
if (!projectFolder.endsWith("/")) {
|
||||
projectFolder += "/";
|
||||
}
|
||||
return projectFolder + subPath;
|
||||
}
|
||||
}
|
||||
const exclusionMatcherUtil = ProjectMatcherUtil.getInstance();
|
||||
export default exclusionMatcherUtil;
|
||||
const projectMatcherUtil = ProjectMatcherUtil.getInstance();
|
||||
export default projectMatcherUtil;
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
import { TFile } from "obsidian";
|
||||
|
||||
class PropertyUtil {
|
||||
private static instance: PropertyUtil;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
static getInstance(): PropertyUtil {
|
||||
if (!PropertyUtil.instance) {
|
||||
PropertyUtil.instance = new PropertyUtil();
|
||||
}
|
||||
return PropertyUtil.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Add property support
|
||||
*
|
||||
* overview.md
|
||||
* Page Properties:
|
||||
* Project: [[Project A]]
|
||||
* File Type: asset
|
||||
*
|
||||
* It would take those Project Property and File Type Properties, moving it to Project A/assets.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Theoretically, projects should then take precedence over tags and names, as they are more specific.
|
||||
*
|
||||
*
|
||||
* The way i see the implementation is adding a new model that will contain the project destination
|
||||
* and then specify in subdirectories where each matching file goes.
|
||||
* And it has to check if the file contains the property from the project such as it was mentioned in the overview.md example.
|
||||
*
|
||||
*/
|
||||
|
||||
public getPropertiesFromFile(file: TFile): Record<string, string> {
|
||||
console.log("Extracted properties: ", properties);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
const propertyUtil = PropertyUtil.getInstance();
|
||||
export default propertyUtil;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import type { MovingRule } from "Models/MovingRule";
|
||||
import { ProjectRule } from "Models/ProjectRule";
|
||||
import type { TagCache, TFile } from "obsidian";
|
||||
|
||||
class RuleMatcherUtil {
|
||||
|
|
|
|||
44
main.ts
44
main.ts
|
|
@ -6,6 +6,7 @@ import movingUtil from "Utils/MovingUtil";
|
|||
import ruleMatcherUtil from "Utils/RuleMatcherUtil";
|
||||
import timerUtil from "Utils/TimerUtil";
|
||||
import * as obsidian from "obsidian";
|
||||
import projectMatcherUtil from "Utils/ProjectMatcherUtil";
|
||||
|
||||
export default class AutoMoverPlugin extends obsidian.Plugin {
|
||||
settings: Settings.AutoMoverSettings;
|
||||
|
|
@ -103,8 +104,9 @@ export default class AutoMoverPlugin extends obsidian.Plugin {
|
|||
* @returns void
|
||||
*/
|
||||
matchAndMoveFile(file: obsidian.TFile): void {
|
||||
// console.log("Moving file: ", file.path);
|
||||
if (this.matchAndMoveByName(file)) return;
|
||||
console.log("Moving file: ", file.path);
|
||||
if (this.matchAndMoveByProject(file)) return;
|
||||
else if (this.matchAndMoveByName(file)) return;
|
||||
else this.matchAndMoveByTag(file);
|
||||
}
|
||||
|
||||
|
|
@ -152,6 +154,44 @@ export default class AutoMoverPlugin extends obsidian.Plugin {
|
|||
return true;
|
||||
}
|
||||
|
||||
matchAndMoveByProject(file: obsidian.TFile): boolean {
|
||||
const cache = this.app.metadataCache.getFileCache(file);
|
||||
if (cache == null) return false;
|
||||
if (cache.frontmatter == null) return false;
|
||||
if (cache.frontmatter.Project == null && cache.frontmatter.project == null) return false;
|
||||
console.log("Frontmatter found: ", cache.frontmatter);
|
||||
|
||||
const projectName: string = cache.frontmatter.Project || cache.frontmatter.project;
|
||||
console.log("Project name found: ", projectName);
|
||||
|
||||
const projectRule = projectMatcherUtil.getMatchingProjectRule(projectName, this.settings.projectRules);
|
||||
if (projectRule == null || projectRule.folder == null) return false;
|
||||
if (projectRule.rules == null || projectRule.rules.length === 0) return false;
|
||||
|
||||
console.log("Project rule found: ", projectRule);
|
||||
|
||||
const rule = ruleMatcherUtil.getMatchingRuleByName(file, projectRule.rules);
|
||||
if (rule == null || rule.folder == null) return false;
|
||||
|
||||
console.log("Project rule's moving rule found: ", rule);
|
||||
|
||||
if (ruleMatcherUtil.isRegexGrouped(rule)) {
|
||||
const matches = ruleMatcherUtil.getGroupMatches(file, rule);
|
||||
const ruleDesinationPath = ruleMatcherUtil.constructFinalDesinationPath(rule, matches!);
|
||||
const finalDestinationPath = projectMatcherUtil.constructProjectDestinationPath(projectRule, ruleDesinationPath);
|
||||
|
||||
console.log("Final destination path: ", finalDestinationPath);
|
||||
|
||||
movingUtil.moveFile(file, finalDestinationPath);
|
||||
} else {
|
||||
const finalDestinationPath = projectMatcherUtil.constructProjectDestinationPath(projectRule, rule.folder);
|
||||
|
||||
console.log("Final destination path: ", finalDestinationPath);
|
||||
movingUtil.moveFile(file, finalDestinationPath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async asyncloadSettings() {
|
||||
this.settings = Object.assign({}, Settings.DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "auto-mover",
|
||||
"name": "AutoMover",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Moves files with specified names into the same folder.",
|
||||
"author": "Al0cam",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "AutoMover",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"description": "AutoMover: Moves files with specified names/tags where you want.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"1.0.6": "0.15.0"
|
||||
"1.0.7": "0.15.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue