Skip to content

Commit

Permalink
v0.0.14
Browse files Browse the repository at this point in the history
  • Loading branch information
kaiiiz committed Sep 16, 2022
2 parents 519ebce + e2cd7a8 commit caf6a3b
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 42 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-raindrop-highlights",
"name": "Raindrop Highlights",
"version": "0.0.13",
"version": "0.0.14",
"minAppVersion": "0.14.0",
"description": "Sync your Raindrop.io highlights.",
"author": "kaiiiz",
Expand Down
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-raindrop-highlights",
"version": "0.0.13",
"version": "0.0.14",
"description": "Sync your Raindrop.io highlights.",
"main": "main.js",
"scripts": {
Expand All @@ -12,23 +12,23 @@
"author": "kaiiiz",
"license": "MIT",
"devDependencies": {
"@tsconfig/svelte": "^3.0.0",
"@types/node": "^16.11.6",
"@types/nunjucks": "^3.2.1",
"@tsconfig/svelte": "3.0.0",
"@types/node": "16.11.6",
"@types/nunjucks": "3.2.1",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"esbuild": "0.14.47",
"esbuild-svelte": "^0.7.1",
"esbuild-svelte": "0.7.1",
"obsidian": "latest",
"svelte": "^3.49.0",
"svelte-preprocess": "^4.10.7",
"svelte": "3.49.0",
"svelte-preprocess": "4.10.7",
"tslib": "2.4.0",
"typescript": "4.7.4"
},
"dependencies": {
"axios": "^0.27.2",
"nunjucks": "^3.2.3",
"sanitize-filename": "^1.6.3"
"axios": "0.27.2",
"nunjucks": "3.2.3",
"sanitize-filename": "1.6.3"
}
}
3 changes: 3 additions & 0 deletions src/assets/defaultMetadataTemplate.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% if link %}link: {{link}}{% endif %}
{% if tags|length %}tags: {%for tag in tags %}
- {{tag}}{% endfor %}{% endif %}
3 changes: 2 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DEFAULT_TEMPLATE from './assets/defaultTemplate.njk';
import type { RaindropPluginSettings } from "./types";

export const VERSION = '0.0.13';
export const VERSION = '0.0.14';

export const DEFAULT_SETTINGS: RaindropPluginSettings = {
version: VERSION,
Expand All @@ -13,6 +13,7 @@ export const DEFAULT_SETTINGS: RaindropPluginSettings = {
highlightsFolder: '/',
syncCollections: {},
template: DEFAULT_TEMPLATE,
metadataTemplate: "",
dateTimeFormat: 'YYYY/MM/DD HH:mm:ss',
autoSyncInterval: 0,
};
84 changes: 66 additions & 18 deletions src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import nunjucks from "nunjucks";
import Moment from "moment";
import type RaindropPlugin from "./main";
import type { BookmarkFileFrontMatter, RaindropBookmark } from "./types";
import { stringifyYaml } from "obsidian";
import { Notice, parseYaml, stringifyYaml } from "obsidian";

type RenderHighlight = {
id: string;
Expand Down Expand Up @@ -32,6 +32,32 @@ type RenderTemplate = {
important: boolean;
};

const FAKE_RENDER_CONTEXT: RenderTemplate = {
is_new_article: true,
id: 1000,
title: "fake_title",
excerpt: "fake_excerpt",
link: "https://example.com",
highlights: [
{
id: "123456789abcdefghijklmno",
color: "red",
created: "2022-08-11T01:58:27.457Z",
lastUpdate: "2022-08-13T01:58:27.457Z",
note: "fake_note",
text: "fake_text",
}
],
collection: {
title: "fake_collection",
},
tags: ["fake_tag1", "fake_tag2"],
cover: "https://example.com",
created: "2022-08-10T01:58:27.457Z",
type: "link",
important: false,
};

export default class Renderer {
plugin: RaindropPlugin;

Expand All @@ -40,16 +66,50 @@ export default class Renderer {
nunjucks.configure({ autoescape: false });
}

validate(template: string): boolean {
validate(template: string, isYaml=false): boolean {
try {
nunjucks.renderString(template, {});
const fakeContent = nunjucks.renderString(template, FAKE_RENDER_CONTEXT);
if (isYaml) {
const {id, created} = FAKE_RENDER_CONTEXT;
const fakeMetadata = `raindrop_id: ${id}\nraindrop_last_update: ${created}\n${fakeContent}`
parseYaml(fakeMetadata);
}
return true;
} catch (error) {
return false;
}
}

renderContent(bookmark: RaindropBookmark, newArticle = true) {
renderContent(bookmark: RaindropBookmark, newArticle: boolean) {
return this.renderTemplate(this.plugin.settings.template, bookmark, newArticle);
}

renderFrontmatter(bookmark: RaindropBookmark, newArticle: boolean) {
const newMdFrontmatter = this.renderTemplate(this.plugin.settings.metadataTemplate, bookmark, newArticle);
let frontmatter: BookmarkFileFrontMatter = {
raindrop_id: bookmark.id,
raindrop_last_update: (new Date()).toISOString(),
};
try {
frontmatter = {
...frontmatter,
...parseYaml(newMdFrontmatter),
};
} catch (e) {
console.error(e);
new Notice(`Failed to parse YAML for ${bookmark.title}: ${e.message}`)
}
return stringifyYaml(frontmatter);
}

renderFullArticle(bookmark: RaindropBookmark) {
const newMdContent = this.renderContent(bookmark, true);
const newMdFrontmatter = this.renderFrontmatter(bookmark, true);
const mdContent = `---\n${newMdFrontmatter}---\n${newMdContent}`;
return mdContent;
}

private renderTemplate(template:string, bookmark: RaindropBookmark, newArticle: boolean) {
const dateTimeFormat = this.plugin.settings.dateTimeFormat;

const renderHighlights: RenderHighlight[] = bookmark.highlights.map((hl) => {
Expand All @@ -64,7 +124,7 @@ export default class Renderer {
return renderHighlight;
});

// sync() should keep the latest collection data in local in the beginning
// the latest collection data is sync from Raindrop at the beginning of `sync` function
const renderCollection: RenderCollection = {
title: this.plugin.settings.syncCollections[bookmark.collectionId].title,
}
Expand All @@ -83,20 +143,8 @@ export default class Renderer {
type: bookmark.type,
important: bookmark.important,
};

const template = this.plugin.settings.template;

const content = nunjucks.renderString(template, context);
return content;
}

renderFullPost(bookmark: RaindropBookmark) {
const newMdContent = this.renderContent(bookmark, true);
const frontmatter: BookmarkFileFrontMatter = {
raindrop_id: bookmark.id,
raindrop_last_update: (new Date()).toISOString(),
};
const frontmatterStr = stringifyYaml(frontmatter);
const mdContent = `---\n${frontmatterStr}---\n${newMdContent}`;
return mdContent;
}
}
35 changes: 33 additions & 2 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {App, Notice, PluginSettingTab, Setting} from 'obsidian';
import DEFAULT_METADATA_TEMPLATE from './assets/defaultMetadataTemplate.njk';
import templateInstructions from './templates/templateInstructions.html';
import metadataTemplateInstructions from './templates/metadataTemplateInstructions.html';
import datetimeInstructions from './templates/datetimeInstructions.html';
import appendModeInstructions from './templates/appendModeInstructions.html';
import type { RaindropAPI } from './api';
Expand Down Expand Up @@ -37,6 +39,7 @@ export class RaindropSettingTab extends PluginSettingTab {
this.autoSyncInterval();
this.dateFormat();
this.template();
this.metadataTemplate();
this.resetSyncHistory();
}

Expand Down Expand Up @@ -76,7 +79,7 @@ export class RaindropSettingTab extends PluginSettingTab {
.setName('Only sync bookmarks with highlights')
.addToggle((toggle) => {
return toggle
.setValue(this.plugin.settings.ribbonIcon)
.setValue(this.plugin.settings.onlyBookmarksWithHl)
.onChange(async (value) => {
this.plugin.settings.onlyBookmarksWithHl = value;
await this.plugin.saveSettings();
Expand Down Expand Up @@ -204,7 +207,7 @@ export class RaindropSettingTab extends PluginSettingTab {
.createContextualFragment(templateInstructions);

new Setting(this.containerEl)
.setName('Highlights template')
.setName('Content template')
.setDesc(templateDescFragment)
.addTextArea((text) => {
text.inputEl.style.width = '100%';
Expand All @@ -224,6 +227,34 @@ export class RaindropSettingTab extends PluginSettingTab {
return text;
});
}
private async metadataTemplate(): Promise<void> {
const templateDescFragment = document
.createRange()
.createContextualFragment(metadataTemplateInstructions);

new Setting(this.containerEl)
.setName('Metadata template')
.setDesc(templateDescFragment)
.addTextArea((text) => {
text.inputEl.style.width = '100%';
text.inputEl.style.height = '250px';
text.inputEl.style.fontSize = '0.8em';
text.setPlaceholder(DEFAULT_METADATA_TEMPLATE);
text.setValue(this.plugin.settings.metadataTemplate)
.onChange(async (value) => {
const isValid = this.renderer.validate(value, true);

if (isValid) {
this.plugin.settings.metadataTemplate = value;
await this.plugin.saveSettings();
}

text.inputEl.style.border = isValid ? '' : '1px solid red';
});
return text;
});
}


private resetSyncHistory(): void {
new Setting(this.containerEl)
Expand Down
19 changes: 10 additions & 9 deletions src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default class RaindropSync {
async updateFileAppendMode(file: TFile, bookmark: RaindropBookmark) {
console.debug("update file append mode", file.path);
const metadata = this.app.metadataCache.getFileCache(file);

if (metadata?.frontmatter && 'raindrop_last_update' in metadata.frontmatter) {
const localLastUpdate = new Date(metadata.frontmatter.raindrop_last_update);
if (localLastUpdate >= bookmark.lastUpdate) {
Expand All @@ -109,36 +110,36 @@ export default class RaindropSync {
});
}

const newMdContent = this.renderer.renderContent(bookmark, false);
await this.app.vault.append(file, newMdContent);
const appendedContent = this.renderer.renderContent(bookmark, false);

// update frontmatter
await this.app.vault.append(file, appendedContent);

// update raindrop_last_update
if (metadata?.frontmatter) {
// separate content and front matter
const fileContent = await this.app.vault.cachedRead(file);
const {position: {start, end}} = metadata.frontmatter;
const fileContentObj = this.splitFrontmatterAndContent(fileContent, end.line);
const article = this.splitFrontmatterAndContent(fileContent, end.line);

// update frontmatter
const frontmatterObj: BookmarkFileFrontMatter = parseYaml(fileContentObj.frontmatter);
const frontmatterObj: BookmarkFileFrontMatter = parseYaml(article.frontmatter);
frontmatterObj.raindrop_last_update = (new Date()).toISOString();

// stringify and concat
const newFrontmatter = stringifyYaml(frontmatterObj);
const newFullFileContent = `---\n${newFrontmatter}---\n${fileContentObj.content}`;
const newFullFileContent = `---\n${newFrontmatter}---\n${article.content}`;
await this.app.vault.modify(file, newFullFileContent);
}
}

async updateFileOverwriteMode(file: TFile, bookmark: RaindropBookmark) {
console.debug("update file overwrite mode", file.path);
const mdContent = this.renderer.renderFullPost(bookmark);
const mdContent = this.renderer.renderFullArticle(bookmark);
return this.app.vault.modify(file, mdContent);
}

async createFile(filePath: string, bookmark: RaindropBookmark): Promise<TFile> {
console.debug("create file", filePath);
const mdContent = this.renderer.renderFullPost(bookmark);
const mdContent = this.renderer.renderFullArticle(bookmark);
return this.app.vault.create(filePath, mdContent);
}

Expand Down
12 changes: 12 additions & 0 deletions src/templates/metadataTemplateInstructions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Metadata template (<a href="https://mozilla.github.io/nunjucks/">Nunjucks</a>) for
rendering every synced Raindrop.io highlights & annotations.

<p>
Some notes:
</p>
<ul>
<li>The rendered result is placed in the front matter of the generated post.</li>
<li>If the rendered result does not follow the YAML syntax, the plugin will reject the update.</li>
<li><code>raindrop_id</code> and <code>raindrop_last_update</code> properties are transparently added by the plugin.</li>
<li>Available variables to use are the same as the previous template.</li>
</ul>
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface RaindropPluginSettings {
highlightsFolder: string;
syncCollections: SyncCollectionSettings;
template: string;
metadataTemplate: string;
dateTimeFormat: string;
autoSyncInterval: number;
}
3 changes: 2 additions & 1 deletion versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
"0.0.10": "0.14.0",
"0.0.11": "0.14.0",
"0.0.12": "0.14.0",
"0.0.13": "0.14.0"
"0.0.13": "0.14.0",
"0.0.14": "0.14.0"
}

0 comments on commit caf6a3b

Please sign in to comment.