From 10a9b9676b2c57e6dcbecb87e2e7530874be8c70 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 22 May 2023 15:40:53 +0800 Subject: [PATCH 1/7] fix: invalid yaml error when generating the front matter --- src/main.ts | 19 +++++++++++++ src/settings/index.ts | 10 +++++++ src/settings/template.ts | 60 +++++++++++++++++++--------------------- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/main.ts b/src/main.ts index de2d3be..16801a8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -173,6 +173,7 @@ export default class OmnivorePlugin extends Plugin { filename, folderDateFormat, isSingleFile, + frontMatterVariables, } = this.settings; if (syncing) { @@ -237,6 +238,7 @@ export default class OmnivorePlugin extends Plugin { this.settings.dateHighlightedFormat, this.settings.dateSavedFormat, isSingleFile, + frontMatterVariables, fileAttachment ); // use the custom filename @@ -484,6 +486,23 @@ class OmnivoreSettingTab extends PluginSettingTab { }); }); + new Setting(generalSettings) + .setName("Front Matter Variables") + .setDesc( + "Enter the front matter variables to be used in the template separated by commas. Available variables are title, author, tags, date_saved, date_published" + ) + .addTextArea((text) => { + text + .setPlaceholder("Enter the front matter variables") + .setValue(this.plugin.settings.frontMatterVariables.join(",")) + .onChange(async (value) => { + this.plugin.settings.frontMatterVariables = JSON.parse(value); + await this.plugin.saveSettings(); + }); + text.inputEl.setAttr("rows", 5); + text.inputEl.setAttr("cols", 60); + }); + new Setting(generalSettings) .setName("Template") .setDesc( diff --git a/src/settings/index.ts b/src/settings/index.ts index 0839fcf..d15eb40 100644 --- a/src/settings/index.ts +++ b/src/settings/index.ts @@ -1,5 +1,13 @@ import { DEFAULT_TEMPLATE } from "./template"; +export const FRONT_MATTER_VARIABLES = [ + "title", + "author", + "tags", + "date_saved", + "date_published", +]; + export const DEFAULT_SETTINGS: OmnivoreSettings = { dateHighlightedFormat: "yyyy-MM-dd HH:mm:ss", dateSavedFormat: "yyyy-MM-dd HH:mm:ss", @@ -19,6 +27,7 @@ export const DEFAULT_SETTINGS: OmnivoreSettings = { isSingleFile: false, frequency: 0, intervalId: 0, + frontMatterVariables: FRONT_MATTER_VARIABLES, }; export enum Filter { @@ -51,4 +60,5 @@ export interface OmnivoreSettings { isSingleFile: boolean; frequency: number; intervalId: number; + frontMatterVariables: string[]; } diff --git a/src/settings/template.ts b/src/settings/template.ts index a82bc73..a8a2a64 100644 --- a/src/settings/template.ts +++ b/src/settings/template.ts @@ -6,7 +6,6 @@ import { formatDate, formatHighlightQuote, getHighlightLocation, - parseFrontMatterFromContent, removeFrontMatterFromContent, siteNameFromUrl, } from "../util"; @@ -18,26 +17,7 @@ type FunctionMap = { ) => string; }; -export const DEFAULT_TEMPLATE = `--- -id: {{{id}}} -title: > - {{{title}}} -{{#author}} -author: > - {{{author}}} -{{/author}} -{{#labels.length}} -tags: -{{#labels}} - {{{name}}} -{{/labels}} -{{/labels.length}} -date_saved: {{{dateSaved}}} -{{#datePublished}} -date_published: {{{datePublished}}} -{{/datePublished}} ---- - -# {{{title}}} +export const DEFAULT_TEMPLATE = `# {{{title}}} #Omnivore [Read on Omnivore]({{{omnivoreUrl}}}) @@ -176,6 +156,7 @@ export const renderArticleContnet = async ( dateHighlightedFormat: string, dateSavedFormat: string, isSingleFile: boolean, + frontMatterVariables: string[], fileAttachment?: string ) => { // filter out notes and redactions @@ -257,19 +238,35 @@ export const renderArticleContnet = async ( dateArchived: article.archivedAt, ...functionMap, }; - // Build content string based on template - const content = Mustache.render(template, articleView); - // get the front matter from the content - let frontMatter = parseFrontMatterFromContent(content); - if (!frontMatter) { - // if no front matter, add the id - frontMatter = { - id: article.id, - }; + const frontMatter: { [id: string]: unknown } = { + id: article.id, // id is required for deduplication + }; + + for (const item of frontMatterVariables) { + switch (item) { + case "title": + frontMatter[item] = articleView.title; + break; + case "author": + frontMatter[item] = articleView.author; + break; + case "tags": + frontMatter[item] = articleView.labels; + break; + case "date_saved": + frontMatter[item] = dateSaved; + break; + case "date_published": + frontMatter[item] = datePublished; + break; + } } + // Build content string based on template + const content = Mustache.render(template, articleView); let contentWithoutFrontMatter = removeFrontMatterFromContent(content); + let frontMatterYaml = stringifyYaml(frontMatter); if (isSingleFile) { // wrap the content without front matter in comments const sectionStart = `%%${article.id}_start%%`; @@ -277,10 +274,9 @@ export const renderArticleContnet = async ( contentWithoutFrontMatter = `${sectionStart}\n${contentWithoutFrontMatter}\n${sectionEnd}`; // if single file, wrap the front matter in an array - frontMatter = [frontMatter]; + frontMatterYaml = stringifyYaml([frontMatter]); } - const frontMatterYaml = stringifyYaml(frontMatter); const frontMatterStr = `---\n${frontMatterYaml}---`; return `${frontMatterStr}\n\n${contentWithoutFrontMatter}`; From 0f269a11e22d43a4b8ed133f1f4fdec9282f7137 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 22 May 2023 16:01:02 +0800 Subject: [PATCH 2/7] reduce the size of the textarea --- src/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index 16801a8..811dc0f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -499,8 +499,8 @@ class OmnivoreSettingTab extends PluginSettingTab { this.plugin.settings.frontMatterVariables = JSON.parse(value); await this.plugin.saveSettings(); }); - text.inputEl.setAttr("rows", 5); - text.inputEl.setAttr("cols", 60); + text.inputEl.setAttr("rows", 2); + text.inputEl.setAttr("cols", 40); }); new Setting(generalSettings) From 06df987b539cf892bdab6e205cefcf529ffc26f0 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 22 May 2023 16:11:35 +0800 Subject: [PATCH 3/7] fix: add a reset template button to reset the template to default template --- src/main.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 811dc0f..7319bf4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -521,7 +521,6 @@ class OmnivoreSettingTab extends PluginSettingTab { .setPlaceholder("Enter the template") .setValue(this.plugin.settings.template) .onChange(async (value) => { - // TODO: validate template // if template is empty, use default template this.plugin.settings.template = value ? value @@ -530,6 +529,17 @@ class OmnivoreSettingTab extends PluginSettingTab { }); text.inputEl.setAttr("rows", 30); text.inputEl.setAttr("cols", 60); + }).addExtraButton((button) => { + // add a button to reset template + button + .setIcon("reset") + .setTooltip("Reset template") + .onClick(async () => { + this.plugin.settings.template = DEFAULT_SETTINGS.template; + await this.plugin.saveSettings(); + this.display(); + new Notice("Template reset"); + }); }); new Setting(generalSettings) From 07f859f1d31f76b1479ff4ef9aec81c133376da6 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 22 May 2023 16:20:03 +0800 Subject: [PATCH 4/7] remove general settings heading --- src/main.ts | 67 ++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/main.ts b/src/main.ts index 7319bf4..73e4bf7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -387,17 +387,7 @@ class OmnivoreSettingTab extends PluginSettingTab { containerEl.createEl("h2", { text: "Settings for Omnivore plugin" }); - // create a group of general settings - containerEl.createEl("h3", { - cls: "omnivore-collapsible", - text: "General Settings", - }); - - const generalSettings = containerEl.createEl("div", { - cls: "omnivore-content", - }); - - new Setting(generalSettings) + new Setting(containerEl) .setName("API Key") .setDesc( createFragment((fragment) => { @@ -420,7 +410,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Filter") .setDesc("Select an Omnivore search filter type") .addDropdown((dropdown) => { @@ -433,7 +423,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Custom query") .setDesc( createFragment((fragment) => { @@ -459,7 +449,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Last Sync") .setDesc("Last time the plugin synced with Omnivore") .addMomentFormat((momentFormat) => @@ -473,7 +463,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Highlight Order") .setDesc("Select the order in which highlights are applied") .addDropdown((dropdown) => { @@ -486,7 +476,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Front Matter Variables") .setDesc( "Enter the front matter variables to be used in the template separated by commas. Available variables are title, author, tags, date_saved, date_published" @@ -503,7 +493,7 @@ class OmnivoreSettingTab extends PluginSettingTab { text.inputEl.setAttr("cols", 40); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Template") .setDesc( createFragment((fragment) => { @@ -529,7 +519,8 @@ class OmnivoreSettingTab extends PluginSettingTab { }); text.inputEl.setAttr("rows", 30); text.inputEl.setAttr("cols", 60); - }).addExtraButton((button) => { + }) + .addExtraButton((button) => { // add a button to reset template button .setIcon("reset") @@ -542,7 +533,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Frequency") .setDesc( "Enter the frequency in minutes to sync with Omnivore automatically. 0 means manual sync" @@ -566,7 +557,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Folder") .setDesc( "Enter the folder where the data will be stored. {{{date}}} could be used in the folder name" @@ -581,7 +572,7 @@ class OmnivoreSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); }); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Attachment Folder") .setDesc( "Enter the folder where the attachment will be downloaded to. {{{date}}} could be used in the folder name" @@ -597,7 +588,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }); }); - new Setting(generalSettings) + new Setting(containerEl) .setName("Is Single File") .setDesc( "Check this box if you want to save all articles in a single file" @@ -611,7 +602,7 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Filename") .setDesc( "Enter the filename where the data will be stored. {{{title}}} and {{{date}}} could be used in the filename" @@ -625,7 +616,7 @@ class OmnivoreSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); - new Setting(generalSettings) + new Setting(containerEl) .setName("Folder Date Format") .setDesc( createFragment((fragment) => { @@ -647,16 +638,24 @@ class OmnivoreSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); - new Setting(generalSettings).setName("Date Saved Format").addText((text) => - text - .setPlaceholder("yyyy-MM-dd'T'HH:mm:ss") - .setValue(this.plugin.settings.dateSavedFormat) - .onChange(async (value) => { - this.plugin.settings.dateSavedFormat = value; - await this.plugin.saveSettings(); - }) - ); - new Setting(generalSettings) + new Setting(containerEl) + .setName( + "Enter the date format for dateSaved variable in rendered template" + ) + .setDesc("Date Saved Format") + .addText((text) => + text + .setPlaceholder("yyyy-MM-dd'T'HH:mm:ss") + .setValue(this.plugin.settings.dateSavedFormat) + .onChange(async (value) => { + this.plugin.settings.dateSavedFormat = value; + await this.plugin.saveSettings(); + }) + ); + new Setting(containerEl) + .setName( + "Enter the date format for dateHighlighted variable in rendered template" + ) .setName("Date Highlighted Format") .addText((text) => text From 1cff8fdf2a113fdeb3677c5bff98e8eb945361cc Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Mon, 22 May 2023 19:25:09 +0800 Subject: [PATCH 5/7] Only set frontmatter values if they are not null --- src/settings/template.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/settings/template.ts b/src/settings/template.ts index a8a2a64..d925df2 100644 --- a/src/settings/template.ts +++ b/src/settings/template.ts @@ -249,16 +249,22 @@ export const renderArticleContnet = async ( frontMatter[item] = articleView.title; break; case "author": - frontMatter[item] = articleView.author; + if (articleView.author) { + frontMatter[item] = articleView.author; + } break; case "tags": - frontMatter[item] = articleView.labels; + if (articleView.labels && articleView.labels.length > 0) { + frontMatter[item] = articleView.labels; + } break; case "date_saved": frontMatter[item] = dateSaved; break; case "date_published": - frontMatter[item] = datePublished; + if (datePublished) { + frontMatter[item] = datePublished; + } break; } } From 4afd036eca6d91fb8db378276fe2a44f25b87573 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 23 May 2023 09:48:37 +0800 Subject: [PATCH 6/7] update the description settings --- src/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 73e4bf7..087e7eb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -639,10 +639,10 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); new Setting(containerEl) - .setName( + .setName("Date Saved Format") + .setDesc( "Enter the date format for dateSaved variable in rendered template" ) - .setDesc("Date Saved Format") .addText((text) => text .setPlaceholder("yyyy-MM-dd'T'HH:mm:ss") @@ -653,10 +653,10 @@ class OmnivoreSettingTab extends PluginSettingTab { }) ); new Setting(containerEl) - .setName( + .setName("Date Highlighted Format") + .setDesc( "Enter the date format for dateHighlighted variable in rendered template" ) - .setName("Date Highlighted Format") .addText((text) => text .setPlaceholder("Date Highlighted Format") From 2f60100683dfdba121ae6ca2af1acbe1d887b5ea Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 23 May 2023 10:32:19 +0800 Subject: [PATCH 7/7] validate front matter variables and deduplicate before saving --- src/main.ts | 10 +++++++++- src/settings/template.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index 087e7eb..6c361e7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,6 +16,7 @@ import { Article, loadArticles, PageType } from "./api"; import { DEFAULT_SETTINGS, Filter, + FRONT_MATTER_VARIABLES, HighlightOrder, OmnivoreSettings, } from "./settings"; @@ -486,7 +487,14 @@ class OmnivoreSettingTab extends PluginSettingTab { .setPlaceholder("Enter the front matter variables") .setValue(this.plugin.settings.frontMatterVariables.join(",")) .onChange(async (value) => { - this.plugin.settings.frontMatterVariables = JSON.parse(value); + // validate front matter variables and deduplicate + this.plugin.settings.frontMatterVariables = value + .split(",") + .map((v) => v.trim()) + .filter( + (v, i, a) => + FRONT_MATTER_VARIABLES.includes(v) && a.indexOf(v) === i + ); await this.plugin.saveSettings(); }); text.inputEl.setAttr("rows", 2); diff --git a/src/settings/template.ts b/src/settings/template.ts index d925df2..4bb285c 100644 --- a/src/settings/template.ts +++ b/src/settings/template.ts @@ -220,7 +220,7 @@ export const renderArticleContnet = async ( author: article.author, labels: article.labels?.map((l) => { return { - name: l.name.replace(" ", "_"), + name: l.name.replaceAll(" ", "_"), }; }), dateSaved,