From f612d74724efac93423e5e3a037f77f84b8fc42d Mon Sep 17 00:00:00 2001 From: Alexander Alemayhu Date: Tue, 12 Nov 2024 06:34:50 +0100 Subject: [PATCH] feat: new card option for disabling indented bullets This is useful for creating cloze deletions on the front and reducing lots of unnecessary cards created. --- .../SettingsController.test.ts | 1 + .../SettingsController/supportedOptions.ts | 6 +++ src/lib/parser/DeckParser.ts | 45 +++++++++++++------ src/lib/parser/Settings/Settings.ts | 3 ++ src/lib/parser/findToggles.ts | 16 +++++++ 5 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/lib/parser/findToggles.ts diff --git a/src/controllers/SettingsController/SettingsController.test.ts b/src/controllers/SettingsController/SettingsController.test.ts index 649dac7c..282d900c 100644 --- a/src/controllers/SettingsController/SettingsController.test.ts +++ b/src/controllers/SettingsController/SettingsController.test.ts @@ -47,6 +47,7 @@ describe('SettingsController', () => { 'remove-mp3-links': 'true', 'perserve-newlines': 'true', 'vertex-ai-pdf-questions': 'false', + 'disable-indented-bullets': 'false', }); }); diff --git a/src/controllers/SettingsController/supportedOptions.ts b/src/controllers/SettingsController/supportedOptions.ts index 07271217..031f328c 100644 --- a/src/controllers/SettingsController/supportedOptions.ts +++ b/src/controllers/SettingsController/supportedOptions.ts @@ -124,6 +124,12 @@ const supportedOptions = (): CardOption[] => { 'Use Vertex AI API to generate questions from PDFs. This is a paid feature and if enabled will send your notes to Google Cloud.', false ), + new CardOption( + 'disable-indented-bullets', + 'Disable Indented Bullets', + 'Disable indented bullets from becoming separate cards. This applies to bullet lists.', + false + ), ]; return v.filter(Boolean); diff --git a/src/lib/parser/DeckParser.ts b/src/lib/parser/DeckParser.ts index 2d1ed3e2..21425d79 100644 --- a/src/lib/parser/DeckParser.ts +++ b/src/lib/parser/DeckParser.ts @@ -26,6 +26,7 @@ import { handleNestedBulletPointsInMarkdown } from './handleNestedBulletPointsIn import { checkFlashcardsLimits } from '../User/checkFlashcardsLimits'; import { extractStyles } from './extractStyles'; import { withFontSize } from './withFontSize'; +import { findToggleLists } from './findToggles'; export interface DeckParserInput { name: string; @@ -117,14 +118,6 @@ export class DeckParser { return dom(selector).toArray(); } - findToggleLists(dom: cheerio.Root): cheerio.Element[] { - const selector = - this.settings.isCherry || this.settings.isAll - ? '.toggle' - : '.page-body > ul'; - return dom(selector).toArray(); - } - removeNestedToggles(input: string) { return input .replace(/(.*?)<\/details>/g, '') @@ -206,9 +199,19 @@ export class DeckParser { const paragraphs = this.extractCardsFromParagraph(dom); let cards: Note[] = this.extractCards(dom, toggleList); + const disableIndentedBullets = this.settings.disableIndentedBulletPoints; // Note: this is a fallback behaviour until we can provide people more flexibility on picking non-toggles if (cards.length === 0) { - cards.push(...[...this.extractCardsFromLists(dom), ...paragraphs]); + cards.push( + ...[ + ...this.extractCardsFromLists(dom, disableIndentedBullets), + ...paragraphs, + ] + ); + } else if (this.settings.disableIndentedBulletPoints) { + cards.push( + ...[...this.extractCardsFromLists(dom, disableIndentedBullets)] + ); } // Prevent bad cards from leaking out @@ -551,7 +554,11 @@ export class DeckParser { } private extractToggleLists(dom: cheerio.Root) { - const foundToggleLists = this.findToggleLists(dom); + const foundToggleLists = findToggleLists(dom, { + isCherry: this.settings.isCherry, + isAll: this.settings.isAll, + disableIndentedBulletPoints: this.settings.disableIndentedBulletPoints, + }); return [...foundToggleLists, ...this.findIndentedToggleLists(dom)]; } @@ -646,14 +653,24 @@ export class DeckParser { return paragraphs.map((p) => new Note(dom(p).html() ?? '', '')); } - private extractCardsFromLists(dom: cheerio.Root) { + private extractCardsFromLists( + dom: cheerio.Root, + disableIndentedBullets: boolean + ) { const cards: Note[] = []; - const lists = [...dom('ul').toArray(), ...dom('ol').toArray()]; + const lists = !disableIndentedBullets + ? [...dom('ul').toArray(), ...dom('ol').toArray()] + : [...dom('.page-body > .bulleted-list').toArray()]; lists.forEach((list) => { - for (const child of dom(list).find('li')) { + if (!disableIndentedBullets) { + for (const child of dom(list).find('li')) { + this.checkLimits(cards.length, []); + cards.push(new Note(dom(child).html() ?? '', '')); + } + } else { this.checkLimits(cards.length, []); - cards.push(new Note(dom(child).html() ?? '', '')); + cards.push(new Note(dom(list).html() ?? '', '')); } }); diff --git a/src/lib/parser/Settings/Settings.ts b/src/lib/parser/Settings/Settings.ts index 2e8c93a8..08cae47f 100644 --- a/src/lib/parser/Settings/Settings.ts +++ b/src/lib/parser/Settings/Settings.ts @@ -67,6 +67,7 @@ export class Settings { readonly nestedBulletPoints: boolean; readonly vertexAIPDFQuestions: boolean; + readonly disableIndentedBulletPoints: boolean; constructor(input: { [key: string]: string }) { this.deckName = input.deckName; @@ -100,6 +101,8 @@ export class Settings { this.pageEmoji = input['page-emoji'] || 'first_emoji'; this.addNotionLink = input['add-notion-link'] === 'true'; this.vertexAIPDFQuestions = input['vertex-ai-pdf-questions'] === 'true'; + this.disableIndentedBulletPoints = + input['disable-indented-bullets'] === 'true'; /* Is this really needed? */ if (this.parentBlockId) { this.addNotionLink = true; diff --git a/src/lib/parser/findToggles.ts b/src/lib/parser/findToggles.ts new file mode 100644 index 00000000..d4a5cdf2 --- /dev/null +++ b/src/lib/parser/findToggles.ts @@ -0,0 +1,16 @@ +import cheerio from 'cheerio'; + +import Settings from './Settings'; + +export function findToggleLists( + dom: cheerio.Root, + context: Pick +): cheerio.Element[] { + if (context.isCherry || context.isAll) { + return dom('.toggle').toArray(); + } + if (!context.disableIndentedBulletPoints) { + return dom('.page-body > ul').toArray(); + } + return dom('.page-body > ul:not(.bulleted-list)').toArray(); +}