hgiesel / closet

The Web Framework for Flashcards
https://closetengine.com
GNU General Public License v3.0
65 stars 6 forks source link

Bug: Output of filtered mathjax formula including custom closet clozes not rendered anymore (Anki 2.1.43, Closet 0.5.1) #57

Closed sandersantema closed 3 years ago

sandersantema commented 3 years ago

Describe the bug Card: \([[jaxc1::x]]\) Front: image Back: image

Previously I the following worked when using closet clozes inside of mathjax formula's:

const elements = closet.anki.getQaChildNodes()
const memory = chooseMemory('closet__1')
const filterManager = closet.FilterManager.make(preset, memory.map)

const output = [[
    elements,
    memory,
    filterManager,
]]

// Use ldots instead of cdots such that ellipsis are located at the bottom of 
// the line in the same way anki's default cloze ellipsis are.
const ellipsis = `\\ldots`
const wrapWithBrackets = (v) => `\\left [ ${v} \\right ]`
const inactiveEllipser = () => wrapWithBrackets(ellipsis)

const backStylizer = closet.Stylizer.make({
    // See: https://docs.mathjax.org/en/latest/input/tex/extensions/color.html
    processor: v => `{\\color{cornflowerblue}{ ${v} }}`,
})

const frontStylizer = backStylizer.toStylizer({
    mapper: wrapWithBrackets,
})

const frontEllipser = (tag) => ([
    tag.values[1]
    ? tag.values[1]
    : ellipsis
])

filterManager.install(
    closet.recipes.shuffle({ tagname: 'mix' }),
    closet.recipes.order({ tagname: 'ord' }),
    closet.recipes.multipleChoice({ tagname: 'mc' }),
    closet.browser.recipes.rect({ tagname: 'rect' }),
    closet.recipes.cloze({ tagname: 'c' }),
    closet.recipes.cloze({
        tagname: 'jaxc',
        inactiveEllipser,
        frontStylizer,
        backStylizer,
        frontEllipser,
    })
)

Having ported this to the new code the following doesn't work anymore:

const elements = closet.template.anki.getQaChildNodes();
const memory = chooseMemory("closet__1");
const filterManager = closet.FilterManager.make(preset, memory.map);

const output = [[elements, memory, filterManager]];

const ellipsis = `\\ldots`
const wrapWithBrackets = (v) => `\\left [ ${v} \\right ]`
const inactiveEllipser = () => wrapWithBrackets(ellipsis)

const backStylizer = closet.Stylizer.make({
    processor: v => `{\\color{cornflowerblue}{ ${v} }}`,
})

const frontStylizer = backStylizer.toStylizer({
    mapper: wrapWithBrackets,
})

const frontEllipser = (tag) => ([
    tag.values[1]
    ? tag.values[1]
    : ellipsis
])

const jaxcOptions = {
  frontStylizer: frontStylizer,
  frontEllipser: frontEllipser,

  backStylizer: frontStylizer,

  inactiveEllipser: inactiveEllipser,
}

filterManager.install(
    closet.recipes.shuffle({ tagname: "mix" }),
    closet.recipes.order({ tagname: "ord" }),

    closet.flashcard.recipes.cloze({
        tagname: "c",
        defaultBehavior: closet.flashcard.behaviors.Show,
    }),
    closet.flashcard.recipes.multipleChoice({
        tagname: "mc",
        defaultBehavior: closet.flashcard.behaviors.Show,
    }),
    closet.flashcard.recipes.sort({
        tagname: "sort",
        defaultBehavior: closet.flashcard.behaviors.Show,
    }),

    closet.browser.recipes.rect({
        tagname: "rect",
        defaultBehavior: closet.flashcard.behaviors.Show,
    }),
    closet.flashcard.recipes.cloze.show({
        tagname: 'jaxc',
        ...jaxcOptions,
    }),
)

Debug information To help you debug, I need some information. I have two suggestions for you to help me. It would be best, if you did both, as that way I can help you the quickest.

Method 1 (preferred method)

(remove zip file extension) debug.apkg.zip

Method 2

No errors: image

hgiesel commented 3 years ago

You need to add a backEllipser to the jaxcOptions, like so:

const jaxcOptions = {
    ...
    backEllipser: (tag) => [tag.values[0]],
    ...
}

This is because Closet now emits semantic HTML, and MathJax doesn't know how to resolve that HTML.

sandersantema commented 3 years ago

Thank you very much for the quick answer, is this documented anywhere or is the best solution just reading trough the code for now?

hgiesel commented 3 years ago

I'm afraid the extending capabilities are terribly documented right now. If you struggle with setting up something, you should read the code, or just approach me :)

Documentation is certainly on the horizon. But I will probably start with more user documentation, rather than developer documentation.

sandersantema commented 3 years ago

I see, good to know documentation is on the horizon. I think more (well at least of minimum quality that is :wink:) documentation is always a good thing whichever kind it is. And I suppose reading the code would be a good way to learn some more typescript.

I do however wonder who exactly are the intended users of Closet or who you might envision as the intended users. Given that closet requires at least some basic scripting I suppose it might be a crowd of somewhat more developer orientated people who might benefit more from developer documentation. Which in turn might enable more of these "developer orientated" people to create Closet scripts which people who are less interested in scripting closet can simply copy and paste. But that really depends on who is currently using Closet or who you intend to.

hgiesel commented 3 years ago

I do however wonder who exactly are the intended users of Closet

I see two groups:

  1. People who want to create their own custom templates
  2. People who want to use powerful note types

Right now, Closet is basically exclusively reserved for the first group. My current plan is to wait for the next Ankidroid release, which will have Closet support, and then publish a powerful notetype with features like Image occlusion + Incremental reveal clozes and make a video-tutorial and get some more attention that way.

However I would expect them to use it in a different way, then the current "developer"-type users. I already made Closet work without Asset Manager installed, so the idea would be to only distritbute the note type and tell the people to install Closet add-on additionally, so the cognitive load is not that high.

TLDR; I try to cater to both groups, however I only have so much time :)