Skip to content

Commit

Permalink
Merge pull request #68 from omnivore-app/fix/yaml
Browse files Browse the repository at this point in the history
fix: invalid yaml error when generating the front matter
  • Loading branch information
sywhb authored May 23, 2023
2 parents d9bd3a9 + 2f60100 commit 8a4c031
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 66 deletions.
102 changes: 69 additions & 33 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Article, loadArticles, PageType } from "./api";
import {
DEFAULT_SETTINGS,
Filter,
FRONT_MATTER_VARIABLES,
HighlightOrder,
OmnivoreSettings,
} from "./settings";
Expand Down Expand Up @@ -173,6 +174,7 @@ export default class OmnivorePlugin extends Plugin {
filename,
folderDateFormat,
isSingleFile,
frontMatterVariables,
} = this.settings;

if (syncing) {
Expand Down Expand Up @@ -237,6 +239,7 @@ export default class OmnivorePlugin extends Plugin {
this.settings.dateHighlightedFormat,
this.settings.dateSavedFormat,
isSingleFile,
frontMatterVariables,
fileAttachment
);
// use the custom filename
Expand Down Expand Up @@ -385,17 +388,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) => {
Expand All @@ -418,7 +411,7 @@ class OmnivoreSettingTab extends PluginSettingTab {
})
);

new Setting(generalSettings)
new Setting(containerEl)
.setName("Filter")
.setDesc("Select an Omnivore search filter type")
.addDropdown((dropdown) => {
Expand All @@ -431,7 +424,7 @@ class OmnivoreSettingTab extends PluginSettingTab {
});
});

new Setting(generalSettings)
new Setting(containerEl)
.setName("Custom query")
.setDesc(
createFragment((fragment) => {
Expand All @@ -457,7 +450,7 @@ class OmnivoreSettingTab extends PluginSettingTab {
})
);

new Setting(generalSettings)
new Setting(containerEl)
.setName("Last Sync")
.setDesc("Last time the plugin synced with Omnivore")
.addMomentFormat((momentFormat) =>
Expand All @@ -471,7 +464,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) => {
Expand All @@ -484,7 +477,31 @@ 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"
)
.addTextArea((text) => {
text
.setPlaceholder("Enter the front matter variables")
.setValue(this.plugin.settings.frontMatterVariables.join(","))
.onChange(async (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);
text.inputEl.setAttr("cols", 40);
});

new Setting(containerEl)
.setName("Template")
.setDesc(
createFragment((fragment) => {
Expand All @@ -502,7 +519,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
Expand All @@ -511,9 +527,21 @@ 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)
new Setting(containerEl)
.setName("Frequency")
.setDesc(
"Enter the frequency in minutes to sync with Omnivore automatically. 0 means manual sync"
Expand All @@ -537,7 +565,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"
Expand All @@ -552,7 +580,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"
Expand All @@ -568,7 +596,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"
Expand All @@ -582,7 +610,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"
Expand All @@ -596,7 +624,7 @@ class OmnivoreSettingTab extends PluginSettingTab {
await this.plugin.saveSettings();
})
);
new Setting(generalSettings)
new Setting(containerEl)
.setName("Folder Date Format")
.setDesc(
createFragment((fragment) => {
Expand All @@ -618,17 +646,25 @@ 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("Date Saved Format")
.setDesc(
"Enter the date format for dateSaved variable in rendered template"
)
.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("Date Highlighted Format")
.setDesc(
"Enter the date format for dateHighlighted variable in rendered template"
)
.addText((text) =>
text
.setPlaceholder("Date Highlighted Format")
Expand Down
10 changes: 10 additions & 0 deletions src/settings/index.ts
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -19,6 +27,7 @@ export const DEFAULT_SETTINGS: OmnivoreSettings = {
isSingleFile: false,
frequency: 0,
intervalId: 0,
frontMatterVariables: FRONT_MATTER_VARIABLES,
};

export enum Filter {
Expand Down Expand Up @@ -51,4 +60,5 @@ export interface OmnivoreSettings {
isSingleFile: boolean;
frequency: number;
intervalId: number;
frontMatterVariables: string[];
}
68 changes: 35 additions & 33 deletions src/settings/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
formatDate,
formatHighlightQuote,
getHighlightLocation,
parseFrontMatterFromContent,
removeFrontMatterFromContent,
siteNameFromUrl,
} from "../util";
Expand All @@ -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}}})
Expand Down Expand Up @@ -176,6 +156,7 @@ export const renderArticleContnet = async (
dateHighlightedFormat: string,
dateSavedFormat: string,
isSingleFile: boolean,
frontMatterVariables: string[],
fileAttachment?: string
) => {
// filter out notes and redactions
Expand Down Expand Up @@ -239,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,
Expand All @@ -257,30 +238,51 @@ 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":
if (articleView.author) {
frontMatter[item] = articleView.author;
}
break;
case "tags":
if (articleView.labels && articleView.labels.length > 0) {
frontMatter[item] = articleView.labels;
}
break;
case "date_saved":
frontMatter[item] = dateSaved;
break;
case "date_published":
if (datePublished) {
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%%`;
const sectionEnd = `%%${article.id}_end%%`;
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}`;
Expand Down

0 comments on commit 8a4c031

Please sign in to comment.