Skip to content

Commit

Permalink
refactoring and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
inhumantsar committed Apr 19, 2024
1 parent 15c3003 commit df8bd0a
Show file tree
Hide file tree
Showing 20 changed files with 104,660 additions and 421 deletions.
125 changes: 87 additions & 38 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { DEFAULT_SETTINGS, DEFAULT_SLURP_PROPS } from './src/const';
import { App, MarkdownView, Notice, Plugin } from 'obsidian';
import type { SlurpArticle } from './src/types/article';
import { SlurpProp, type SlurpProps } from './src/slurp-prop';
import { createFilePath, sortSlurpProps } from './src/util';
import { createFrontMatter } from './src/frontmatter';
import { fetchHtml, parsePage, mergeMetadata, parseMetadata, parseMarkdown } from './src/parse';
import { MarkdownView, Notice, Plugin } from 'obsidian';
import { DEFAULT_SETTINGS } from './src/const';
import { createFrontMatter, createFrontMatterPropSettings, createFrontMatterProps } from './src/frontmatter';
import { Logger } from './src/logger';
import { SlurpNewNoteModal } from './src/modals/new-note';
import { SlurpSettingsTab } from 'src/settings';
import type { SlurpSettings } from 'src/types/settings';
import type { FormatterArgs } from 'src/types/misc';
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';

export default class SlurpPlugin extends Plugin {
settings!: SlurpSettings;
slurpProps!: SlurpProps;
settings!: ISettings;
fmProps!: TFrontMatterProps;
logger!: Logger;

async onload() {
await this.loadSettings();
Expand All @@ -38,34 +37,73 @@ export default class SlurpPlugin extends Plugin {

onunload() { }

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

fixPropIdx() {
const props = Object.values<SlurpProp<any>>(this.slurpProps);
sortSlurpProps(props);
props.forEach((prop, idx) => prop.idx = idx);
migrateSettingsV0toV1(loadedSettings: Object): ISettings {
// only v0 lacks the settingsVersion key
if (Object.keys(loadedSettings).contains("settingsVersion")) return loadedSettings as ISettings;
if (Object.keys(loadedSettings).length == 0) return DEFAULT_SETTINGS;

const v0 = loadedSettings as ISettingsV0;

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

const fm = {
includeEmpty: v0.showEmptyProps,
tags: fmTags,
properties: v0.propSettings
} as IFrontMatterSettings;

const v1 = {
settingsVersion: 1,
fm: fm,
logs: DEFAULT_SETTINGS.logs
} as ISettings;

return v1;
}

migrateObjToMap<K, V>(obj: Object) {
if (!obj.hasOwnProperty('keys')) {
if (Object.keys(obj).length === 0)
return new Map<K, V>();
}
}

migrateSettings() {
this.fixTagPrefix();
this.fixPropIdx();
this.saveSettings();
migrateSettings(settings: ISettingsV0 | ISettings): ISettings {
// this.fixPropIdx();
const s1 = this.migrateSettingsV0toV1(settings);
// // @ts-ignore
// s1.fm.properties = this.migrateObjToMap<string, IFrontMatterPropSetting>(s1.fm.properties);
// ...more to come...
return s1;
}

async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
this.slurpProps = SlurpProp.fromSettings(this.settings.propSettings, DEFAULT_SLURP_PROPS);
this.migrateSettings();
const preSettings = Object.assign({}, await this.loadData());
// this.logger.debug("pre-migration settings", preSettings);
this.settings = this.migrateSettings(preSettings);

this.logger = new Logger(this);
this.logger.debug("post-migration settings", this.settings);

this.fmProps = createFrontMatterProps(this.settings.fm.properties);
this.logger.debug("fmProps loaded", this.fmProps);
await this.saveSettings();
}

async saveSettings() {
for (let i in this.slurpProps) {
this.settings.propSettings[i] = this.slurpProps[i].getSetting();
}
this.settings.fm.tags.prefix = this.fixTagPrefix(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 All @@ -74,26 +112,37 @@ export default class SlurpPlugin extends Plugin {
async slurp(url: string): Promise<void> {
const doc = new DOMParser().parseFromString(await fetchHtml(url), 'text/html');

const article: SlurpArticle = {
const article: IArticle = {
slurpedTime: new Date(),
tags: new Set<FormatterArgs>(),
tags: new Array<FormatterArgs>(),
...parsePage(doc)
};
this.logger.debug("parsed page", article);

// find metadata that readability doesn't pick up
const parsedMetadata = parseMetadata(doc, this.slurpProps, this.settings.tagPrefix, this.settings.tagCase)
const parsedMetadata = parseMetadata(doc, this.fmProps, this.settings.fm.tags.prefix, this.settings.fm.tags.case)
this.logger.debug("parsed metadata", parsedMetadata);

const mergedMetadata = mergeMetadata(article, parsedMetadata)
this.logger.debug("merged metadata", parsedMetadata);

const md = parseMarkdown(article.content);
this.logger.debug("converted page to markdown", md);

await this.slurpNewNoteCallback({
...mergeMetadata(article, parsedMetadata),
content: parseMarkdown(article.content),
...mergedMetadata,
content: md,
link: url
});
}

async slurpNewNoteCallback(article: SlurpArticle) {
const frontMatter = createFrontMatter(article, this.slurpProps, this.settings.showEmptyProps);
const content = `---\n${frontMatter}\n---\n${article.content}`;
async slurpNewNoteCallback(article: IArticle) {
const frontMatter = createFrontMatter(article, this.fmProps, this.settings.fm.includeEmpty);
this.logger.debug("created frontmatter", frontMatter);

const content = `---\n${frontMatter}\n---\n\n${article.content}`;

this.logger.debug("writing file...");
const filePath = await createFilePath(this.app.vault, article.title);
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.5b6",
"version": "0.1.5b7",
"minAppVersion": "0.15.0",
"description": "Slurps webpages and saves them as clean, uncluttered Markdown.",
"author": "inhumantsar",
Expand Down
43 changes: 25 additions & 18 deletions src/components/NotePropSettings.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
<script lang="ts">
import { validateSlurpProps } from "src/validate";
import { SlurpProp } from "src/slurp-prop";
import { flip } from "svelte/animate";
import { crossfade } from "svelte/transition";
import { quintOut } from "svelte/easing";
import { sortSlurpProps } from "../util";
import { FrontMatterProp, validateFrontMatterProps } from "../frontmatter";
import { sortFrontMatterItems } from "../util";
// for the order-shift animation
const [send, receive] = crossfade({ duration: 350 });
export let props: Array<SlurpProp<any>>;
export let onValidate: (props: Array<SlurpProp<any>>) => void;
$: sortSlurpProps(props);
export let props: FrontMatterProp[];
export let onValidate: (props: FrontMatterProp[]) => void;
$: sortFrontMatterItems(props);
// populate, then make reactive.
let inputsVisible = new Array(props.length);
$: inputsVisible;
// making validation reactive helps with errors but also spams the save settings function.
// might become an issue when there are lots of properties to deal with.
$: validationErrors = validateSlurpProps(props, onValidate);
$: validationErrors = validateFrontMatterProps(props);
$: {
const hasErrorsCount = validationErrors
.map((val) => val.hasErrors)
.filter((val) => val === true).length;
if (hasErrorsCount === 0) onValidate(props);
}
$: tooltips = props.map((prop) => {
return {
Expand All @@ -29,7 +34,7 @@
});
const toggleInputVisibility = (idx: number) => {
if (propErrors(idx).length == 0)
if (getValidationErrors(idx).length == 0)
inputsVisible[idx] = !inputsVisible[idx];
};
Expand All @@ -48,9 +53,11 @@
props[to].idx = from;
};
const addNewProp = () => {
const newProp = new SlurpProp({
id: (Math.random() + 1).toString(36).substring(7),
const addItem = () => {
const id = (Math.random() + 1).toString(36).substring(7);
const newProp = new FrontMatterProp({
id: id,
key: id,
idx: props.length,
enabled: true,
custom: true,
Expand All @@ -61,7 +68,7 @@
props = props;
};
const deleteProp = (idx: number) => {
const deleteItem = (idx: number) => {
toggleInputVisibility(idx);
props.remove(props[idx]);
props.forEach((v, i) => {
Expand All @@ -80,7 +87,7 @@
const getInvalidClass = (idx: number) =>
validationErrors[idx].format.length > 0 ? "validation-error" : "";
const propErrors = (idx: number) => [
const getValidationErrors = (idx: number) => [
...validationErrors[idx].format,
...validationErrors[idx].key,
];
Expand Down Expand Up @@ -133,7 +140,7 @@
<button
class="edit {inputsVisible[idx] ? 'mod-cta' : ''}"
title={inputsVisible[idx] ? "Close" : "Edit"}
disabled={propErrors(idx).length > 0}
disabled={getValidationErrors(idx).length > 0}
on:click={() => toggleInputVisibility(idx)}
>
{inputsVisible[idx] ? "Close" : "Edit"}
Expand All @@ -143,12 +150,12 @@
<div
id={`input-section-${idx}`}
class="input-section {inputsVisible[idx] ||
propErrors(idx).length > 0
getValidationErrors(idx).length > 0
? 'visible'
: ''}"
>
<div class="validation-error">
{propErrors(idx).join("\n").trim()}
{getValidationErrors(idx).join("\n").trim()}
</div>

<!-- Enable -->
Expand Down Expand Up @@ -252,7 +259,7 @@
<div class="setting-item-control">
<button
class="mod-warning"
on:click={() => deleteProp(idx)}
on:click={() => deleteItem(idx)}
>
Delete
</button>
Expand All @@ -265,7 +272,7 @@

<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div id="new-property" title="New Property" on:click={addNewProp}>
<div id="new-property" title="New Property" on:click={addItem}>
<span style="margin-right:0.6em">New Property</span>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down
Loading

0 comments on commit df8bd0a

Please sign in to comment.