Skip to content

Commit

Permalink
feat: add export logic (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
bingryan authored Mar 6, 2023
1 parent 7be3a42 commit 0a683e6
Show file tree
Hide file tree
Showing 13 changed files with 288 additions and 103 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pnpm run release
pnpm run version
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Obsidian ibook Plugin(WIP)
# Obsidian ibook Plugin
2 changes: 1 addition & 1 deletion esbuild.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const context = await esbuild.context({
banner: {
js: banner,
},
entryPoints: ["src/main.ts"],
entryPoints: ["src/plugin.ts"],
bundle: true,
external: [
"obsidian",
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"
},
"dependencies": {
"handlebars": "^4.7.7"
}
}
43 changes: 41 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 21 additions & 19 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LibraryAsset, Annotation } from "./types";
import { IBOOK_LIBRARY, IBOOK_ANNOTATION } from "./config"
import { sqlite3 } from './utils';
import { LibraryAsset, Annotation, AnnotationAssetId, LibraryAssetId } from "@/types";
import { IBOOK_LIBRARY, IBOOK_ANNOTATION } from "@/config"
import { sqlite3 } from '@/utils';


export async function getAllBook(): Promise<LibraryAsset[]> {
Expand All @@ -12,42 +12,44 @@ export async function getAllBook(): Promise<LibraryAsset[]> {
return await sqlite3<LibraryAsset[]>(sql, IBOOK_LIBRARY);
}

export async function getAllBookId(): Promise<string[]> {
export async function getAllBookId(): Promise<LibraryAssetId[]> {
const sql = `
SELECT
ZASSETID
DISTINCT ZASSETID
FROM ZBKLIBRARYASSET
`
return await sqlite3<string[]>(sql, IBOOK_LIBRARY);
return await sqlite3<LibraryAssetId[]>(sql, IBOOK_LIBRARY);
}

export async function getBookById(assetId: string): Promise<LibraryAsset> {
export async function getBookById(assetId: string): Promise<LibraryAsset[]> {
const sql = `
SELECT
*
FROM ZBKLIBRARYASSET
WHERE ZASSETID == "${assetId}"
WHERE ZASSETID == '${assetId}'
`
return await sqlite3<LibraryAsset>(sql, IBOOK_LIBRARY);
return await sqlite3<LibraryAsset[]>(sql, IBOOK_LIBRARY);
}

export async function getAllAnnotionBookId(): Promise<string[]> {
export async function getAllAnnotionBookId(): Promise<AnnotationAssetId[]> {
const sql = `
SELECT
ZANNOTATIONASSETID
FROM ZAEANNOTATION
`
return await sqlite3<string[]>(sql, IBOOK_ANNOTATION);
SELECT
DISTINCT ZANNOTATIONASSETID
FROM ZAEANNOTATION
WHERE ZANNOTATIONASSETID IS NOT NULL
AND ZANNOTATIONASSETID != ''
AND ZANNOTATIONLOCATION IS NOT NULL
`
return await sqlite3<AnnotationAssetId[]>(sql, IBOOK_ANNOTATION);
}

export async function getAnnotationBookId(assetId: string): Promise<Annotation> {
export async function getAnnotationBookId(assetId: string): Promise<Annotation[]> {
const sql = `
SELECT
*
FROM ZAEANNOTATION
WHERE ZANNOTATIONASSETID LIKE '${assetId}'
WHERE ZANNOTATIONASSETID == '${assetId}'
ORDER BY ZPLLOCATIONRANGESTART,ZFUTUREPROOFING6
`
return await sqlite3<Annotation>(sql, IBOOK_ANNOTATION);
return await sqlite3<Annotation[]>(sql, IBOOK_ANNOTATION);
}
37 changes: 33 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,41 @@ export const IBOOK_LIBRARY = '~/Library/Containers/com.apple.iBooksX/Data/Docume
export const IBOOK_ANNOTATION = '~/Library/Containers/com.apple.iBooksX/Data/Documents/AEAnnotation/AEAnnotation_v10312011_1727_local.sqlite'
export const IBOOK_RECENTLY = '~/Library/Containers/com.apple.iBooksX/Data/Documents/BCRecentlyOpenedBooksDB/BCRecentlyOpenedBooksDB.sqlite'
export const IBOOK_SERIES = '~/Library/Containers/com.apple.iBooksX/Data/Documents/BKSeriesDatabase/BKSeries-1-012820141020.sqlite'
export const IBOOK_SNAPSHOTS = '/Users/legotime/Library/Containers/com.apple.iBooksX/Data/Documents/BKSnapshotManager/BookSnapshots.sqlite'
export const IBOOK_SNAPSHOTS = '~/Library/Containers/com.apple.iBooksX/Data/Documents/BKSnapshotManager/BookSnapshots.sqlite'
export interface IbookPluginSettings {
mySetting: string;
output: string;
template: string;
}

const defaultTemplate = `
---
tags:
- ibook/
---
# 📔 Book: {{library.ZSORTTITLE}}
Author:: {{library.ZAUTHOR}}
LANGUAGE:: {{library.ZLANGUAGE}}
Book Path:: {{library.ZPATH}}
---
# 🔍 How I Discovered IT
{{#each annotation}}
{{#if this.ZFUTUREPROOFING5}}
- {{this.ZFUTUREPROOFING5}}
{{/if}}
{{#if this.ZANNOTATIONSELECTEDTEXT}}
- {{this.ZANNOTATIONSELECTEDTEXT}}
{{/if}}
{{#if this.ZANNOTATIONNOTE}}
- {{this.ZANNOTATIONNOTE}}
{{/if}}
{{/each}}
`

export const DEFAULT_SETTINGS: IbookPluginSettings = {
mySetting: 'default'
output: 'ibook',
template: defaultTemplate
};

61 changes: 61 additions & 0 deletions src/export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { getAllBookId, getBookById, getAnnotationBookId } from "@/api";
import { IbookPluginSettings } from '@/config';
import { Renderer } from '@/renderer';
import IbookPlugin from '@/plugin'
import * as path from "path";
export interface IExport {
start(): void;
}

export class IBookExport implements IExport {
private settings: IbookPluginSettings;
private renderer: Renderer;
public plugin: IbookPlugin;
constructor(settings: IbookPluginSettings, plugin: IbookPlugin) {
this.settings = settings;
this.renderer = new Renderer(this.settings);
this.plugin = plugin;
}

/**
* During the develop, the following problems will be found
1. ZAEANNOTATION has data, but ZBKLIBRARYASSET has no book information
*/
async start() {
const getBookId = await getAllBookId();

if (getBookId.length > 0) {
for (let i = 0; i < getBookId.length; i++) {
const renderData = await this.getRenderDataById(getBookId[i].ZASSETID);

if (renderData.annotation.length === 0 || renderData.library.ZTITLE === null) {
continue;
}
const content = this.renderer.render(renderData);
this.save(renderData.library.ZTITLE, content);
}
}
}

async getRenderDataById(bookId: string) {
const library = await getBookById(bookId);
const annotation = await getAnnotationBookId(bookId);
return { "library": library[0], "annotation": annotation }
}


save(contentName: string, content: string) {
try {
this.plugin.app.vault.create(
path.join(this.plugin.settings.output, `${contentName}.md`),
content
);
} catch (error) {
if (!error.message.contains("file already exists")) {
throw error;
}
}

}
}
39 changes: 16 additions & 23 deletions src/main.ts → src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@

import {
App,
Editor,
MarkdownView,
Plugin,
PluginSettingTab,
Setting,
} from "obsidian";

import { IbookPluginSettings, DEFAULT_SETTINGS } from "./config";
import { getAllBook,getAllAnnotionBookId,getAnnotationBookId } from "./api";
import { IbookPluginSettings, DEFAULT_SETTINGS } from "@/config";
import { IExport, IBookExport } from "@/export";
import { tryCreateFolder } from "@/utils";



export default class IbookPlugin extends Plugin {
settings: IbookPluginSettings;
export: IExport;

async onload() {
await this.loadSettings();
await tryCreateFolder(
this,
this.settings.output,
);

// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new IbookSettingTab(this.app, this));
this.export = new IBookExport(this.settings, this);

const res = await getAllBook();
const idList = await getAllAnnotionBookId();

console.log("ibook:", res);
console.log("ibook id list:", idList);

const annotation = await getAnnotationBookId("3FB4A96BF9A00F2589847EB9DD23674F");
console.log("annotation:", annotation);


// This adds an editor command that can perform some operation on the current editor instance
this.addCommand({
id: "sample-editor-command",
name: "Sample editor command",
editorCallback: (editor: Editor, view: MarkdownView) => {
console.log(editor.getSelection());
editor.replaceSelection("Sample Editor Command");
},
id: 'Ibook-export-command',
name: 'IBook export',
callback: () => {
this.export.start();
}
});
}

Expand Down Expand Up @@ -80,10 +73,10 @@ class IbookSettingTab extends PluginSettingTab {
.addText((text) =>
text
.setPlaceholder("Enter your secret")
.setValue(this.plugin.settings.mySetting)
.setValue(this.plugin.settings.output)
.onChange(async (value) => {
console.log("Secret: " + value);
this.plugin.settings.mySetting = value;
this.plugin.settings.output = value;
await this.plugin.saveSettings();
})
);
Expand Down
17 changes: 17 additions & 0 deletions src/renderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as Handlebars from 'handlebars';
import { IbookPluginSettings } from '@/config';
import { RendererData } from '@/types';

export class Renderer {
private settings: IbookPluginSettings;

constructor(settings: IbookPluginSettings) {
this.settings = settings;
}

public render(data: RendererData) {
const source = this.settings.template;
const template = Handlebars.compile(source);
return template(data);
}
}
Loading

0 comments on commit 0a683e6

Please sign in to comment.