diff --git a/main.ts b/main.ts index 86a9c46..7d07549 100644 --- a/main.ts +++ b/main.ts @@ -107,33 +107,37 @@ export default class SlurpPlugin extends Plugin { await this.saveData(this.settings); } - displayError = (err: Error) => new Notice(`Slurp Error! ${err.message}`); + displayError = (err: Error) => new Notice(`Slurp Error! ${err.message}. If this is a bug, please report it from plugin settings.`, 0); async slurp(url: string): Promise { - const doc = new DOMParser().parseFromString(await fetchHtml(url), 'text/html'); - - const article: IArticle = { - slurpedTime: new Date(), - tags: new Array(), - ...parsePage(doc) - }; - this.logger.debug("parsed page", article); - - // find metadata that readability doesn't pick up - 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({ - ...mergedMetadata, - content: md, - link: url - }); + try { + const doc = new DOMParser().parseFromString(await fetchHtml(url), 'text/html'); + + const article: IArticle = { + slurpedTime: new Date(), + tags: new Array(), + ...parsePage(doc) + }; + this.logger.debug("parsed page", article); + + // find metadata that readability doesn't pick up + 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({ + ...mergedMetadata, + content: md, + link: url + }); + } catch (err) { + this.displayError(err as Error); + } } async slurpNewNoteCallback(article: IArticle) { diff --git a/manifest-beta.json b/manifest-beta.json index c5b3457..097fb97 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "slurp", "name": "Slurp", - "version": "0.1.6", + "version": "0.1.7", "minAppVersion": "0.15.0", "description": "Slurps webpages and saves them as clean, uncluttered Markdown.", "author": "inhumantsar", diff --git a/manifest.json b/manifest.json index 66eedaf..98c31bc 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "slurp", "name": "Slurp", - "version": "0.1.6", + "version": "0.1.7", "minAppVersion": "0.15.0", "description": "Slurps webpages and saves them as clean, uncluttered Markdown.", "author": "inhumantsar", diff --git a/src/logger.ts b/src/logger.ts index 1a45617..4697597 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -13,7 +13,7 @@ interface LogMessage { timestamp: number } -const MAX_BUFFER_SIZE = 10 ^ 5; +const MAX_BUFFER_SIZE = 100; let _logger: Logger; @@ -64,10 +64,14 @@ export class Logger { _logger = this; } + private sortBuffer = () => this.buffer.sort((a, b) => a.timestamp - b.timestamp); + private bufferLog = (msg: LogMessage) => { - this.buffer.sort((a, b) => a.timestamp - b.timestamp); + this.sortBuffer(); if (this.buffer.length >= MAX_BUFFER_SIZE) - this.buffer.pop(); + // pop would be more efficient, but with 100 items max and a 500ms + // interval, the impact should be negligible. + this.buffer.shift(); this.buffer.push(msg); } @@ -77,36 +81,44 @@ export class Logger { return this.vault.getFileByPath(file) || await this.vault.create(file, `##### startup: ${new Date().toUTCString()}\n`); }; - flush = async () => { - if (this.buffer.length == 0) return; - - const file = await this.getOrCreateLogFile(); - - if (this.settings.debug) console.log(`flushing logs`, this.buffer, file); - - const b = new Set(this.buffer); + dump = (returnCallback = true, limit = Infinity, format: "markdown" = "markdown"): { content: string, onComplete: null | (() => void) } => { let content = "\n"; + const b = new Set(this.sortBuffer()); - b.forEach((msg) => { + for (let idx = 0; idx < this.buffer.length && idx < limit; idx++) { + const msg = this.buffer[idx]; let optJson = []; for (let i of msg.optionalParams || []) { optJson.push(JSON.stringify(serialize(i), undefined, 2)); } - content += `##### [${msg.level.padStart(5)}] ${msg.msg}\n` + - `> \`${msg.caller}\`\n> ${msg.timestamp}\n\n` + content += `##### ${msg.timestamp} | ${msg.level.padStart(5).toUpperCase()} | ${msg.msg}\n` + + `- Caller: \`${msg.caller}\`\n\n` if (optJson.length > 0) content += "```\n" + `${optJson.join('\n')}\n` + "```\n\n"; - }); + }; + return { + content, onComplete: returnCallback + ? () => b.forEach((msg) => this.buffer.remove(msg)) + : null + }; + } + + flush = async () => { + if (this.buffer.length == 0 || !this.settings.debug) return; + + const file = await this.getOrCreateLogFile(); + + console.log(`flushing logs`, this.buffer, file); + + const { content, onComplete } = this.dump(); await this.vault.append(file, content); - b.forEach((msg) => this.buffer.remove(msg)); + if (onComplete) onComplete(); }; private log = (msg: LogMessage) => { - if (!this.settings.debug && msg.level == "debug") return; - const msgStr = `[${msg.caller}] ${msg.msg}`; const fn = msg.level === "error" ? console.error @@ -114,8 +126,10 @@ export class Logger { ? console.warn : console.log; - fn(msgStr, ...msg.optionalParams || []); - if (this.settings.debug) this.bufferLog(msg); + if (this.settings.debug || msg.level != "debug") + fn(msgStr, ...msg.optionalParams || []); + + this.bufferLog(msg); } debug = (msg: string, ...optionalParams: any[]) => { diff --git a/src/settings.ts b/src/settings.ts index d070855..910bd6d 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,8 +1,8 @@ import type SlurpPlugin from "main"; -import { App, PluginSettingTab, Setting } from "obsidian"; +import { App, PluginSettingTab, Setting, ValueComponent } from "obsidian"; import FrontMatterSettings from "./components/NotePropSettings.svelte"; import { FrontMatterProp } from "./frontmatter"; -import { Logger } from "./logger"; +import { Logger, logger } from "./logger"; import { StringCaseOptions, type StringCase } from "./string-case"; import { DEFAULT_SETTINGS } from "./const"; @@ -52,8 +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] }`)); - this.plugin.fmProps.set(prop.id, prop) + this.plugin.fmProps.set(prop.id, prop); return prop.id; }); @@ -118,7 +117,11 @@ export class SlurpSettingsTab extends PluginSettingTab { }) ); - new Setting(containerEl).setName('Logs').setHeading(); + + new Setting(containerEl) + .setName("Report an Issue") + .setHeading(); + new Setting(containerEl) .setName("Debug mode") .setDesc("Write debug messages to console and slurp.log.") @@ -129,5 +132,43 @@ export class SlurpSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); + + new Setting(containerEl) + .setName("Recent Logs") + .setDesc( + "Copy+Paste these when opening a new GitHub issue. Not available when debug mode is enabled. " + + "Submit the most recent log file instead" + ) + .setDisabled(!this.plugin.settings.logs.debug); + + if (!this.plugin.settings.logs.debug) { + const recentLogs = containerEl.createDiv(); + const recentLogsStyles: Record = {}; + recentLogsStyles["font-size"] = "small"; + recentLogs.setCssProps(recentLogsStyles); + + const logsTextArea = containerEl.createEl("textarea"); + logsTextArea.setText(logger().dump(false, 25).content); + const logsTextAreaStyles: Record = {}; + logsTextAreaStyles["width"] = "100%"; + logsTextAreaStyles["height"] = "20em"; + logsTextArea.setCssProps(logsTextAreaStyles); + recentLogs.appendChild(logsTextArea); + containerEl.appendChild(recentLogs); + } + + const githubOuter = containerEl.createDiv(); + const githubPara = containerEl.createEl("p"); + const githubParaStyles: Record = {}; + githubParaStyles["font-size"] = "normal"; + githubParaStyles["text-align"] = "center"; + githubPara.setCssProps(githubParaStyles); + + const gitHubLink = containerEl.createSpan(); + gitHubLink.addClass("external-link"); + gitHubLink.setText('https://github.com/inhumantsar/slurp/issues/new?labels=bug'); + githubPara.appendChild(gitHubLink); + githubOuter.appendChild(githubPara); + containerEl.appendChild(githubOuter); } } \ No newline at end of file diff --git a/src/util.ts b/src/util.ts index b13c9ec..55d8385 100644 --- a/src/util.ts +++ b/src/util.ts @@ -31,7 +31,7 @@ export const cleanTitle = (title: string) => { } export const ensureFolderExists = async (vault: Vault, path: string) => { - const existingFolder = vault.getFolderByPath(path); + const existingFolder = vault.getFolderByPath(normalizePath(path)); logger().debug(`getFolderByPath("${path}")`, existingFolder); return existingFolder !== null ? existingFolder.path diff --git a/test-resources/vault/.obsidian/workspace.json b/test-resources/vault/.obsidian/workspace.json index 0e11489..18415a1 100644 --- a/test-resources/vault/.obsidian/workspace.json +++ b/test-resources/vault/.obsidian/workspace.json @@ -4,16 +4,16 @@ "type": "split", "children": [ { - "id": "5c3c141e81d9d7bd", + "id": "f4f043c1cdef4697", "type": "tabs", "children": [ { - "id": "3780d90630b6e19d", + "id": "1b543898b9339945", "type": "leaf", "state": { "type": "markdown", "state": { - "file": "slurp/Are SAP users embracing AI.md", + "file": "other path/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md", "mode": "source", "backlinks": false, "source": false @@ -86,7 +86,7 @@ "state": { "type": "backlink", "state": { - "file": "slurp/Are SAP users embracing AI.md", + "file": "other path/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md", "collapseAll": false, "extraContext": false, "sortOrder": "alphabetical", @@ -103,7 +103,7 @@ "state": { "type": "outgoing-link", "state": { - "file": "slurp/Are SAP users embracing AI.md", + "file": "other path/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md", "linksCollapsed": false, "unlinkedCollapsed": true } @@ -126,7 +126,7 @@ "state": { "type": "outline", "state": { - "file": "slurp/Are SAP users embracing AI.md" + "file": "other path/The first Apple-approved emulator for the iPhone has arrived... and been pulled.md" } } } @@ -147,10 +147,18 @@ "command-palette:Open command palette": false } }, - "active": "3780d90630b6e19d", + "active": "1b543898b9339945", "lastOpenFiles": [ - "Are SAP users embracing AI (1).md", + "_slurplogs/slurp-2024-04-22.md", + "_slurplogs/slurp-2024-04-21.md", + "Inbox/Slurped/Are SAP users embracing AI (1).md", + "Inbox/Slurped/Are SAP users embracing AI.md", + "Slurped Pages/Are SAP users embracing AI (1).md", + "Inbox/Slurped", + "Inbox", + "Slurped Pages/Are SAP users embracing AI.md", "slurp/Are SAP users embracing AI.md", + "Are SAP users embracing AI (1).md", "slurp", "Are SAP users embracing AI.md", "OpenNeRF - Open Set 3D Neural Scene Segmentation with Pixel-Wise Features and Rendered Novel Views (1).md", @@ -171,14 +179,8 @@ "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-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", "_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" ] } \ No newline at end of file