Skip to content

Commit

Permalink
add setting for default save location
Browse files Browse the repository at this point in the history
  • Loading branch information
inhumantsar committed Apr 20, 2024
1 parent cc4e784 commit 81de945
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 54 deletions.
20 changes: 10 additions & 10 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SlurpNewNoteModal } from './src/modals/new-note';
import { fetchHtml, mergeMetadata, parseMarkdown, parseMetadata, parsePage } from './src/parse';
import { SlurpSettingsTab } from './src/settings';
import type { FormatterArgs, IArticle, IFrontMatterSettings, IFrontMatterTagSettings, ISettings, ISettingsV0, TFrontMatterProps } from './src/types';
import { createFilePath } from './src/util';
import { getNewFilePath, removeTrailingSlash } from './src/util';

export default class SlurpPlugin extends Plugin {
settings!: ISettings;
Expand Down Expand Up @@ -37,12 +37,6 @@ export default class SlurpPlugin extends Plugin {

onunload() { }

fixTagPrefix(tagPrefix: string) {
return tagPrefix.endsWith('/')
? tagPrefix.substring(0, tagPrefix.length - 1)
: tagPrefix;
}

migrateSettingsV0toV1(loadedSettings: Object): ISettings {
// only v0 lacks the settingsVersion key
if (Object.keys(loadedSettings).contains("settingsVersion")) return loadedSettings as ISettings;
Expand All @@ -52,7 +46,7 @@ export default class SlurpPlugin extends Plugin {

const fmTags = {
parse: v0.parseTags,
prefix: this.fixTagPrefix(v0.tagPrefix),
prefix: removeTrailingSlash(v0.tagPrefix),
case: v0.tagCase
} as IFrontMatterTagSettings;

Expand All @@ -71,6 +65,11 @@ export default class SlurpPlugin extends Plugin {
return v1;
}

patchInDefaults() {
if (this.settings.defaultPath === undefined)
this.settings.defaultPath = DEFAULT_SETTINGS.defaultPath;
}

migrateObjToMap<K, V>(obj: Object) {
if (!obj.hasOwnProperty('keys')) {
if (Object.keys(obj).length === 0)
Expand All @@ -91,6 +90,7 @@ export default class SlurpPlugin extends Plugin {
const preSettings = Object.assign({}, await this.loadData());
// this.logger.debug("pre-migration settings", preSettings);
this.settings = this.migrateSettings(preSettings);
this.patchInDefaults();

this.logger = new Logger(this);
this.logger.debug("post-migration settings", this.settings);
Expand All @@ -101,7 +101,7 @@ export default class SlurpPlugin extends Plugin {
}

async saveSettings() {
this.settings.fm.tags.prefix = this.fixTagPrefix(this.settings.fm.tags.prefix);
this.settings.fm.tags.prefix = removeTrailingSlash(this.settings.fm.tags.prefix);
this.settings.fm.properties = createFrontMatterPropSettings(this.fmProps);
this.logger.debug("saving settings", this.settings);
await this.saveData(this.settings);
Expand Down Expand Up @@ -143,7 +143,7 @@ export default class SlurpPlugin extends Plugin {
const content = `---\n${frontMatter}\n---\n\n${article.content}`;

this.logger.debug("writing file...");
const filePath = await createFilePath(this.app.vault, article.title);
const filePath = await getNewFilePath(this.app.vault, article.title, this.settings.defaultPath);
const newFile = await this.app.vault.create(filePath, content);
this.app.workspace.getActiveViewOfType(MarkdownView)?.leaf.openFile(newFile);
}
Expand Down
2 changes: 1 addition & 1 deletion manifest-beta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "slurp",
"name": "Slurp",
"version": "0.1.6b0",
"version": "0.1.6",
"minAppVersion": "0.15.0",
"description": "Slurps webpages and saves them as clean, uncluttered Markdown.",
"author": "inhumantsar",
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "slurp",
"name": "Slurp",
"version": "0.1.5",
"version": "0.1.6",
"minAppVersion": "0.15.0",
"description": "Slurps webpages and saves them as clean, uncluttered Markdown.",
"author": "inhumantsar",
Expand Down
5 changes: 2 additions & 3 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const FRONT_MATTER_ITEM_DEFAULT_SETTINGS = createFrontMatterPropSettings(createF

export const DEFAULT_SETTINGS: ISettings = {
settingsVersion: 1,
defaultPath: "Slurped Pages",
fm: {
includeEmpty: false,
tags: {
Expand All @@ -83,6 +84,4 @@ export const DEFAULT_SETTINGS: ISettings = {
properties: FRONT_MATTER_ITEM_DEFAULT_SETTINGS
},
logs: { logPath: "_slurplogs", debug: false }
}

export const DEFAULT_PATH: string = "Slurped Pages";
}
17 changes: 12 additions & 5 deletions src/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,22 @@ export const formatDate = (t = "YYYY-MM-DDTHH:mm", v = new Date()) => {
return isNaN(+result) ? result : +result;
}

export const formatString = (tmpl: string, val: any) => formatStrings(tmpl, [{ s: val }])[0];
export const formatString = (tmpl: string, val: any) =>
val
? formatStrings(tmpl, [{ s: val }])[0]
: "";

export const formatStrings = (tmpl: string, val: Iterable<FormatterArgs>): Array<string> => {
const result = new Array<string>();
for (let i of val) {
const s = tmpl.replace(/\{(\w+)\}/g, (match, name) => {
return i.hasOwnProperty(name) ? i[name] : match;
});
result.push(s);
result.push(
tmpl.replace(/\{(\w+)\}/g, (match, name) =>
!i.hasOwnProperty(name)
? match
: i[name] !== undefined
? ""
: i[name]
));
}
return result;
}
Expand Down
18 changes: 16 additions & 2 deletions src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import FrontMatterSettings from "./components/NotePropSettings.svelte";
import { FrontMatterProp } from "./frontmatter";
import { Logger } from "./logger";
import { StringCaseOptions, type StringCase } from "./string-case";
import { DEFAULT_SETTINGS } from "./const";

export class SlurpSettingsTab extends PluginSettingTab {
plugin: SlurpPlugin;
Expand All @@ -16,11 +17,24 @@ export class SlurpSettingsTab extends PluginSettingTab {
}

display(): void {

const { containerEl } = this;

containerEl.empty();

new Setting(containerEl).setName('General').setHeading();
this.app.workspace
new Setting(containerEl)
.setName('Default save location')
.setDesc("What directory should Slurp save pages to? Leave blank to save to the vault's main directory.")
.addText((text) => text
.setValue(this.plugin.settings.defaultPath)
.setPlaceholder(DEFAULT_SETTINGS.defaultPath)
.onChange(async (val) => {
this.plugin.settings.defaultPath = val;
await this.plugin.saveSettings();
})
);

new Setting(containerEl).setName('Properties').setHeading();

new Setting(containerEl)
Expand All @@ -38,7 +52,7 @@ export class SlurpSettingsTab extends PluginSettingTab {
this.logger.debug("onValidate called", props);
// update existing
const modKeys = props.map((prop) => {
//Object.keys(prop).forEach((key) => console.log(`new: ${prop[key]}, curr: ${this.plugin.slurpProps[prop.id][key]}`));
//Object.keys(prop).forEach((key) => console.log(`new: ${ prop[key]}, curr: ${ this.plugin.slurpProps[prop.id][key] }`));
this.plugin.fmProps.set(prop.id, prop)
return prop.id;
});
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ export interface IFrontMatterValidationErrors {


export interface ISettings {
settingsVersion: number,
settingsVersion: number
defaultPath: string
fm: IFrontMatterSettings
logs: ILogSettings
}
Expand Down
66 changes: 53 additions & 13 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,68 @@
import { Vault, normalizePath } from "obsidian";
import { DEFAULT_PATH } from "src/const";
import type { FrontMatterProp } from "src/frontmatter";
import type { StringCase } from "src/string-case";
import { logger } from "./logger";

export const isEmpty = (val: any): boolean => {
return val == null
|| (typeof val === 'string' && val.trim().length == 0)
|| (typeof val[Symbol.iterator] === 'function' && val.length === 0)
}

export const createFilePath = async (vault: Vault, title: string, path: string = DEFAULT_PATH): Promise<string> => {
// increment suffix on duplicated file names... to a point.
const fpLoop = (p: string, fn: string, retries: number): string => {
if (retries == 100) throw "Cowardly refusing to increment past 100.";
const suffix = retries > 0 ? `-${retries}.md` : '.md';
const fp = normalizePath(`${p}/${fn}${suffix}`);
return vault.getFileByPath(fp) ? fpLoop(p, fn, retries + 1) : fp
}
export const removeTrailingSlash = (str: string) =>
str.endsWith('/')
? str.substring(0, str.length - 1)
: str;

export const cleanTitle = (title: string) => {
// disallowed characters: * " \ / < > : | ?
return title
// assume that a colons and pipes are most likely a useful separator, eg:
// OpenNeRF: Open Set 3D Neural Scene Segmentation...
// Local News | Botched home sale costs man his real estate license
// Blog|Some Title
.replace(/\s?[\|:]\s?/g, ' - ')
// assume that quotes are used to enclose words/phrases
// eg: Bitcoin prices edges lower after "Halving" concludes
.replace('"', "'")
// assume that others can simply be nuked
.replace(/[\*"\\/<>:\?]/g, '');

}

export const ensureFolderExists = async (vault: Vault, path: string) => {
const existingFolder = vault.getFolderByPath(path);
logger().debug(`getFolderByPath("${path}")`, existingFolder);
return existingFolder !== null
? existingFolder.path
: path === ""
? ""
: await (await vault.createFolder(path)).path;

}

const handleDuplicates = (vault: Vault, filename: string, retries: number, path: string): string => {
if (retries == 100) throw "Cowardly refusing to increment past 100.";

const suffix = retries > 0 ? ` (${retries}).md` : '.md';
const fullPath = path !== ""
? `${path}/${filename}${suffix}`
: `${filename}${suffix}`;
const normPath = normalizePath(fullPath);

logger().debug(`checking if path is available: ${normPath}`);
return vault.getFileByPath(normPath) ? handleDuplicates(vault, filename, retries + 1, path) : normPath
}

export const getNewFilePath = async (vault: Vault, title: string, pathSetting: string): Promise<string> => {

const titleClean = cleanTitle(title);
logger().debug(`finalised title: ${title}`);

// TODO: add setting for slurped pages folder
const folder = vault.getFolderByPath(path) || await vault.createFolder(path);
const fileName = title.replace(/[\\\/:]/g, '-');
const path = await ensureFolderExists(vault, pathSetting);
logger().debug(`finalised folder: ${path}`);

return fpLoop(folder.path, fileName, 0);
return handleDuplicates(vault, titleClean, 0, path);
};

export const sortFrontMatterItems = (items: FrontMatterProp[]) => items.sort((a, b) => a.idx - b.idx);
Expand Down
37 changes: 19 additions & 18 deletions test-resources/vault/.obsidian/workspace.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"state": {
"type": "markdown",
"state": {
"file": "Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md",
"file": "Are SAP users embracing AI (1).md",
"mode": "source",
"backlinks": false,
"source": false
Expand Down Expand Up @@ -70,7 +70,7 @@
}
],
"direction": "horizontal",
"width": 300
"width": 294.5
},
"right": {
"id": "903645595e28f33d",
Expand All @@ -86,7 +86,7 @@
"state": {
"type": "backlink",
"state": {
"file": "Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md",
"file": "Are SAP users embracing AI (1).md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
Expand All @@ -103,7 +103,7 @@
"state": {
"type": "outgoing-link",
"state": {
"file": "Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md",
"file": "Are SAP users embracing AI (1).md",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
Expand All @@ -126,7 +126,7 @@
"state": {
"type": "outline",
"state": {
"file": "Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md"
"file": "Are SAP users embracing AI (1).md"
}
}
}
Expand All @@ -149,34 +149,35 @@
},
"active": "3780d90630b6e19d",
"lastOpenFiles": [
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md",
"Are SAP users embracing AI.md",
"Are SAP users embracing AI (1).md",
"OpenNeRF - Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views (1).md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion.md",
"OpenNeRF - Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views.md",
"Slurped Pages/OpenNeRF - Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views (1).md",
"Slurped Pages/OpenNeRF - Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views.md",
"Slurped Pages/OpenNeRF- Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views.md",
"_slurplogs/slurp-2024-04-20.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-2.md",
"_slurplogs/slurp-2024-04-19.md",
"other path/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-1.md",
"other path",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-6.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-7.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-5.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-4.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-3.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-2.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-10.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-11.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-8.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-9.md",
"_slurplogs/slurp-2024-04-18.md",
"Slurped Pages/OpenNeRF- Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion.md",
"_slurplogs/slurp-2024-04-18.log",
"_slurplogs",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled-12.md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled (without tags).md",
"Slurped Pages/The first Apple-approved emulator for the iPhone has arrived... and been pulled (with tags).md",
"Slurped Pages/Show HN- Invertornot.com – API to enhance your images in dark-mode.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-3.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-4.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-2.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-1.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-5.md",
"Slurped Pages/InvertOrNot - Smart Dark-Mode Image Inversion-6.md",
"Slurped Pages"
]
}

0 comments on commit 81de945

Please sign in to comment.