diff --git a/src/lib/parser/DeckParser.test.ts b/src/lib/parser/DeckParser.test.ts index 493c9046..0e992c93 100644 --- a/src/lib/parser/DeckParser.test.ts +++ b/src/lib/parser/DeckParser.test.ts @@ -101,6 +101,9 @@ test('Markdown nested bullet points', async () => { expect(deck.cards[1].name).toBe(''); expect(deck.cards[1].back).toBe('
Oslo
'); expect(deck.cards[2].name).toBe(''); - expect(deck.cards[2].back).toBe('
Stockholm
'); + + console.log('Deck card 2 back:', deck.cards[2].back); + + expect(deck.cards[2].back).toBe('

Stockholm

'); expect(deck.cards.length).toBe(3); }) diff --git a/src/lib/parser/DeckParser.ts b/src/lib/parser/DeckParser.ts index 22ee1a73..68f30874 100644 --- a/src/lib/parser/DeckParser.ts +++ b/src/lib/parser/DeckParser.ts @@ -54,6 +54,9 @@ export class DeckParser { noLimits: boolean; + workspace: Workspace; + customExporter: CustomExporter; + public get name() { return this.payload[0].name; } @@ -65,6 +68,11 @@ export class DeckParser { this.noLimits = input.noLimits; this.globalTags = null; this.payload = []; + this.workspace = new Workspace(true, 'fs'); + this.customExporter = new CustomExporter( + input.name, + this.workspace.location + ); this.processFirstFile(input.name); } @@ -73,13 +81,16 @@ export class DeckParser { if (this.settings.nestedBulletPoints && isMarkdownFile(name)) { const contents = getFileContents(firstFile, false); - this.payload = handleNestedBulletPointsInMarkdown( + this.payload = handleNestedBulletPointsInMarkdown({ name, - contents?.toString(), - this.settings.deckName, - [], - this.settings - ); + contents: contents?.toString(), + deckName: this.settings.deckName, + decks: [], + settings: this.settings, + exporter: this.customExporter, + workspace: this.workspace, + files: this.files, + }); } else if (isHTMLFile(name)) { const contents = getFileContents(firstFile, true); this.payload = contents @@ -254,13 +265,6 @@ export class DeckParser { return dom('.page-body > p > del'); } - setupExporter(decks: Deck[], workspace: string) { - for (const d of decks) { - d.style = d.cleanStyle(); - } - return new CustomExporter(this.firstDeckName, workspace); - } - // https://stackoverflow.com/questions/6903823/regex-for-youtube-id _getYouTubeID(input: string) { return this.ensureNotNull(input, () => { @@ -363,7 +367,11 @@ export class DeckParser { } build(ws: Workspace) { - const exporter = this.setupExporter(this.payload, ws.location); + if (ws.location !== this.workspace.location) { + console.debug('workspace location changed for build'); + console.debug(ws.location); + this.customExporter = new CustomExporter(this.firstDeckName, ws.location); + } for (const d of this.payload) { const deck = d; @@ -401,7 +409,7 @@ export class DeckParser { const originalName = dom(elem).attr('src'); if (originalName && isImageFileEmbedable(originalName)) { const newName = embedFile({ - exporter, + exporter: this.customExporter, files: this.files, filePath: decodeURIComponent(originalName), workspace: ws, @@ -430,7 +438,7 @@ export class DeckParser { ); } const newFileName = embedFile({ - exporter, + exporter: this.customExporter, files: this.files, filePath: global.decodeURIComponent(audiofile), workspace: ws, @@ -486,13 +494,12 @@ export class DeckParser { } this.payload[0].settings = this.settings; - exporter.configure(this.payload); - return exporter.save(); + this.customExporter.configure(this.payload); + return this.customExporter.save(); } - tryExperimental(ws: Workspace) { + tryExperimental() { const fallback = new FallbackParser(this.files); - const exporter = this.setupExporter(this.payload, ws.location); this.payload = fallback.run(this.settings); if ( @@ -504,9 +511,9 @@ export class DeckParser { } this.payload[0].settings = this.settings; - exporter.configure(this.payload); + this.customExporter.configure(this.payload); - return exporter.save(); + return this.customExporter.save(); } totalCardCount() { diff --git a/src/lib/parser/PrepareDeck.ts b/src/lib/parser/PrepareDeck.ts index a704ba87..907e3e2e 100644 --- a/src/lib/parser/PrepareDeck.ts +++ b/src/lib/parser/PrepareDeck.ts @@ -78,7 +78,7 @@ export async function PrepareDeck( const htmlFile = convertedFiles.find((file) => isHTMLFile(file.name)); parser.processFirstFile(htmlFile?.name ?? input.name); } else { - const apkg = await parser.tryExperimental(input.workspace); + const apkg = await parser.tryExperimental(); return { name: getDeckFilename(parser.name ?? input.name), apkg, diff --git a/src/lib/parser/handleNestedBulletPointsInMarkdown.ts b/src/lib/parser/handleNestedBulletPointsInMarkdown.ts index 8df61c6f..cd1b8bf7 100644 --- a/src/lib/parser/handleNestedBulletPointsInMarkdown.ts +++ b/src/lib/parser/handleNestedBulletPointsInMarkdown.ts @@ -3,18 +3,42 @@ import { getTitleFromMarkdown } from './getTitleFromMarkdown'; import get16DigitRandomId from '../../shared/helpers/get16DigitRandomId'; import Note from './Note'; import { markdownToHTML } from '../markdown'; +import cheerio from 'cheerio'; import CardOption from './Settings'; +import { embedFile } from './exporters/embedFile'; +import { isImageFileEmbedable } from '../storage/checks'; +import CustomExporter from './exporters/CustomExporter'; +import Workspace from './WorkSpace'; + +import { File } from '../zip/zip'; const BULLET_POINT_REGEX = /^-/; +interface HandleNestedBulletPointsInMarkdownInput { + name: string; + contents: string | undefined; + deckName: string | undefined; + decks: Deck[]; + settings: CardOption; + exporter: CustomExporter; + workspace: Workspace; + files: File[]; +} + export const handleNestedBulletPointsInMarkdown = ( - name: string, - contents: string | undefined, - deckName: string | undefined, - decks: Deck[], - settings: CardOption + input: HandleNestedBulletPointsInMarkdownInput ) => { + const { + name, + contents, + deckName, + decks, + settings, + exporter, + workspace, + files, + } = input; const deck = new Deck( deckName ?? getTitleFromMarkdown(contents) ?? name, [], @@ -39,7 +63,32 @@ export const handleNestedBulletPointsInMarkdown = ( const isEnd = lines.length - 1 == lines.indexOf(line); if (isEnd || (BULLET_POINT_REGEX.exec(line) && isCreating)) { - deck.cards.push(new Note(currentFront, markdownToHTML(currentBack))); + const dom = cheerio.load(currentBack, { + xmlMode: true, + }); + const images = dom('img'); + const media: string[] = []; + + images.each((_i, elem) => { + const src = dom(elem).attr('src'); + if (src && isImageFileEmbedable(src)) { + const newName = embedFile({ + exporter: exporter, + files: files, + filePath: src, + workspace: workspace, + }); + if (newName) { + dom(elem).attr('src', newName); + media.push(newName); + } + } + }); + + currentBack = dom.html(); + const note = new Note(currentFront, markdownToHTML(currentBack)); + note.media = media; + deck.cards.push(note); isCreating = false; currentFront = ''; currentBack = ''; @@ -55,7 +104,32 @@ export const handleNestedBulletPointsInMarkdown = ( } if (currentBack !== '' || currentFront !== '') { - deck.cards.push(new Note(currentFront, markdownToHTML(currentBack))); + const dom = cheerio.load(currentBack, { + xmlMode: true, + }); + const images = dom('img'); + const media: string[] = []; + + images.each((_i, elem) => { + const src = dom(elem).attr('src'); + if (src && isImageFileEmbedable(src)) { + const newName = embedFile({ + exporter, + files: files, + filePath: src, + workspace, + }); + if (newName) { + dom(elem).attr('src', newName); + media.push(newName); + } + } + }); + + currentBack = dom.html() || ''; + const note = new Note(currentFront, markdownToHTML(currentBack)); + note.media = media; + deck.cards.push(note); } return decks; diff --git a/src/test/fixtures/simple-deck.md b/src/test/fixtures/simple-deck.md index 637894d0..d8073f08 100644 --- a/src/test/fixtures/simple-deck.md +++ b/src/test/fixtures/simple-deck.md @@ -10,4 +10,4 @@ - What is the capital of Sweden - Stockholm + Stockholm