Skip to content

Commit

Permalink
Merge pull request #4 from takker99/make-apkg
Browse files Browse the repository at this point in the history
✨ Make Anki packages
  • Loading branch information
takker99 committed Feb 26, 2023
2 parents a3f52c0 + 7c21e6e commit 4786f47
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 3 deletions.
2 changes: 1 addition & 1 deletion deps/deno-anki.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "https://raw.githubusercontent.com/takker99/deno-anki/0.0.2/mod.ts";
export * from "https://raw.githubusercontent.com/takker99/deno-anki/0.0.3/mod.ts";
1 change: 1 addition & 0 deletions deps/jsZip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { default as JSZip } from "https://esm.sh/jszip@3.9.1";
4 changes: 2 additions & 2 deletions deps/scrapbox.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.19.0/rest/mod.ts";
export * from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.19.0/title.ts";
export * from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.19.2/rest/mod.ts";
export * from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.19.2/title.ts";
export * from "https://raw.githubusercontent.com/scrapbox-jp/types/0.3.8/rest.ts";
1 change: 1 addition & 0 deletions deps/sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { SqlJsStatic } from "https://esm.sh/sql.js@1.8.0";
136 changes: 136 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import {
getTable,
NotFoundError,
NotLoggedInError,
NotMemberError,
Page,
Result,
} from "./deps/scrapbox.ts";
import {
Deck,
makeCollection,
makePackage,
NoteType,
} from "./deps/deno-anki.ts";
import { JSZip } from "./deps/jsZip.ts";
import { SqlJsStatic } from "./deps/sql.ts";
import { parseNotes, Path } from "./note.ts";
import { InvalidDeckError, parseDeck } from "./deck.ts";
import { InvalidNoteTypeError, parseNoteType } from "./noteType.ts";

/** 既定のdeck */
const defaultDeck: Deck = {
name: "default",
id: 1,
};

/** 既定のNote type */
// @ts-ignore NoteTypeしか帰ってこないはず
const defaultNoteType: NoteType = parseNoteType(`name,Basic (Cloze)
id,1677417085373
isCloze,true`).value;

type DeckResult = Result<
Deck,
InvalidDeckError | NotFoundError | NotLoggedInError | NotMemberError
>;

/** 読み込んだdecksのcache
*
* Promiseを入れることで、重複読み込みを避ける
*/
const decks = new Map<Key, Promise<DeckResult>>();

/** 指定されたdeckをcacheから読み込む
*
* cacheになければfetchする
*
* `path`が`undefined`のときはdefaultのdeckを返す
*/
const getDeck = (path: Path | undefined): Promise<DeckResult> => {
if (!path) return Promise.resolve({ ok: true, value: defaultDeck });
const deck = decks.get(toKey(path));
// すでにfetch中のがあれば、それを待つ
if (deck) return deck;

const promise = (async () => {
const result = await getTable(path.project, path.title, "deck");
if (!result.ok) return result;
return parseDeck(result.value);
})();
decks.set(toKey(path), promise);
return promise;
};

type NoteTypeResult = Result<
NoteType,
InvalidNoteTypeError | NotFoundError | NotLoggedInError | NotMemberError
>;

/** 読み込んだnote typesのcache
*
* Promiseを入れることで、重複読み込みを避ける
*/
const noteTypes = new Map<Key, Promise<NoteTypeResult>>();

/** 指定されたnote typeをcacheから読み込む
*
* cacheになければfetchする
*/
const getNoteType = (path: Path | undefined): Promise<NoteTypeResult> => {
if (!path) return Promise.resolve({ ok: true, value: defaultNoteType });
const noteType = noteTypes.get(toKey(path));
// すでにfetch中のがあれば、それを待つ
if (noteType) return noteType;

const promise = (async () => {
const result = await getTable(path.project, path.title, "note type");
if (!result.ok) return result;
return parseNoteType(result.value);
})();
noteTypes.set(toKey(path), promise);
return promise;
};

export interface MakeApkgInit {
jsZip: typeof JSZip;
sql: SqlJsStatic;
}

export const makeApkg = async (
project: string,
pages: Page[],
init: MakeApkgInit,
): Promise<{ ok: true; value: Blob }> => {
const notes = (await Promise.all(pages.map(async (page) => {
const { deckRef, noteTypeRef, notes: notes_ } = parseNotes(
project,
page.title,
page.lines,
);

const deckRes = await getDeck(deckRef);
if (!deckRes.ok) {
console.warn(`${deckRes.value.name} ${deckRes.value.message}`);
}
const deck = deckRes.ok ? deckRes.value : defaultDeck;
const noteTypeRes = await getNoteType(noteTypeRef);
if (!noteTypeRes.ok) {
console.warn(`${noteTypeRes.value.name} ${noteTypeRes.value.message}`);
}
const noteType = noteTypeRes.ok ? noteTypeRes.value : defaultNoteType;
return notes_.map((note) => ({ deck, noteType, ...note }));
}))).flat();

return {
ok: true,
value: await makePackage(
makeCollection(notes, init.sql),
{},
init.jsZip,
),
};
};

type Key = `/${string}/${string}`;
const toKey = (path: Path): Key => `/${path.project}/${path.title}`;

0 comments on commit 4786f47

Please sign in to comment.