Skip to content

Commit

Permalink
refactor(core): split functionality for better testability
Browse files Browse the repository at this point in the history
  • Loading branch information
bandantonio committed May 4, 2024
1 parent 2e1d747 commit a76650d
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 76 deletions.
53 changes: 8 additions & 45 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { normalizePath, Notice, Plugin } from 'obsidian';
import path from 'path';
import { DEFAULT_SETTINGS, IBookHighlightsSettingTab } from './src/settings';
import { Notice, Plugin } from 'obsidian';
import { IBookHighlightsPluginSearchModal } from './src/search';
import {
ICombinedBooksAndHighlights,
IBookHighlightsPluginSettings
} from './src/types';
import { aggregateBookAndHighlightDetails } from './src/methods/aggregateDetails';
import { renderHighlightsTemplate } from './src/methods/renderHighlightsTemplate';
import SaveHighlights from './src/methods/saveHighlightsToVault';
import { AppleBooksHighlightsImportPluginSettings, IBookHighlightsSettingTab } from './src/settings';

export default class IBookHighlightsPlugin extends Plugin {
settings: IBookHighlightsPluginSettings;
settings: AppleBooksHighlightsImportPluginSettings;
saveHighlights: SaveHighlights;

async onload() {
const settings = await this.loadSettings();
this.saveHighlights = new SaveHighlights(this.app, settings);

if (settings.importOnStart) {
await this.aggregateAndSaveHighlights();
Expand All @@ -25,7 +22,6 @@ export default class IBookHighlightsPlugin extends Plugin {
}).catch((error) => {
new Notice(`[${this.manifest.name}]:\nError importing highlights. Check console for details (⌥ ⌘ I)`, 0);
console.error(`[${this.manifest.name}]: ${error}`);

});
});

Expand Down Expand Up @@ -62,7 +58,7 @@ export default class IBookHighlightsPlugin extends Plugin {
onunload() { }

async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
this.settings = Object.assign(new AppleBooksHighlightsImportPluginSettings(), await this.loadData());

return this.settings;
}
Expand All @@ -78,39 +74,6 @@ export default class IBookHighlightsPlugin extends Plugin {
throw ('No highlights found. Make sure you made some highlights in your Apple Books.');
}

await this.saveHighlightsToVault(highlights);
}

async saveHighlightsToVault(highlights: ICombinedBooksAndHighlights[]) {
const highlightsFolderPath = this.app.vault.getAbstractFileByPath(this.settings.highlightsFolder);
const isBackupEnabled = this.settings.backup;

// Backup highlights folder if backup is enabled
if (highlightsFolderPath) {
if (isBackupEnabled) {
const highlightsFilesToBackup = (await this.app.vault.adapter.list(highlightsFolderPath.path)).files;
const highlightsBackupFolder = `${this.settings.highlightsFolder}-bk-${Date.now()}`;

await this.app.vault.createFolder(highlightsBackupFolder);

highlightsFilesToBackup.forEach(async (file: string) => {
const fileName = path.basename(file);
await this.app.vault.adapter.copy(normalizePath(file), normalizePath(path.join(highlightsBackupFolder, fileName)));
});
}
await this.app.vault.delete(highlightsFolderPath, true);
}

await this.app.vault.createFolder(this.settings.highlightsFolder);


highlights.forEach(async (highlight: ICombinedBooksAndHighlights) => {
const renderedTemplate = await renderHighlightsTemplate(highlight, this.settings.template);

await this.app.vault.create(
normalizePath(path.join(this.settings.highlightsFolder, `${highlight.bookTitle}.md`)),
renderedTemplate
);
});
await this.saveHighlights.saveHighlightsToVault(highlights);
}
}
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
"type": "git",
"url": "git+https://github.com/bandantonio/obsidian-apple-books-highlights-plugin.git"
},
"engines": {
"node": ">=20.8.0",
"npm": ">=10.0.0"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.10",
"@types/node": "^18.4.1",
Expand Down
8 changes: 4 additions & 4 deletions src/db/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ const db = drizzle(sqlite);
export const seedDatabase = async (table: typeof bookLibrary | typeof annotations, seed: any[]) => {

Check warning on line 8 in src/db/seed.ts

View workflow job for this annotation

GitHub Actions / ✅ Linter

Unexpected any. Specify a different type
const tableName = (table === bookLibrary) ? 'books' : 'annotations';
console.log(`Seeding ${tableName} database...`);

try {
await db.delete(table);

await db.insert(table).values(seed);
} catch (error) {
console.error(error);
process.exit(1);
}

console.log(`Seeding ${tableName} successful`);

};
56 changes: 56 additions & 0 deletions src/methods/saveHighlightsToVault.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { App, Vault } from 'obsidian';
import path from 'path';
import { ICombinedBooksAndHighlights } from '../types';
import { AppleBooksHighlightsImportPluginSettings } from '../settings';
import { renderHighlightsTemplate } from './renderHighlightsTemplate';

export default class SaveHighlights {
private app: App;
private vault: Vault;
private settings: AppleBooksHighlightsImportPluginSettings;

constructor(app: App, settings: AppleBooksHighlightsImportPluginSettings) {
this.app = app;
this.vault = this.app.vault;
this.settings = settings;
}

async saveHighlightsToVault(highlights: ICombinedBooksAndHighlights[]): Promise<void> {
const highlightsFolderPath = this.vault.getAbstractFileByPath(
this.settings.highlightsFolder
);

const isBackupEnabled = this.settings.backup;

// // Backup highlights folder if backup is enabled
if (highlightsFolderPath) {
if (isBackupEnabled) {
const highlightsFilesToBackup = (await this.vault.adapter.list(highlightsFolderPath.path)).files;

const highlightsBackupFolder = `${this.settings.highlightsFolder}-bk-${Date.now()}`;

await this.vault.createFolder(highlightsBackupFolder);

highlightsFilesToBackup.forEach(async (file: string) => {
const fileName = path.basename(file);

await this.vault.adapter.copy(file, path.join(highlightsBackupFolder, fileName))
});
}

await this.vault.delete(highlightsFolderPath, true);
}

await this.vault.createFolder(this.settings.highlightsFolder);

highlights.forEach(async (highlight: ICombinedBooksAndHighlights) => {
const renderedTemplate = await renderHighlightsTemplate(highlight, this.settings.template);
const filePath = path.join(this.settings.highlightsFolder, `${highlight.bookTitle}.md`);

await this.vault.create(
filePath,
renderedTemplate
);
});
}
}
2 changes: 1 addition & 1 deletion src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export class IBookHighlightsPluginSearchModal extends IBookHighlightsPluginSugge

//eslint-disable-next-line
onChooseSuggestion(item: ICombinedBooksAndHighlights, event: MouseEvent | KeyboardEvent) {
this.plugin.saveHighlightsToVault([item]);
this.plugin.saveHighlights.saveHighlightsToVault([item]);
}
}
42 changes: 24 additions & 18 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { App, Notice, PluginSettingTab, Setting } from 'obsidian';
import IBookHighlightsPlugin from '../main';
import defaultTemplate from './template';
import { IBookHighlightsPluginSettings } from './types';

export const DEFAULT_SETTINGS: IBookHighlightsPluginSettings = {
highlightsFolder: 'ibooks-highlights',
backup: false,
importOnStart: false,
template: defaultTemplate,
export class AppleBooksHighlightsImportPluginSettings {
highlightsFolder: string = 'ibooks-highlights';

Check failure on line 6 in src/settings.ts

View workflow job for this annotation

GitHub Actions / ✅ Linter

Type string trivially inferred from a string literal, remove type annotation
backup: boolean = false;

Check failure on line 7 in src/settings.ts

View workflow job for this annotation

GitHub Actions / ✅ Linter

Type boolean trivially inferred from a boolean literal, remove type annotation
importOnStart: boolean = false;

Check failure on line 8 in src/settings.ts

View workflow job for this annotation

GitHub Actions / ✅ Linter

Type boolean trivially inferred from a boolean literal, remove type annotation
template: string = defaultTemplate;
}

class IBookHighlightsSettingTab extends PluginSettingTab {
export class IBookHighlightsSettingTab extends PluginSettingTab {
plugin: IBookHighlightsPlugin;

constructor(app: App, plugin: IBookHighlightsPlugin) {
Expand All @@ -23,16 +22,24 @@ class IBookHighlightsSettingTab extends PluginSettingTab {

containerEl.empty();

new Setting(containerEl)
const folder = new Setting(containerEl)
.setName('Highlights folder')
.setDesc('A folder (within the root of your vault) where you want to save imported highlights')
.addText(text => text
.setPlaceholder('Folder to save highlights')
.setValue(this.plugin.settings.highlightsFolder)
.onChange(async (value) => {
this.plugin.settings.highlightsFolder = value;
await this.plugin.saveSettings();
}));
.setClass('ibooks-highlights-folder')

folder.addText(text => text
.setPlaceholder('Folder to save highlights')
.setValue(this.plugin.settings.highlightsFolder)
.onChange(async (value) => {
if (!value) {
folder.controlEl.addClass('setting-error');
return;
}

folder.controlEl.removeClass('setting-error');
this.plugin.settings.highlightsFolder = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.setName('Import highlights on start')
Expand All @@ -44,7 +51,7 @@ class IBookHighlightsSettingTab extends PluginSettingTab {
await this.plugin.saveSettings();
});
});

new Setting(containerEl)
.setName('Backup highlights')
.setDesc('Backup highlights folder before import. Backup folder template: <highlights-folder>-bk-<timestamp> (For example, ibooks-highlights-bk-1704060001)')
Expand All @@ -62,7 +69,7 @@ class IBookHighlightsSettingTab extends PluginSettingTab {
new Setting(containerEl)
.setName('Template')
.setDesc('Template for highlight files')
.setClass("ibooks-highlights-template")
.setClass('ibooks-highlights-template')
.addTextArea((text) => {
text
.setPlaceholder('Template')
Expand Down Expand Up @@ -97,4 +104,3 @@ class IBookHighlightsSettingTab extends PluginSettingTab {
}
}

export { IBookHighlightsSettingTab }
7 changes: 0 additions & 7 deletions src/types/index.ts → src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
export interface IBookHighlightsPluginSettings {
highlightsFolder: string;
template: string;
backup: boolean;
importOnStart: boolean;
}

export interface IBook {
ZASSETID: string;
ZTITLE: string;
Expand Down
6 changes: 5 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
width: 100%;
height: 350px;
overflow: auto;
}
}

.ibooks-highlights-folder > .setting-item-control.setting-error > input {
border-color: #b00;
}

0 comments on commit a76650d

Please sign in to comment.