diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ac6046..8b43bb7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,3 +28,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | pnpm run release + pnpm run version diff --git a/README.md b/README.md index 858b072..1101819 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# Obsidian ibook Plugin(WIP) +# Obsidian ibook Plugin diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 859fa6e..dec1f29 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -15,7 +15,7 @@ const context = await esbuild.context({ banner: { js: banner, }, - entryPoints: ["src/main.ts"], + entryPoints: ["src/plugin.ts"], bundle: true, external: [ "obsidian", diff --git a/package.json b/package.json index acbb415..6d54f7d 100644 --- a/package.json +++ b/package.json @@ -31,5 +31,8 @@ "obsidian": "latest", "tslib": "2.4.0", "typescript": "4.7.4" + }, + "dependencies": { + "handlebars": "^4.7.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52f1217..590aca5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,10 +9,14 @@ specifiers: builtin-modules: 3.3.0 esbuild: 0.17.3 eslint: ^8.35.0 + handlebars: ^4.7.7 obsidian: latest tslib: 2.4.0 typescript: 4.7.4 +dependencies: + handlebars: registry.npmmirror.com/handlebars/4.7.7 + devDependencies: '@types/node': registry.npmmirror.com/@types/node/16.18.14 '@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.29.0_jwx5cc4si27vroeurmigvyu3du @@ -1967,6 +1971,21 @@ packages: version: 1.0.4 dev: true + registry.npmmirror.com/handlebars/4.7.7: + resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/handlebars/-/handlebars-4.7.7.tgz} + name: handlebars + version: 4.7.7 + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: registry.npmmirror.com/minimist/1.2.8 + neo-async: registry.npmmirror.com/neo-async/2.6.2 + source-map: registry.npmmirror.com/source-map/0.6.1 + wordwrap: registry.npmmirror.com/wordwrap/1.0.0 + optionalDependencies: + uglify-js: registry.npmmirror.com/uglify-js/3.17.4 + dev: false + registry.npmmirror.com/has-flag/3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz} name: has-flag @@ -2345,7 +2364,6 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz} name: minimist version: 1.2.8 - dev: true registry.npmmirror.com/module-alias/2.2.2: resolution: {integrity: sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/module-alias/-/module-alias-2.2.2.tgz} @@ -2371,6 +2389,12 @@ packages: version: 1.4.0 dev: true + registry.npmmirror.com/neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz} + name: neo-async + version: 2.6.2 + dev: false + registry.npmmirror.com/nested-error-stacks/2.0.1: resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz} name: nested-error-stacks @@ -2859,7 +2883,6 @@ packages: name: source-map version: 0.6.1 engines: {node: '>=0.10.0'} - dev: true registry.npmmirror.com/string_decoder/1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz} @@ -3151,6 +3174,16 @@ packages: engines: {node: '>=8'} dev: true + registry.npmmirror.com/uglify-js/3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/uglify-js/-/uglify-js-3.17.4.tgz} + name: uglify-js + version: 3.17.4 + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + registry.npmmirror.com/universal-user-agent/6.0.0: resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz} name: universal-user-agent @@ -3224,6 +3257,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + registry.npmmirror.com/wordwrap/1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wordwrap/-/wordwrap-1.0.0.tgz} + name: wordwrap + version: 1.0.0 + dev: false + registry.npmmirror.com/wordwrapjs/4.0.1: resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz} name: wordwrapjs diff --git a/src/api.ts b/src/api.ts index 5663578..98ab4ca 100644 --- a/src/api.ts +++ b/src/api.ts @@ -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 { @@ -12,42 +12,44 @@ export async function getAllBook(): Promise { return await sqlite3(sql, IBOOK_LIBRARY); } -export async function getAllBookId(): Promise { +export async function getAllBookId(): Promise { const sql = ` SELECT - ZASSETID + DISTINCT ZASSETID FROM ZBKLIBRARYASSET ` - return await sqlite3(sql, IBOOK_LIBRARY); + return await sqlite3(sql, IBOOK_LIBRARY); } -export async function getBookById(assetId: string): Promise { +export async function getBookById(assetId: string): Promise { const sql = ` SELECT * FROM ZBKLIBRARYASSET - WHERE ZASSETID == "${assetId}" + WHERE ZASSETID == '${assetId}' ` - return await sqlite3(sql, IBOOK_LIBRARY); + return await sqlite3(sql, IBOOK_LIBRARY); } -export async function getAllAnnotionBookId(): Promise { +export async function getAllAnnotionBookId(): Promise { const sql = ` - SELECT - ZANNOTATIONASSETID - FROM ZAEANNOTATION - -` - return await sqlite3(sql, IBOOK_ANNOTATION); + SELECT + DISTINCT ZANNOTATIONASSETID + FROM ZAEANNOTATION + WHERE ZANNOTATIONASSETID IS NOT NULL + AND ZANNOTATIONASSETID != '' + AND ZANNOTATIONLOCATION IS NOT NULL + ` + return await sqlite3(sql, IBOOK_ANNOTATION); } -export async function getAnnotationBookId(assetId: string): Promise { +export async function getAnnotationBookId(assetId: string): Promise { const sql = ` SELECT * FROM ZAEANNOTATION - WHERE ZANNOTATIONASSETID LIKE '${assetId}' + WHERE ZANNOTATIONASSETID == '${assetId}' ORDER BY ZPLLOCATIONRANGESTART,ZFUTUREPROOFING6 ` - return await sqlite3(sql, IBOOK_ANNOTATION); + return await sqlite3(sql, IBOOK_ANNOTATION); } diff --git a/src/config.ts b/src/config.ts index 0006870..9e6f8d1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -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 }; - diff --git a/src/export.ts b/src/export.ts new file mode 100644 index 0000000..800c112 --- /dev/null +++ b/src/export.ts @@ -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; + } + } + + } +} diff --git a/src/main.ts b/src/plugin.ts similarity index 58% rename from src/main.ts rename to src/plugin.ts index c53e0ef..5de0f93 100644 --- a/src/main.ts +++ b/src/plugin.ts @@ -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(); + } }); } @@ -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(); }) ); diff --git a/src/renderer.ts b/src/renderer.ts new file mode 100644 index 0000000..2c15bb6 --- /dev/null +++ b/src/renderer.ts @@ -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); + } +} diff --git a/src/types.ts b/src/types.ts index ba3b368..40fc974 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,96 +1,109 @@ +export interface RendererData { + library: LibraryAsset; + annotation: Annotation[]; +} + +export interface AnnotationAssetId { + ZANNOTATIONASSETID: string; +} + +export interface LibraryAssetId { + ZASSETID: string; +} + export interface LibraryAsset { Z_PK: number; Z_ENT: number; Z_OPT: number; ZCANREDOWNLOAD: number; ZCOMBINEDSTATE: number; - ZCOMPUTEDRATING?: any; + ZCOMPUTEDRATING: string; ZCONTENTTYPE: number; ZDESKTOPSUPPORTLEVEL: number; - ZDIDRUNFORYOUENDOFBOOKEXPERIENCE?: any; + ZDIDRUNFORYOUENDOFBOOKEXPERIENCE: string; ZDIDWARNABOUTDESKTOPSUPPORT: number; ZFILESIZE: number; ZGENERATION: number; ZHASRACSUPPORT: number; ZISDEVELOPMENT: number; - ZISDOWNLOADINGSUPPLEMENTALCONTENT?: any; + ZISDOWNLOADINGSUPPLEMENTALCONTENT: string; ZISEPHEMERAL: number; - ZISEXPLICIT?: any; - ZISFINISHED?: any; + ZISEXPLICIT: string; + ZISFINISHED: string; ZISHIDDEN: number; ZISLOCKED: number; - ZISNEW?: any; + ZISNEW: string; ZISPROOF: number; ZISSAMPLE: number; - ZISSTOREAUDIOBOOK?: any; + ZISSTOREAUDIOBOOK: string; ZISSUPPLEMENTALCONTENT: number; ZISTRACKEDASRECENT: number; - ZMETADATAMIGRATIONVERSION?: any; - ZNOTFINISHED?: any; + ZMETADATAMIGRATIONVERSION: string; + ZNOTFINISHED: string; ZPAGECOUNT: number; ZRATING: number; - ZSERIESISCLOUDONLY?: any; - ZSERIESISHIDDEN?: any; - ZSERIESNEXTFLAG?: any; + ZSERIESISCLOUDONLY: string; + ZSERIESISHIDDEN: string; + ZSERIESNEXTFLAG: string; ZSERIESSORTKEY: number; ZSORTKEY: number; ZSTATE: number; ZTASTE: number; ZTASTESYNCEDTOSTORE: number; - ZLOCALONLYSERIESITEMSPARENT?: any; - ZPURCHASEDANDLOCALPARENT?: any; - ZSERIESCONTAINER?: any; - ZSUPPLEMENTALCONTENTPARENT?: any; + ZLOCALONLYSERIESITEMSPARENT: string; + ZPURCHASEDANDLOCALPARENT: string; + ZSERIESCONTAINER: string; + ZSUPPLEMENTALCONTENTPARENT: string; ZASSETDETAILSMODIFICATIONDATE: number; ZBOOKHIGHWATERMARKPROGRESS: number; - ZBOOKMARKSSERVERMAXMODIFICATIONDATE?: any; + ZBOOKMARKSSERVERMAXMODIFICATIONDATE: string; ZCREATIONDATE: number; ZDATEFINISHED: number; ZDURATION: number; - ZEXPECTEDDATE?: any; - ZFILEONDISKLASTTOUCHDATE?: any; + ZEXPECTEDDATE: string; + ZFILEONDISKLASTTOUCHDATE: string; ZLASTENGAGEDDATE: number; ZLASTOPENDATE: number; - ZLOCATIONSERVERMAXMODIFICATIONDATE?: any; + ZLOCATIONSERVERMAXMODIFICATIONDATE: string; ZMODIFICATIONDATE: number; ZPURCHASEDATE: number; ZREADINGPROGRESS: number; - ZRELEASEDATE?: any; + ZRELEASEDATE: string; ZUPDATEDATE: number; ZVERSIONNUMBER: number; - ZACCOUNTID?: any; + ZACCOUNTID: string; ZASSETGUID: string; ZASSETID: string; ZAUTHOR: string; - ZBOOKDESCRIPTION?: any; - ZBOOKMARKSSERVERVERSION?: any; - ZCOMMENTS?: any; - ZCOVERURL?: any; + ZBOOKDESCRIPTION: string; + ZBOOKMARKSSERVERVERSION: string; + ZCOMMENTS: string; + ZCOVERURL: string; ZCOVERWRITINGMODE: string; ZDATASOURCEIDENTIFIER: string; - ZDOWNLOADEDDSID?: any; + ZDOWNLOADEDDSID: string; ZEPUBID: string; - ZFAMILYID?: any; + ZFAMILYID: string; ZGENRE: string; - ZGROUPING?: any; - ZKIND?: any; + ZGROUPING: string; + ZKIND: string; ZLANGUAGE: string; - ZLOCATIONSERVERVERSION?: any; + ZLOCATIONSERVERVERSION: string; ZPAGEPROGRESSIONDIRECTION: string; ZPATH: string; - ZPERMLINK?: any; - ZPURCHASEDDSID?: any; - ZSEQUENCEDISPLAYNAME?: any; - ZSERIESID?: any; - ZSERIESSTACKIDS?: any; + ZPERMLINK: string; + ZPURCHASEDDSID: string; + ZSEQUENCEDISPLAYNAME: string; + ZSERIESID: string; + ZSERIESSTACKIDS: string; ZSORTAUTHOR: string; ZSORTTITLE: string; - ZSTOREID?: any; - ZSTOREPLAYLISTID?: any; - ZTEMPORARYASSETID?: any; + ZSTOREID: string; + ZSTOREPLAYLISTID: string; + ZTEMPORARYASSETID: string; ZTITLE: string; - ZVERSIONNUMBERHUMANREADABLE?: any; - ZYEAR?: any; + ZVERSIONNUMBERHUMANREADABLE?: string; + ZYEAR: string; } @@ -111,21 +124,21 @@ export interface Annotation { ZANNOTATIONCREATORIDENTIFIER: string; ZANNOTATIONLOCATION: string; ZANNOTATIONNOTE: string; - ZANNOTATIONREPRESENTATIVETEXT?: any; + ZANNOTATIONREPRESENTATIVETEXT: string; ZANNOTATIONSELECTEDTEXT: string; ZANNOTATIONUUID: string; - ZFUTUREPROOFING1?: any; - ZFUTUREPROOFING10?: any; + ZFUTUREPROOFING1: string; + ZFUTUREPROOFING10: string; ZFUTUREPROOFING11: string; - ZFUTUREPROOFING12?: any; - ZFUTUREPROOFING2?: any; - ZFUTUREPROOFING3?: any; - ZFUTUREPROOFING4?: any; + ZFUTUREPROOFING12: string; + ZFUTUREPROOFING2: string; + ZFUTUREPROOFING3: string; + ZFUTUREPROOFING4: string; ZFUTUREPROOFING5: string; ZFUTUREPROOFING6: string; - ZFUTUREPROOFING7?: any; - ZFUTUREPROOFING8?: any; + ZFUTUREPROOFING7: string; + ZFUTUREPROOFING8: string; ZFUTUREPROOFING9: string; - ZPLSTORAGEUUID?: any; - ZPLUSERDATA?: any; + ZPLSTORAGEUUID: string; + ZPLUSERDATA: string; } diff --git a/src/utils.ts b/src/utils.ts index 631fa65..f033fc1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,26 @@ import * as child_process from 'child_process'; import { promisify } from 'util'; +import IbookPlugin from "@/plugin"; + +/** + * create folder + * + * @param plugin + * @param path + */ +export async function tryCreateFolder( + plugin: IbookPlugin, + path: string +) { + try { + await plugin.app.vault.createFolder(path); + } catch (error) { + if (!error.message.contains("Folder already exists")) { + throw error; + } + } +} /** * Execute shell command @@ -27,5 +47,9 @@ export async function shell(cmd: string) { */ export async function sqlite3(sql: string, sqliteDBPath: string): Promise { const command = `echo "${sql}" | sqlite3 ${sqliteDBPath} -json`; - return JSON.parse(await shell(command)); + const res = await shell(command); + if (res === "") { + return JSON.parse("[]"); + } + return JSON.parse(res); } diff --git a/tsconfig.json b/tsconfig.json index 2d6fbdf..ed3c06f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,9 @@ { "compilerOptions": { "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, "inlineSourceMap": true, "inlineSources": true, "module": "ESNext",