Skip to content

Commit

Permalink
Add support for templating (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
OGKevin authored Sep 15, 2022
1 parent c2cc73c commit ec1f627
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 18 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

This plugin aims to make highlight import from Kobo devices easier.

- [Obsidian Kobo Highlight Importer](#obsidian-kobo-highlight-importer)
- [How to use](#how-to-use)
- [Templating](#templating)
- [Examples](#examples)
- [Variables](#variables)
- [Helping Screenshots](#helping-screenshots)
- [Contributing](#contributing)

## How to use

Once installed, the steps to import your highlights directly into the vault are:
Expand All @@ -12,6 +20,30 @@ Once installed, the steps to import your highlights directly into the vault are:
4. Locate _KoboReader.sqlite_ in the _.kobo_ folder ( this folder is hidden, so if you don't see it you should enable hidden files view from system configs )
5. Extract

## Templating

The default template is:

```markdown
{{highlights}}
```

### Examples

```markdown
---
tags:
- books
---

{{highlights}}
```
### Variables

| Tag | Description | Example |
|------------|--------------------------------------------------|------------------|
| highlights | Will get replaced with the extracted highlights. | `{{highlights}}` |

## Helping Screenshots
![](./README_assets/step1.png)
![](./README_assets/step2.png)
Expand Down
4 changes: 2 additions & 2 deletions src/database/Highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class HighlightService {
fromMapToMarkdown(bookTitle: string, chapters: Map<chapter, highlight[]>): string {
let markdown = `# ${bookTitle}\n\n`;
for (const [chapter, highlights] of chapters) {
markdown += `## ${chapter}\n\n`
markdown += highlights.join('\n\n')
markdown += `## ${chapter.trim()}\n\n`
markdown += highlights.join('\n\n').trim()
markdown += `\n\n`
}

Expand Down
1 change: 0 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,3 @@ export default class KoboHighlightsImporter extends Plugin {
await this.saveData(this.settings);
}
}

9 changes: 8 additions & 1 deletion src/modal/ExtractHighlightsModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { binary } from "src/binaries/sql-wasm";
import { HighlightService } from "src/database/Highlight";
import { Repository } from "src/database/repository";
import { KoboHighlightsImporterSettings } from "src/settings/Settings";
import { applyTemplateTransformations } from 'src/template/template';
import { getTemplateContents } from 'src/template/templateContents';

export class ExtractHighlightsModal extends Modal {
goButtonEl!: HTMLButtonElement;
Expand Down Expand Up @@ -44,11 +46,16 @@ export class ExtractHighlightsModal extends Modal {
this.settings.dateFormat,
)

const template = await getTemplateContents(this.app, this.settings.templatePath)

for (const [bookTitle, chapters] of content) {
const markdown = service.fromMapToMarkdown(bookTitle, chapters)
const saniizedBookName = sanitize(bookTitle)
const fileName = normalizePath(`${this.settings.storageFolder}/${saniizedBookName}.md`)
this.app.vault.adapter.write(fileName, markdown)
this.app.vault.adapter.write(
fileName,
applyTemplateTransformations(template, markdown)
)
}
}

Expand Down
47 changes: 33 additions & 14 deletions src/settings/Settings.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,62 @@
import { App, PluginSettingTab, Setting } from "obsidian";
import KoboHighlightsImporter from "src/main";
import { FileSuggestor } from "./suggestors/FileSuggestor";
import { FolderSuggestor } from "./suggestors/FolderSuggestor";

export const DEFAULT_SETTINGS: KoboHighlightsImporterSettings = {
storageFolder: '',
storageFolder: '',
includeCreatedDate: false,
dateFormat: "YYYY-MM-DD"
dateFormat: "YYYY-MM-DD",
templatePath: "",
}

export interface KoboHighlightsImporterSettings {
storageFolder: string;
storageFolder: string;
includeCreatedDate: boolean;
dateFormat: string;
templatePath: string;
}

export class KoboHighlightsImporterSettingsTab extends PluginSettingTab {
constructor(public app: App, private plugin: KoboHighlightsImporter) {
super(app, plugin);
}
constructor(public app: App, private plugin: KoboHighlightsImporter) {
super(app, plugin);
}

display(): void {
this.containerEl.empty();
display(): void {
this.containerEl.empty();
this.containerEl.createEl('h2', { text: this.plugin.manifest.name });

this.add_destination_folder();
this.add_enable_creation_date();
this.add_date_fromat();
}
this.add_temaplte_path();
}

add_destination_folder(): void {
new Setting(this.containerEl)
.setName('Destination folder')
.setDesc('Where to save your imported highlights')
.addSearch((cb) => {
.setName('Destination folder')
.setDesc('Where to save your imported highlights')
.addSearch((cb) => {
new FolderSuggestor(this.app, cb.inputEl);
cb.setPlaceholder("Example: folder1/folder2")
.setValue(this.plugin.settings.storageFolder)
.onChange((new_folder) => {
this.plugin.settings.storageFolder = new_folder;
.onChange((newFolder) => {
this.plugin.settings.storageFolder = newFolder;
this.plugin.saveSettings();
});
});
}

add_temaplte_path(): void {
new Setting(this.containerEl)
.setName('Tempalte Path')
.setDesc('Which tempalte to use for extracted highlights')
.addSearch((cb) => {
new FileSuggestor(this.app, cb.inputEl);
cb.setPlaceholder("Example: folder1/template")
.setValue(this.plugin.settings.templatePath)
.onChange((newTemplatePath) => {
this.plugin.settings.templatePath = newTemplatePath;
this.plugin.saveSettings();
});
});
Expand Down
34 changes: 34 additions & 0 deletions src/settings/suggestors/FileSuggestor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// source: https://github.com/liamcain/obsidian-periodic-notes/blob/04965a1e03932d804f6dd42c2e5dba0ede010d79/src/ui/file-suggest.ts

import { TAbstractFile, TFile } from "obsidian";
import { TextInputSuggest } from "./Suggest";

export class FileSuggestor extends TextInputSuggest<TFile> {
getSuggestions(inputStr: string): TFile[] {
const abstractFiles = this.app.vault.getAllLoadedFiles();
const files: TFile[] = [];
const lowerCaseInputStr = inputStr.toLowerCase();

abstractFiles.forEach((file: TAbstractFile) => {
if (
file instanceof TFile &&
file.extension === "md" &&
file.path.toLowerCase().contains(lowerCaseInputStr)
) {
files.push(file);
}
});

return files;
}

renderSuggestion(file: TFile, el: HTMLElement): void {
el.setText(file.path);
}

selectSuggestion(file: TFile): void {
this.inputEl.value = file.path;
this.inputEl.trigger("input");
this.close();
}
}
43 changes: 43 additions & 0 deletions src/template/template.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as chai from 'chai';
import { applyTemplateTransformations, defaultTemplate } from './template';


describe('template', async function () {
it('applyTemplateTransformations default', async function () {
const content = applyTemplateTransformations(defaultTemplate, "test")

chai.expect(content).deep.eq("test")
});

const templates = new Map<string, string[]>([
[
"default",
[defaultTemplate, "test"]
],
[
"with front matter",
[
`
---
tag: [tags]
---
{{highlights}}
`,
`---
tag: [tags]
---
test`
]
],
])

for (const [title, t] of templates) {
it(`applyTemplateTransformations ${title}`, async function () {
const content = applyTemplateTransformations(t[0], "test")

chai.expect(content).deep.eq(t[1])
});
}


});
10 changes: 10 additions & 0 deletions src/template/template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const defaultTemplate = `
{{highlights}}
`

export function applyTemplateTransformations(rawTemaple: string, highlights: string): string {
return rawTemaple.replace(
/{{\s*highlights\s*}}/gi,
highlights,
).trim()
}
28 changes: 28 additions & 0 deletions src/template/templateContents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Inspired by https://github.com/liamcain/obsidian-periodic-notes/blob/04965a1e03932d804f6dd42c2e5dba0ede010d79/src/utils.ts

import { App, normalizePath, Notice } from "obsidian";
import { defaultTemplate } from "./template";

export async function getTemplateContents(
app: App,
templatePath: string | undefined
): Promise<string> {
const { metadataCache, vault } = app;
const normalizedTemplatePath = normalizePath(templatePath ?? "");
if (normalizedTemplatePath === "/") {
return defaultTemplate;
}

try {
const templateFile = metadataCache.getFirstLinkpathDest(normalizedTemplatePath, "");
return templateFile ? vault.cachedRead(templateFile) : defaultTemplate;
} catch (err) {
console.error(
`Failed to read the kobo highlight exporter template '${normalizedTemplatePath}'`,
err
);
new Notice("Failed to read the kobo highlight exporter template");

return "";
}
}

0 comments on commit ec1f627

Please sign in to comment.