Adds option to append ID's inline (#35)

* Adds option to append ID's inline
* Images in cards can now be stored in any folder that Obsidian recognizes
* Removed unnecessary utils functions
This commit is contained in:
Shreyas 2021-06-23 12:35:01 -07:00 committed by GitHub
parent 69b9984fd7
commit c14e58272c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 114 additions and 85 deletions

3
.gitignore vendored
View File

@ -23,3 +23,6 @@ move.sh
# Local History for Visual Studio Code
.history/
# Gtihub
.DS_Store

View File

@ -56,7 +56,7 @@ export default class ObsidianFlashcard extends Plugin {
}
private getDefaultSettings(): ISettings {
return { contextAwareMode: true, sourceSupport: false, codeHighlightSupport: false, contextSeparator: " > ", deck: "Default", flashcardsTag: "card", defaultAnkiTag: "obsidian" }
return { contextAwareMode: true, sourceSupport: false, codeHighlightSupport: false, inlineID: false, contextSeparator: " > ", deck: "Default", flashcardsTag: "card", defaultAnkiTag: "obsidian" }
}
private generateCards(activeFile: TFile) {

View File

@ -46,6 +46,6 @@ export class Inlinecard extends Card {
}
public getIdFormat(): string {
return "\n^" + this.id.toString()
return "^" + this.id.toString()
}
}

View File

@ -55,6 +55,17 @@ export class SettingsTab extends PluginSettingTab {
plugin.saveData(plugin.settings)
})
)
new Setting(containerEl)
.setName("Inline ID support")
.setDesc("Add ID to end of line for inline cards.")
.addToggle((toggle) =>
toggle
.setValue(plugin.settings.inlineID)
.onChange((value) => {
plugin.settings.inlineID = value
plugin.saveData(plugin.settings)
})
)
new Setting(containerEl)
.setName("Default deck")

View File

@ -38,7 +38,11 @@ export class Regex {
this.flashscardsWithTag = new RegExp(str, flags)
// https://regex101.com/r/Ixtzlv/1
str = "( {0,3}[#]{0,6})?(?:(?:[\\t ]*)(?:\\d.|[-+*]|#{1,6}))?(.+?) ?(:{2,3}) ?(.+?)((?: *#[\\p{Letter}-]+)+|$)(?:\\n\\^(\\d{13}))?"
if (settings.inlineID){
str = "( {0,3}[#]{0,6})?(?:(?:[\\t ]*)(?:\\d.|[-+*]|#{1,6}))?(.+?) ?(:{2,3}) ?(.+?)((?: *#[\\p{Letter}-]+)+)?(?:\\s+\\^(\\d{13})|$)"
} else {
str = "( {0,3}[#]{0,6})?(?:(?:[\\t ]*)(?:\\d.|[-+*]|#{1,6}))?(.+?) ?(:{2,3}) ?(.+?)((?: *#[\\p{Letter}-]+)+|$)(?:\\n\\^(\\d{13}))?"
}
this.cardsInlineStyle = new RegExp(str, flags)
// https://regex101.com/r/HOXF5E/1

View File

@ -3,9 +3,10 @@ import { App, FileSystemAdapter, FrontMatterCache, Notice, parseFrontMatterEntry
import { Parser } from 'src/services/parser'
import { ISettings } from 'src/settings'
import { Card } from 'src/entities/card'
import { arrayBufferToBase64 } from "src/utils"
import { arrayBufferToBase64} from "src/utils"
import { Regex } from 'src/regex'
import { noticeTimeout } from 'src/constants'
import { Inlinecard } from 'src/entities/inlinecard'
export class CardsService {
@ -43,6 +44,7 @@ export class CardsService {
this.totalOffset = 0
this.notifications = []
let filePath = activeFile.basename
let sourcePath = activeFile.path
let fileCachedMetadata = this.app.metadataCache.getFileCache(activeFile)
let vaultName = this.app.vault.getName()
let globalTags: string[] = undefined
@ -69,7 +71,7 @@ export class CardsService {
let cards: Card[] = this.parser.generateFlashcards(this.file, deckName, vaultName, filePath, globalTags)
let [cardsToCreate, cardsToUpdate] = this.filterByUpdate(ankiCards, cards)
let cardIds : number[] = this.getCardsIds(ankiCards, cards)
let cardIds: number[] = this.getCardsIds(ankiCards, cards)
let cardsToDelete: number[] = this.parser.getCardsToDelete(this.file)
console.info("Flashcards: Cards to create")
@ -79,7 +81,7 @@ export class CardsService {
console.info("Flashcards: Cards to delete")
console.info(cardsToDelete)
this.insertMedias(cards)
this.insertMedias(cards, sourcePath)
await this.deleteCardsOnAnki(cardsToDelete, ankiBlocks)
await this.updateCardsOnAnki(cardsToUpdate)
await this.insertCardsOnAnki(cardsToCreate, frontmatter, deckName)
@ -116,11 +118,11 @@ export class CardsService {
}
}
private async insertMedias(cards: Card[]) {
private async insertMedias(cards: Card[], sourcePath: string) {
try {
// Currently the media are created for every run, this is not a problem since Anki APIs overwrite the file
// A more efficient way would be to keep track of the medias saved
await this.generateMediaLinks(cards)
await this.generateMediaLinks(cards, sourcePath)
await this.anki.storeMediaFiles(cards)
} catch (err) {
console.error(err)
@ -128,16 +130,15 @@ export class CardsService {
}
}
private async generateMediaLinks(cards: Card[]) {
private async generateMediaLinks(cards: Card[], sourcePath: string) {
if (this.app.vault.adapter instanceof FileSystemAdapter) {
// @ts-ignore: Unreachable code error
let attachmentsPath = this.app.vault.config.attachmentFolderPath
for (let card of cards) {
for (let media of card.mediaNames) {
let file: TFile = this.app.vault.getAbstractFileByPath(attachmentsPath + "/" + media) as TFile
let image = this.app.metadataCache.getFirstLinkpathDest(decodeURIComponent(media), sourcePath);
try {
let binaryMedia = await this.app.vault.readBinary(file)
let binaryMedia = await this.app.vault.readBinary(image)
card.mediaBase64Encoded.push(arrayBufferToBase64(binaryMedia))
} catch (err) {
Error("Error: Could not read media")
@ -208,6 +209,13 @@ export class CardsService {
// if it has been inserted it has an ID too
if (card.id !== null && !card.inserted) {
let id = card.getIdFormat()
if (card instanceof Inlinecard) {
if (this.settings.inlineID) {
id = " " + id
} else {
id = "\n" + id
}
}
card.endOffset += this.totalOffset
let offset = card.endOffset
@ -296,7 +304,7 @@ export class CardsService {
return [cardsToCreate, cardsToUpdate]
}
public async deckNeedToBeChanged(cardsIds : number[], deckName: string) {
public async deckNeedToBeChanged(cardsIds: number[], deckName: string) {
let cardsInfo = await this.anki.cardsInfo(cardsIds)
console.log("Flashcards: Cards info")
console.log(cardsInfo)
@ -307,10 +315,10 @@ export class CardsService {
return false
}
public getCardsIds(ankiCards: any, generatedCards: Card[]) : number[] {
let ids : number[] = []
public getCardsIds(ankiCards: any, generatedCards: Card[]): number[] {
let ids: number[] = []
if (ankiCards) {
if (ankiCards) {
for (let flashcard of generatedCards) {
let ankiCard = undefined
if (flashcard.inserted) {
@ -323,7 +331,7 @@ export class CardsService {
return ids
}
public parseGlobalTags(file: String) : string[] {
public parseGlobalTags(file: String): string[] {
let globalTags: string[] = []
let tags = file.match(/(?:cards-)?tags: ?(.*)/im)

View File

@ -2,6 +2,7 @@ export interface ISettings {
contextAwareMode: boolean
sourceSupport: boolean
codeHighlightSupport: boolean
inlineID: boolean
contextSeparator: string
deck: string
flashcardsTag: string

View File

@ -1,3 +1,5 @@
import { Vault, TFile} from 'obsidian';
export function arrayBufferToBase64(buffer: ArrayBuffer): string {
var binary = "";
var bytes = new Uint8Array(buffer);