Skip to content

Setup: Yomichan

Overview

Yomichan is the main program that will create the cards. You can download Yomichan as a Firefox extension or under the Chrome web store.

This section will go over the minimal Yomichan setup to work with this card type.

If you have never used Yomichan before, please see this page first to get it working.

Warning for Firefox Users

The default version for Yomichan on Firefox's Add-ons page is over three years old, and is not compatible with this note. If you are using Firefox, ensure that your Yomichan version is indeed the latest version, by clicking on the Yomichan icon and clicking on the question mark.

If it isn't, you will have to download it manually (use a708116f79104891acbd-22.10.23.0.xpi).


Preliminary Steps

  • If you have used Yomichan before, please make a backup of your settings (just in case).

  • On top of the standard dictionaries, I highly recommend installing some frequency and pitch accent dictionaries, as that information is used by jp-mining-note. Many of these dictionaries can be found within TheMoeWay's drive. These dictionaries are installed in the exact same way as the standard Yomichan dictionaries.

    In particular, I recommend the JPDB frequency list.


Yomichan Fields

To edit the fields that Yomichan will automatically fill out, do the following:

  1. Navigate to Yomichan Settings.
  2. Go to the Anki section.
  3. Select Anki card format....
  4. Set "Model" as JP Mining Note, and "Deck" to whatever your Anki deck is.
  5. Copy and paste the following values into the fields (the custom helpers won't be available in the dropdown arrow):
Click here to see the fields to copy and paste.
Anki Fields Yomichan Format
Key {expression}
Word {expression}
WordReading {furigana-plain}
PAOverride
PAOverrideText
AJTWordPitch
PrimaryDefinition {jpmn-primary-definition}
PrimaryDefinitionPicture
Sentence {cloze-prefix}<b>{cloze-body}</b>{cloze-suffix}
SentenceReading
AltDisplayWord
AltDisplaySentence
AltDisplayPASentenceCard
AltDisplayAudioCard
AdditionalNotes
Hint
HintNotHidden
*IsSentenceCard
*IsTargetedSentenceCard
*IsClickCard
*IsHoverCard
*IsHintCard
*IsSentenceFirstCard
*IsAudioCard
*PAShowInfo
*PATestOnlyWord
*PADoNotTest
*PASeparateWordCard
*PASeparateSentenceCard
*SeparateAudioCard
*SeparateSentenceAudioCard
Picture
WordAudio {audio}
SentenceAudio
PAGraphs {jpmn-pitch-accent-graphs}
PAPositions {jpmn-pitch-accent-positions}
FrequenciesStylized {jpmn-frequencies}
FrequencySort {jpmn-frequency-sort}
PASilence [sound:_silence.wav]
WordReadingHiragana {jpmn-word-reading-hiragana}
YomichanWordTags {tags}
SecondaryDefinition {jpmn-secondary-definition}
ExtraDefinitions {jpmn-extra-definitions}
UtilityDictionaries {jpmn-utility-dictionaries}
CardCache
Comment

The above fields will create, by default, a basic vocab card in bilingual format, with all other definitions in collapsable fields.

Note

Anything field marked with * are fields used to determine the resulting card type, and should be configured to each user's personal preferences.

To change the default value of any of the fields, simply fill the field in within the aforementioned Anki card format... section. For example, if you want the card to be a sentence card by default, fill the IsSentenceCard field with anything, e.g. 1.

See the Changing Card Type page for more info.

The custom helpers like {jpmn-primary-definition} is not provided by Yomichan by default. See the section below to make these helpers usable.


Yomichan Templates

Yomichan supports user inserted template code that allows the automatic separation of bilingual and monolingual dictionary definitions, custom stylization, etc. This note type makes heavy use of these custom templates.

To make the new helpers usable, do the following:

  1. Navigate to Yomichan Settings.
  2. Make sure that advanced settings are turned on (bottom left corner).
  3. Go to the Anki section
  4. Select Configure Anki card templates...
  5. If you have existing template code already, I highly recommend resetting the templates (bottom right corner, red button) unless you know exactly what you are doing.

After resetting the templates, without removing any of the existing template code, add the following template code as follows:

  1. Copy and paste the code below to the top of the default Yomichan template code:

    Click here to show the template code to copy.
    {{~!                                                                      ~}}
    {{~! ==================== jp-mining-note handlebars ===================== ~}}
    {{~!                               v1.0.10                                ~}}
    {{~!                                                                      ~}}
    {{~!       https://aquafina-water-bottle.github.io/jp-mining-note/        ~}}
    {{~!       -------------------------------------------------------        ~}}
    
    
    {{~! ================ Dictionary Categorization Options ================= ~}}
    
    {{~! valid values: "bilingual", "monolingual" ~}}
    {{~set "opt-first-definition-type" "bilingual" ~}}
    
    {{~!
        A bunch of JP and CN bilingual dictionaries covered by default,
        including: JMdict, 新和英, CEDICT, etc
    ~}}
    {{~#set "bilingual-dict-regex"~}} ^(([Jj][Mm][Dd]ict)(.*)|新和英|日本語文法辞典\(全集\)|KireiCake|NEW斎藤和英大辞典|CEDICT|CC-CEDICT|CantoDict|Canto CEDICT|Words\.hk C-E FS|CE Wiktionary|CC-Canto|ADD_BILINGUAL_DICTIONARIES_HERE)$ {{~/set~}}
    {{~#set "utility-dict-regex"~}} ^(NHK日本語発音アクセント新辞典|シン・漢字遣い参考|[Jj][Mm][Dd]ict( Surface)? Forms|JMedict)$ {{~/set~}}
    {{~#set "ignored-dict-regex"~}} ^(ADD_IGNORED_DICTIONARIES_HERE)$ {{~/set~}}
    
    
    
    {{~! ====================== Selected Text Options ======================= ~}}
    
    {{set "opt-selection-text-enabled"               true}}
    {{set "opt-selection-text-dictionary"            true}}
    {{set "opt-selection-text-glossary"              true}}
    {{set "opt-selection-text-glossary-attempt-bold" true}}
    
    
    
    {{~! ==================== Frequency Sorting Options ===================== ~}}
    {{~! See here for the official documentation on how these options work:
        https://github.com/MarvNC/JP-Resources#freq-settings ~}}
    
    {{~#set "opt-ignored-freq-dict-regex"~}} ^(JLPT_Level)$ {{~/set~}}
    {{~#set "opt-ignored-freq-value-regex"~}}{{~/set~}}
    {{~#set "opt-keep-freqs-past-first-regex"~}} ^()$ {{~/set~}}
    {{~set "opt-no-freq-default-value" 9999999 ~}}
    {{~set "opt-freq-sorting-method" "harmonic" ~}} {{~! "min", "first", "avg", "harmonic" ~}}
    
    {{~set "opt-grammar-override" true ~}}
    {{~set "opt-grammar-override-value" 0 ~}}
    {{~#set "opt-grammar-override-dict-regex"~}} ^(日本語文法辞典\(全集\)|毎日のんびり日本語教師|JLPT文法解説まとめ|どんなときどう使う 日本語表現文型辞典|絵でわかる日本語)$ {{~/set~}}
    
    
    
    {{~! ============== Dictionary First Line Removal Options =============== ~}}
    {{~set "opt-wrap-first-line-spans" true ~}}
    
    {{~! valid values: "except", "only" ~}}
    {{~set "opt-first-line-regex-mode" "except"~}}
    
    {{~!
        JMdict and jitenon dictionaries from stephenmk are ignored
        (the latter because the handlebars cannot properly detect the first line.)
        In particular, removing the first line from jitenon dictionaries with handlebars alone
        is not trivial, so that feature will not be supported.
    ~}}
    {{~#set "opt-first-line-dicts-regex"~}} ^(JMdict.*|Nico/Pixiv|故事・ことわざ・慣用句オンライン|四字熟語辞典オンライン|国語辞典オンライン|大辞林 第四版|新明解国語辞典 第八版)$ {{~/set~}}
    
    
    
    {{~! ========================== Other Options =========================== ~}}
    {{~set "opt-primary-def-one-dict-entry-only" false ~}}
    {{~set "opt-jmdict-list-format" true ~}}
    
    
    
    
    
    
    
    
    {{~! ======================== Plaintext Options ========================= ~}}
    
    {{~!
        WARNING: I recommend not changing these options if you are using the
        jp-mining-note template. These options will change the general layout
        of the HTML, which will prevent certain features or stylizations
        from properly working. (If you aren't using jp-mining-note, please feel
        free to change these options!)
    
        Instead of using these options, see here:
    
            https://aquafina-water-bottle.github.io/jp-mining-note/definitions/
    
        These hide specific elements using CSS instead of modifying the raw HTML
        structure behind it.
    ~}}
    
    {{~set "opt__plaintext__enabled"                     false ~}}
    {{~set "opt__plaintext__one-dict-entry-only-no-list" false ~}}
    {{~set "opt__plaintext__remove-dictionary-tag"       false ~}}
    {{~set "opt__plaintext__remove-first-line-enabled"   false ~}}
    
    
    
    {{~! ============== ORIGINAL YOMICHAN TEMPLATE CODE BELOW ============== ~}}
    
  2. Copy and paste the code below to the bottom of the default Yomichan template code:

    Click here to show the template code to copy.
    {{~! ============== ORIGINAL YOMICHAN TEMPLATE CODE ABOVE =============== ~}}
    {{~!                               v1.0.10                                ~}}
    
    {{~!
        ==================
         helper functions
        ==================
    ~}}
    
    {{#*inline "s"}}{{/inline}}
    
    {{~! categorizes into 4 types: "ignored", "bilingual", "utility", or "monolingual" ~}}
    {{~#*inline "jpmn-get-dict-type"~}}
    
        {{~#scope~}}
            {{~#set "rx-match-ignored" ~}}
                {{~#regexMatch (get "ignored-dict-regex") "gu"~}}{{dictionaryName}}{{~/regexMatch~}}
            {{/set~}}
            {{~#set "rx-match-utility" ~}}
                {{~#regexMatch (get "utility-dict-regex") "gu"~}}{{dictionaryName}}{{~/regexMatch~}}
            {{/set~}}
            {{~#set "rx-match-bilingual" ~}}
                {{~#regexMatch (get "bilingual-dict-regex") "gu"~}}{{dictionaryName}}{{~/regexMatch~}}
            {{/set~}}
    
    
            {{~#if (op "!==" (get "rx-match-ignored") "")~}}
                ignored
            {{~else if (op "!==" (get "rx-match-utility") "")~}}
                utility
            {{~else if (op "!==" (get "rx-match-bilingual") "")~}}
                bilingual
            {{~else~}}
                {{~! assumed that anything else is a monolingual dictionary ~}}
                monolingual
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    
    {{~! returns "" if selection text is disabled, or if none existed in the first place ~}}
    {{~#*inline "_jpmn-selection-text"~}}
        {{~! text-mode != "" and text-mode > 0 ~}}
        {{~#if (op "===" (get "opt-selection-text-enabled") true)~}}
            {{~! removes leading and trailing whitespace ~}}
            {{~#regexReplace "^\s+|\s+$" "" "g"~}}
                {{~#getMedia "selectionText"}}{{/getMedia~}}
            {{~/regexReplace~}}
        {{~/if~}}
    {{~/inline~}}
    
    {{~! checks that the selection text is indeed a dictionary (returns the text if true, nothing if false) ~}}
    {{~#*inline "_jpmn-check-dictionary"~}}
        {{~#scope~}}
            {{~#set "selection-is-dictionary" false}}{{/set~}}
    
            {{~#each definition.definitions~}}
                {{~#if (op "===" (get "selection") dictionary)~}}
                    {{~#set "selection-is-dictionary" true ~}}{{~/set~}}
                {{~/if~}}
            {{~/each~}}
    
            {{~#if (op "===" (get "selection-is-dictionary") true)~}}
                {{~get "selection"~}}
            {{~else~}}
                {{~! null ~}}
            {{~/if~}}
        {{~/scope~}}
    {{~/inline~}}
    
    
    
    {{~!
        Gives the raw glossary as the search string
        (for searching to see if the selected text is a part of a dictionary)
    
        Remember: we should NOT use _jpmn-glossary-single because it preprocesses the text!
        If the selected text was on the first line and the first line is removed,
        then using _jpmn-glossary-single will fail to find the selected text!
    ~}}
    {{#*inline "_jpmn-glossary-single-search"}}
    
        {{~#scope~}}
            {{~#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each~}}
        {{~/scope~}}
    
    {{/inline}}
    
    
    
    {{~! escape a regex string: https://stackoverflow.com/a/6969486~}}
    {{~! /[.*+?^${}()|[\]\\]/g, '\\$&' ~}}
    {{~! escapes the `regexString` regex to allow it to be used like a normal search in a string ~}}
    {{#*inline "_jpmn-escape-regex"}}
        {{~#regexReplace "[.*+?^${}()|[\]\\]" "\$&" "g"~}}{{~regexString~}}{{~/regexReplace~}}
    {{/inline}}
    
    
    {{~#*inline "_jpmn-get-dict-if-glossary-selected"~}}
        {{~#scope~}}
            {{~#set "result-dictionary" null}}{{/set~}}
            {{~#set "search-selection"}}{{~#regexReplace "[.*+?^${}()|[\]\\]" "\$&" "g"~}}{{~> _jpmn-selection-text ~}}{{~/regexReplace~}}{{/set~}}
    
            {{~#each definition.definitions~}}
                {{~#set "search-def"}}{{~> _jpmn-glossary-single-search . brief=../brief noDictionaryTag=../noDictionaryTag ~}}{{/set~}}
    
                {{~set "search-regex-match" (regexMatch (get "search-selection") "gu" (get "search-def"))}}
                {{~#if (op "&&"
                    (op "===" (get "result-dictionary") null)
                    (op "!==" (get "search-regex-match") "")
                )~}}
                    {{~#set "result-dictionary" dictionary}}{{/set~}}
                {{~/if~}}
    
            {{~/each~}}
            {{~get "result-dictionary" ~}}
        {{~/scope~}}
    {{~/inline~}}
    
    
    
    
    {{~!
        searches dictionary, determined by `opt-first-definition-type`
        - (opt-first-definition-type === bilingual) -> bilingual dictionaries are searched first
        - (opt-first-definition-type === monolingual) -> monolingual dictionaries are searched first
    ~}}
    {{~#*inline "_jpmn-search-primary-definition-dict"~}}
        {{~#scope~}}
            {{~#if (op "===" (get "opt-first-definition-type") "bilingual")~}}
                {{~#set "first-definition-search-type-1" "bilingual"}}{{/set~}}
                {{~#set "first-definition-search-type-2" "monolingual"}}{{/set~}}
            {{~else~}}
                {{~#set "first-definition-search-type-1" "monolingual"}}{{/set~}}
                {{~#set "first-definition-search-type-2" "bilingual"}}{{/set~}}
            {{~/if~}}
    
    
            {{~! first-dictionary === null <=> no valid dictionary was found ~}}
            {{~#set "first-dictionary" null}}{{/set~}}
    
            {{~#each definition.definitions~}}
    
                {{~#set "test-dict-name"}}{{~> jpmn-get-dict-type . dictionaryName=dictionary ~}}{{/set~}}
                {{~#if (op "===" (get "test-dict-name") (get "first-definition-search-type-1"))~}}
                    {{~#if (op "===" null (get "first-dictionary"))~}}
                        {{~#set "first-dictionary" dictionary~}}{{~/set~}}
                    {{~/if~}}
                {{~/if~}}
    
            {{~/each~}}
    
    
            {{~! uses other dictionary type, last resort ~}}
            {{~#if (op "===" (get "first-dictionary") null)~}}
    
                {{~#each definition.definitions~}}
    
                    {{~#set "test-dict-name"}}{{~> jpmn-get-dict-type . dictionaryName=dictionary ~}}{{/set~}}
                    {{~#if (op "===" (get "test-dict-name") (get "first-definition-search-type-2"))~}}
                        {{~#if (op "===" null (get "first-dictionary"))~}}
                            {{~#set "first-dictionary" dictionary~}}{{~/set~}}
                        {{~/if~}}
                    {{~/if~}}
    
                {{~/each~}}
    
            {{~/if~}}
    
            {{~#get "first-dictionary"~}}{{~/get~}}
        {{~/scope~}}
    {{~/inline~}}
    
    
    {{~!
        if (selection-text exists):
            if (selection-text is exactly a dictionary):
                return dictionary
            if (able to detect dictionary of which the selection-text is highlighting):
                return dictionary
            return null
    ~}}
    {{~#*inline "_jpmn-check-dictionary-and-glossary"~}}
        {{~#scope~}}
    
            {{~#set "result" ""}}{{/set~}}
    
            {{~! checks if the selected text matches a dictionary ~}}
            {{~#if (op "===" (get "opt-selection-text-dictionary") true)~}}
                {{~#set "result"}}{{~> _jpmn-check-dictionary . ~}}{{/set~}}
            {{~/if~}}
    
            {{~! checks if the selected text matches a definition in a dictionary ~}}
            {{~#if
                (op "&&" (op "===" (get "result") "")
                    (op "&&"
                        (op "===" (get "opt-selection-text-glossary") true)
                        (op "===" (get "opt-selection-text-glossary-attempt-bold") true)
                    )
                )
            ~}}
                {{~#set "result"}}{{~> _jpmn-get-dict-if-glossary-selected . ~}}{{/set~}}
            {{~/if~}}
    
            {{~get "result" ~}}
    
        {{~/scope~}}
    {{~/inline~}}
    
    
    {{~!
        if (selection-text exists):
            if (selection-text is exactly a dictionary):
                return null
            if (able to detect dictionary of which the selection-text is highlighting):
                return "uses-glossary"
            return null
    ~}}
    {{~#*inline "_jpmn-selection-uses-glossary"~}}
        {{~#scope~}}
    
            {{~#set "result" ""}}{{/set~}}
    
            {{~! checks if the selected text matches a dictionary ~}}
            {{~#if (op "===" (get "opt-selection-text-dictionary") true)~}}
                {{~#set "result"}}{{~> _jpmn-check-dictionary . ~}}{{/set~}}
            {{~/if~}}
    
            {{~! checks if the selected text matches a definition in a dictionary ~}}
            {{~#if (op "!==" (get "result") "") ~}}
                {{~! selection-text is a dictionary -> null ~}}
            {{~else if
                (op "&&"
                    (op "===" (get "opt-selection-text-glossary") true)
                    (op "===" (get "opt-selection-text-glossary-attempt-bold") true)
                )
            ~}}
                {{~#set "result"}}{{~> _jpmn-get-dict-if-glossary-selected . ~}}{{/set~}}
                {{~#if (op "!==" (get "result") "") ~}}
                    {{~! selection-text dict found -> "uses-glossary" ~}}
                    uses-glossary
                {{~/if~}}
            {{~/if~}}
    
        {{~/scope~}}
    {{~/inline~}}
    
    
    
    
    {{~!
        if (selection-text exists):
            if (selection-text is exactly a dictionary):
                return dictionary
            if (able to detect dictionary of which the selection-text is highlighting):
                return dictionary
            if (selection-text-glossary is not enabled):
                return first-dictionary (determined by `opt-first-definition-type`)
            return null
    
        else:
            return first-dictionary (determined by `opt-first-definition-type`)
    ~}}
    {{~#*inline "_jpmn-get-primary-definition-dict"~}}
        {{~#scope~}}
    
            {{~! first checks selection text ~}}
            {{~#set "selection"}}{{~> _jpmn-selection-text ~}}{{/set~}}
            {{~#if (op "!==" (get "selection") "")~}}
    
                {{~#set "result"}}{{~> _jpmn-check-dictionary-and-glossary . ~}}{{/set~}}
    
                {{~! doesn't return a dictionary if opt-selection-text-glossary is false b/c ~}}
                {{~#if
                    (op "&&"
                        (op "===" (get "result") "")
                        (op "===" (get "opt-selection-text-glossary") false)
                    )
                ~}}
                    {{~#set "result"}}{{~> _jpmn-search-primary-definition-dict . ~}}{{/set~}}
                {{~/if~}}
    
                {{~get "result" ~}}
    
            {{~! no selection text ~}}
            {{~else~}}
                {{~> _jpmn-search-primary-definition-dict . ~}}
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    
    
    {{~!
        get number of primary dictionary entries
    ~}}
    {{~#*inline "_jpmn-primary-dict-entry-count"~}}
        {{~#scope~}}
    
            {{~#set "primary-dictionary"}}{{~> _jpmn-get-primary-definition-dict . ~}}{{/set~}}
    
            {{~set "dict-entry-count" 0 ~}}
    
            {{~#each definition.definitions~}}
                {{~#if (op "===" dictionary (get "primary-dictionary")) ~}}
                    {{~! dict-entry-count += 1 ~}}
                    {{~set "dict-entry-count" (op "+"
                        (get "dict-entry-count") 1
                    )
                    ~}}
                {{~/if~}}
            {{~/each~}}
    
            {{~get "dict-entry-count" ~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    
    
    
    
    
    {{~!
        returns "true" if valid dict, "" (null) otherwise
    ~}}
    {{~#*inline "_jpmn-non-primary-is-valid-dict"~}}
        {{~!
            PARAMETERS:
                validDictType: "monolingual" or "bilingual" or "utility"
                dictionaryName: dictionary id
                entryCount: primary dictionary entry count
        ~}}
        {{~#scope~}}
    
            {{~set "use-primary-dictionary" (op "&&"
                (get "opt-primary-def-one-dict-entry-only")
                (op "&&" (op "!==" (op "+" entryCount) 0) (op "!==" (op "+" entryCount) 1))
            )
            ~}}
    
            {{~set "valid-dict" null ~}}
            {{~#set "test-dict-type"}}{{~> jpmn-get-dict-type . dictionaryName=dictionaryName ~}}{{/set~}}
            {{~#if (op "&&"
                (op "===" (get "test-dict-type") validDictType)
                (op "||"
                    (op "!==" (get "primary-dictionary") dictionaryName)
                    (op "===" (get "use-primary-dictionary") true)
                )
            ) ~}}
                {{~set "valid-dict" "true" ~}}
            {{~/if~}}
            {{~get "valid-dict" ~}}
    
        {{~/scope~}}
    {{~/inline~}}
    
    
    {{~!
        returns "true" if valid dict, "" (null) otherwise
    ~}}
    {{~#*inline "_jpmn-non-primary-has-valid-dict"~}}
        {{~!
            PARAMETERS:
                validDictType: "monolingual" or "bilingual" or "utility"
                entryCount: primary dictionary entry count
        ~}}
        {{~#scope~}}
    
            {{~set "use-primary-dictionary" (op "&&"
                (get "opt-primary-def-one-dict-entry-only")
                (op "&&" (op "!==" (op "+" entryCount) 0) (op "!==" (op "+" entryCount) 1))
            )
            ~}}
    
            {{~!
                without this set statement, the parameters
                magically disappears within the bottom 'each' loop...
            ~}}
            {{~ set "valid-dict-type" validDictType ~}}
            {{~ set "entry-count" entryCount ~}}
    
            {{~set "has-valid-dict" null ~}}
            {{~#each definition.definitions~}}
                {{~#set "is-valid-dict"}}{{~> _jpmn-non-primary-is-valid-dict . validDictType=(get "valid-dict-type") entryCount=(get "entry-count") dictionaryName=dictionary ~}}{{/set~}}
    
                {{~#if (op "===" (get "is-valid-dict") "true") ~}}
                    {{~set "has-valid-dict" "true" ~}}
                {{~/if~}}
    
            {{~/each~}}
            {{~get "has-valid-dict" ~}}
    
        {{~/scope~}}
    {{~/inline~}}
    
    
    
    
    
    
    {{~#*inline "_jpmn-get-primary-definition-value"~}}
        {{~!
            ASSUMPTION: "primary-dictionary" and "search-selection" is available to us from previous functions
        ~}}
        {{~#scope~}}
    
            {{~#if
                (op "&&"
                    (op "!==" (get "search-selection") "")
                    (get "opt-primary-def-one-dict-entry-only")
                )
            ~}}
                {{~! text was highlighted -> use primary dictionary entry with highlighted text ~}}
    
                {{~set "found-dict-entry" false ~}}
    
                {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                <ol>
                {{~/if~}}
    
                {{~#each definition.definitions~}}
    
                    {{~#set "rx-match-dict-entry" ~}}
                        {{~#regexMatch (get "search-selection") "gu"~}}{{~> _jpmn-glossary-single-search . brief=../brief noDictionaryTag=../noDictionaryTag ~}}{{~/regexMatch~}}
                    {{/set~}}
    
                    {{~#if
                        (op "&&"
                            (op "===" (get "found-dict-entry") false)
                            (op "&&"
                                (op "!==" (get "rx-match-dict-entry") "")
                                (op "===" dictionary (get "primary-dictionary"))
                            )
                        )
                    ~}}
    
                        {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                        <li data-details="{{~dictionary~}}">
                        {{~/if~}}
    
                        {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
    
                        {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                        </li>
                        {{~/if~}}
    
                        {{~set "found-dict-entry" true ~}}
                    {{~/if~}}
                {{~/each~}}
    
                {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                </ol>
                {{~/if~}}
    
            {{~else if (get "opt-primary-def-one-dict-entry-only") ~}}
                {{~! use first primary dictionary entry ~}}
    
                {{~set "found-dict-entry" false ~}}
    
                {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                <ol>
                {{~/if~}}
    
                {{~#each definition.definitions~}}
                    {{~#if
                        (op "&&"
                            (op "===" (get "found-dict-entry") false)
                            (op "===" dictionary (get "primary-dictionary"))
                        )
                    ~}}
    
                        {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                        <li data-details="{{~dictionary~}}">
                        {{~/if~}}
    
                        {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
    
                        {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                        </li>
                        {{~/if~}}
    
                        {{~set "found-dict-entry" true ~}}
                    {{~/if~}}
                {{~/each~}}
    
                {{~#if (op "!" (get "opt__plaintext__one-dict-entry-only-no-list")) ~}}
                </ol>
                {{~/if~}}
    
            {{~else~}}
                {{~! use all primary dictionary entries ~}}
    
                {{~#if (get "opt__plaintext__one-dict-entry-only-no-list") ~}}
                    {{~! must manually calculate number of primary-dictionary entries... ~}}
    
                    {{~set "t" 0 ~}}
                    {{~#each definition.definitions~}}
                        {{~#if (op "===" dictionary (get "primary-dictionary"))~}}
                            {{~set "t" (op "+" (get "t") 1) ~}}
                        {{~/if~}}
                    {{~/each~}}
    
                    {{~#if (op ">=" (get "t") 2)~}} <ol> {{~/if~}}
    
                    {{~#each definition.definitions~}}
                        {{~#if (op "===" dictionary (get "primary-dictionary"))~}}
                            {{~#if (op ">=" (get "t") 2)~}} <li data-details="{{~dictionary~}}"> {{~/if~}}
                                {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                            {{~#if (op ">=" (get "t") 2)~}} </li> {{~/if~}}
                        {{~/if~}}
                    {{~/each~}}
    
                    {{~#if (op ">=" (get "t") 2)~}} </ol> {{~/if~}}
    
                {{~else~}}
    
                    <ol> {{~s~}}
    
                    {{~#each definition.definitions~}}
                        {{~#if (op "===" dictionary (get "primary-dictionary"))~}}
                            <li data-details="{{~dictionary~}}">
                                {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                            </li>
                        {{~/if~}}
                    {{~/each~}}
    
                    </ol> {{~s~}}
    
                {{~/if~}}
    
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    {{~!
        if (mode === "except" and (regex doesn't match) or mode === "only" and (regex matches)):
            return true
        return null
    ~}}
    
    {{#*inline "_jpmn-check-first-line-dict"}}
        {{~#scope~}}
    
            {{~#set "rx-match-first-line-dict" ~}}
                {{~#regexMatch (get "opt-first-line-dicts-regex") "u"~}}{{dictionary}}{{~/regexMatch~}}
            {{/set~}}
    
            {{~#if (op "||"
                (op "&&"
                    (op "===" (get "opt-first-line-regex-mode") "except")
                    (op "===" (get "rx-match-first-line-dict") "")
                )
                (op "&&"
                    (op "===" (get "opt-first-line-regex-mode") "only")
                    (op "!==" (get "rx-match-first-line-dict") "")
                )
            )
            ~}}
                true
            {{~/if~}}
        {{~/scope~}}
    {{~/inline~}}
    
    {{~! custom glossary-single function for additional regex parsing per dictionary ~}}
    {{~! OVERRIDES brief and noDictionaryTag ~}}
    {{#*inline "_jpmn-glossary-single"}}
        {{~#scope~}}
    
            {{~#if (op "===" dictionary "NHK日本語発音アクセント新辞典")~}}
                {{~#regexReplace "<br></span> ・" "<br></span>" "g"~}}
                    {{~#regexReplace "<br> ・" "<br>" "g"~}}
                        {{~> _jpmn-glossary-single2 . ~}}
                    {{~/regexReplace~}}
                {{~/regexReplace~}}
            {{~else~}}
                {{~> _jpmn-glossary-single2 . ~}}
            {{~/if~}}
    
        {{~/scope~}}
    {{/inline}}
    
    
    
    {{~! custom glossary-single function to add custom html around the dictionary and tags ~}}
    {{#*inline "_jpmn-glossary-single2"}}
    
        {{~#scope~}}
    
            {{~#if (op "!" (get "opt__plaintext__enabled")) ~}}
    
                <span class="dict-group__tag-list"> {{~s~}}
    
                    {{~#each definitionTags~}}
    
                        <span class="dict-group__tag dict-group__tag--name"> {{~s~}}
                            <span class="dict-group__tag-inner"> {{~s~}}
                                {{~name~}}
                            </span> {{~s~}}
                        </span> {{~s~}}
    
                    {{~/each~}}
    
                    <span class="dict-group__tag dict-group__tag--dict"> {{~s~}}
                        <span class="dict-group__tag-inner"> {{~s~}}
                            {{~dictionary~}}
                        </span> {{~s~}}
                    </span> {{~s~}}
    
                </span> {{~s~}}
    
            {{~else~}}
    
                {{~#scope~}}
                    {{~#set "any" false}}{{/set~}}
                    {{~#each definitionTags~}}
                        {{~#if (get "any")}}, {{else}}({{/if~}}
                        {{name}}
                        {{~#set "any" true}}{{/set~}}
                    {{~/each~}}
                    {{~#if (op "!" (get "opt__plaintext__remove-dictionary-tag"))~}}
                        {{~#if (get "any")}}, {{else}}({{/if~}}
                        {{dictionary}}
                        {{~#set "any" true}}{{/set~}}
                    {{~/if~}}
                    {{~#if (get "any")}}) {{/if~}}
                {{~/scope~}}
                {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
    
            {{~/if~}}
    
            {{~#if (op "!" (get "opt__plaintext__enabled")) ~}}
            <span class="dict-group__glossary"> {{~s~}}
            {{~/if~}}
    
            {{~!
                option to not wrap with spans because it may break dictionaries
                (this is the hell that is parsing html with regex)
            ~}}
            {{~#if (op "&&"
                (get "opt-wrap-first-line-spans")
                (op "!" (get "opt__plaintext__enabled"))
            )
            }}
    
                {{~#set "modify-first-line" ~}}{{> _jpmn-check-first-line-dict dictionary=dictionary }}{{~/set~}}
    
                {{~#if (get "modify-first-line") ~}}
                    {{~#regexReplace
                            "^(<span lang=\"ja\">)?(.*?)<br>"
                            "$1<span class=\"dict-group__glossary--first-line\">$2</span><span class=\"dict-group__glossary--first-line-break\"><br></span>"
                    ~}}
                        {{~> _jpmn-glossary-single3 . ~}}
                    {{~/regexReplace~}}
                {{~else~}}
                    {{~> _jpmn-glossary-single3 . ~}}
                {{~/if~}}
    
            {{~else if (get "opt__plaintext__remove-first-line-enabled")~}}
    
                {{~#set "modify-first-line" ~}}{{> _jpmn-check-first-line-dict dictionary=dictionary }}{{~/set~}}
    
                {{~#if (get "modify-first-line") ~}}
                    {{~! none match means the dictionary is not an exception, i.e. replace newline ~}}
                    {{~#regexReplace
                            "^(<span lang=\"ja\">)?(.*?)<br>"
                            "$1"
                    ~}}
                        {{~> _jpmn-glossary-single3 . ~}}
                    {{~/regexReplace~}}
                {{~else~}}
                    {{~> _jpmn-glossary-single3 . ~}}
                {{~/if~}}
    
            {{~else~}}
                {{~> _jpmn-glossary-single3 . ~}}
            {{~/if~}}
    
            {{~#if (op "!" (get "opt__plaintext__enabled")) ~}}
            </span> {{~s~}}
            {{~/if~}}
    
        {{~/scope~}}
    
        {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}
    {{/inline}}
    
    
    
    
    {{#*inline "_jpmn-glossary-single3"}}
    
        {{~#scope~}}
    
            {{~#if (op "&&"
                (op "===" (get "opt-jmdict-list-format") true)
                (op "||"
                    (op "===" dictionary "JMdict (English)")
                    (op "||"
                        (op "===" dictionary "JMdict Extra")
                        (op "===" dictionary "JMdict")
                    )
                )
            )
            ~}}
                {{~#if (op "<=" glossary.length 1)~}}
                    {{#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{/each}}
                {{~else~}}
                    <ul>{{#each glossary}}<li>{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}</li>{{/each}}</ul>
                {{~/if~}}
            {{~else~}}
                {{~#each glossary}}{{#formatGlossary ../dictionary}}{{{.}}}{{/formatGlossary}}{{#unless @last}} | {{/unless}}{{/each~}}
            {{~/if~}}
    
        {{~/scope~}}
    
    {{/inline}}
    
    
    
    
    
    {{~!
        =============
         frequencies
        =============
    ~}}
    
    {{#*inline "jpmn-frequencies"}}
        {{~#if (op ">" definition.frequencies.length 0)~}}
            {{~#each definition.frequencies~}}
                <div class="frequencies__group" data-details="{{~dictionary~}}"> {{~s~}}
                    <div class="frequencies__number"> {{~s~}}
                        <span class="frequencies__number-inner"> {{~s~}}
                            {{~! removes the "X" in JPDB's frequency and replaces it with a less assuming character
                                (it interferes with the color of the card, since you see red
                                at the top corner which is somewhat distracting) ~}}
                            {{~#regexReplace "❌" "✖" "g"~}}
                                {{~frequency~}}
                            {{~/regexReplace~}}
                        </span> {{~s~}}
                    </div> {{~s~}}
                    <div class="frequencies__dictionary"> {{~s~}}
                        <span class="frequencies__dictionary-inner"> {{~s~}}
                            {{~dictionary~}}
                        </span> {{~s~}}
                    </div> {{~s~}}
                </div>
            {{~/each~}}
        {{~/if~}}
    {{/inline}}
    
    {{~! base code taken from: https://github.com/MarvNC/JP-Resources#sorting-mined-anki-cards-by-frequency ~}}
    {{~! NOTE: THIS IS ONLY KEPT FOR LEGACY PURPOSES, and is now deprecated. Please use {jpmn-frequency-sort} instead. ~}}
    {{~#*inline "jpmn-min-freq"~}}
        {{~#scope~}}
            {{~#set "min-freq" 0~}}{{~/set~}}
                {{~#each definition.frequencies~}}
    
                    {{~#set "rx-match-ignored-freq" ~}}
                        {{~#regexMatch (get "ignored-freq-dict-regex") "gu"~}}{{this.dictionary}}{{~/regexMatch~}}
                    {{/set~}}
    
                    {{~#if
                        (op "&&"
                            (op "||"
                                (op "===" (get "min-freq") 0)
                                (op ">" (op "+" (get "min-freq")) (op "+" (regexMatch "\d" "g" this.frequency)))
                            )
                            (op "===" (get "rx-match-ignored-freq") "")
                        )
                    ~}}
                        {{~#set "min-freq" (op "+" (regexMatch "\d" "g" this.frequency))}}{{/set~}}
                    {{~/if~}}
                {{~/each~}}
            {{~get "min-freq"~}}
        {{~/scope~}}
    {{/inline}}
    
    
    {{#*inline "jpmn-frequency-sort"}}
        {{~! Frequency sort handlebars: v23.03.13.1 ~}}
        {{~! The latest version can be found at https://github.com/MarvNC/JP-Resources#freq-handlebar ~}}
        {{~#scope~}}
    
            {{~! Do not change the code below unless you know what you are doing. ~}}
            {{~set "result-freq" -1 ~}} {{~! -1 is chosen because no frequency dictionaries should have an entry as -1 ~}}
            {{~set "prev-freq-dict" "" ~}}
            {{~set "t" 1 ~}}
            {{~set "found-grammar-dict" false ~}}
    
            {{~! search for grammar dictionary ~}}
            {{~#each definition.definitions~}}
                {{~#set "rx-match-grammar-dicts" ~}}
                    {{~#regexMatch (get "opt-grammar-override-dict-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
                {{/set~}}
                {{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
                {{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
                    {{~set "found-grammar-dict" true ~}}
                {{/if~}}
            {{~/each~}}
    
            {{~! Additional case when "Result grouping mode" is set to "No Grouping"~}}
            {{~#set "rx-match-grammar-dicts" ~}}
                {{~#regexMatch (get "opt-grammar-override-dict-regex") "u"~}}{{this.definition.dictionary}}{{~/regexMatch~}}
            {{/set~}}
            {{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
            {{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
                {{~set "found-grammar-dict" true ~}}
            {{/if~}}
    
            {{~#each definition.frequencies~}}
    
                {{~! rx-match-ignored-freq is not empty if ignored <=> rx-match-ignored-freq is empty if not ignored ~}}
                {{~#set "rx-match-ignored-freq" ~}}
                    {{~#regexMatch (get "opt-ignored-freq-dict-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
                {{/set~}}
    
                {{~#set "rx-match-ignored-value" ~}}
                    {{~#regexMatch (get "opt-ignored-freq-value-regex") "u"~}}{{this.frequency}}{{~/regexMatch~}}
                {{/set~}}
                {{~#if (op "&&" (op "===" (get "rx-match-ignored-freq") "") (op "===" (get "rx-match-ignored-value") ""))~}}
    
                    {{~!
                        only uses the 1st frequency of any dictionary.
                        For example, if JPDB lists 440 and 26189㋕, only the first 440 will be used.
                    ~}}
                    {{~set "read-freq" false ~}}
                    {{~#if (op "!==" (get "prev-freq-dict") this.dictionary ) ~}}
                        {{~set "read-freq" true ~}}
                        {{~set "prev-freq-dict" this.dictionary ~}}
                    {{/if~}}
    
                    {{~#if (op "!" (get "read-freq") ) ~}}
                        {{~#set "rx-match-keep-freqs" ~}}
                            {{~#regexMatch (get "opt-keep-freqs-past-first-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
                        {{/set~}}
    
                        {{~! rx-match-keep-freqs is not empty if keep freqs ~}}
                        {{~#if (op "!==" (get "rx-match-keep-freqs") "") ~}}
                            {{~set "read-freq" true ~}}
                        {{/if~}}
                    {{/if~}}
    
                    {{~#if (get "read-freq") ~}}
                        {{~set "f" (op "+" (regexMatch "\d+" "" this.frequency)) ~}}
    
                        {{~#if (op "===" (get "opt-freq-sorting-method") "min") ~}}
                            {{~#if
                                (op "||"
                                    (op "===" (get "result-freq") -1)
                                    (op ">" (get "result-freq") (get "f"))
                                )
                            ~}}
                                {{~set "result-freq" (op "+" (get "f")) ~}}
                            {{~/if~}}
    
                        {{~else if (op "===" (get "opt-freq-sorting-method") "first") ~}}
                            {{~#if (op "===" (get "result-freq") -1) ~}}
                                {{~set "result-freq" (get "f") ~}}
                            {{~/if~}}
    
                        {{~else if (op "===" (get "opt-freq-sorting-method") "avg") ~}}
    
                            {{~#if (op "===" (get "result-freq") -1) ~}}
                                {{~set "result-freq" (get "f") ~}}
                            {{~else~}}
                                {{~!
                                    iterative mean formula (to prevent floating point overflow):
                                        $S_{(t+1)} = S_t + \frac{1}{t+1} (x - S_t)$
                                    - example java implementation: https://stackoverflow.com/a/1934266
                                    - proof: https://www.heikohoffmann.de/htmlthesis/node134.html
                                ~}}
                                {{~set "result-freq"
                                    (op "+"
                                        (get "result-freq")
                                        (op "/"
                                            (op "-"
                                                (get "f")
                                                (get "result-freq")
                                            )
                                            (get "t")
                                        )
                                    )
                                }}
                            {{~/if~}}
                            {{~set "t" (op "+" (get "t") 1) ~}}
    
                        {{~else if (op "===" (get "opt-freq-sorting-method") "harmonic") ~}}
                            {{~#if (op ">" (get "f") 0) ~}} {{~! ensures only positive numbers are used ~}}
                                {{~#if (op "===" (get "result-freq") -1) ~}}
                                    {{~set "result-freq" (op "/" 1 (get "f")) ~}}
                                {{~else ~}}
                                    {{~set "result-freq"
                                        (op "+"
                                            (get "result-freq")
                                            (op "/" 1 (get "f"))
                                        )
                                    }}
                                    {{~set "t" (op "+" (get "t") 1) ~}}
                                {{~/if~}}
                            {{~/if~}}
    
                        {{~else if (op "===" (get "opt-freq-sorting-method") "debug") ~}}
    
                            {{ this.dictionary }}: {{ this.frequency }} -> {{ get "f" }} <br>
    
                        {{~else~}}
                            (INVALID opt-freq-sorting-method value)
                        {{~/if~}}
    
                    {{~/if~}}
    
                {{~/if~}}
    
            {{~/each~}}
    
            {{~! (x) >> 0 apparently floors x: https://stackoverflow.com/a/4228528 ~}}
            {{~#if (op "===" (get "result-freq") -1) ~}}
                {{~set "result-freq" (get "opt-no-freq-default-value") ~}}
            {{~ else if (op "===" (get "opt-freq-sorting-method") "avg") ~}}
                {{~set "result-freq"
                    (op ">>" (get "result-freq") 0 )
                ~}}
            {{~ else if (op "===" (get "opt-freq-sorting-method") "harmonic") ~}}
                {{~set "result-freq"
                    (op ">>"
                        (op "*"
                            (op "/" 1 (get "result-freq"))
                            (get "t")
                        )
                        0
                    )
                ~}}
            {{~/if~}}
    
            {{~! override final result if grammar dictionary ~}}
            {{~#if (
                op "&&"
                    (op "===" (get "found-grammar-dict") true)
                    (op "===" (get "opt-grammar-override") true)
                )
            ~}}
                {{~set "result-freq" (get "opt-grammar-override-value") ~}}
            {{/if}}
    
            {{~get "result-freq"~}}
        {{~/scope~}}
    {{/inline}}
    
    
    
    
    {{~!
        ==============
         pitch accent
        ==============
    ~}}
    
    {{#*inline "jpmn-pitch-accent-graphs"}}
        {{~#if (op ">" pitchCount 0)~}}
            {{~#each pitches~}}
                <div class="pa-graphs__group" data-details="{{dictionary}}"> {{~s~}}
                    <div class="pa-graphs__dictionary"> {{~s~}}
                        <div class="pa-graphs__dictionary-inner"> {{~s~}}
                            {{~dictionary~}}
                        </div> {{~s~}}
                    </div> {{~s~}}
                    <ol> {{~s~}}
                        {{~#each pitches~}}
                            <li>
                                {{~> pitch-accent-item-disambiguation~}}
    
                                {{~#scope~}}
                                    {{~#set "any" false}}{{/set~}}
                                    {{~#each tags~}}
                                        {{~#if (get "any")}}, {{else}}({{/if~}}
                                        {{name}}
                                        {{~#set "any" true}}{{/set~}}
                                    {{~/each~}}
                                    {{~#if (get "any")}}) {{/if~}}
                                {{~/scope~}}
    
                                {{~> pitch-accent-item format="graph"~}}
                            </li>
                        {{~/each~}}
                    </ol> {{~s~}}
                </div>
            {{~/each~}}
        {{~/if~}}
    {{/inline}}
    
    
    {{#*inline "jpmn-pitch-accent-positions"}}
        {{~#if (op ">" pitchCount 0)~}}
            {{~#each pitches~}}
                <div class="pa-positions__group" data-details="{{dictionary}}"> {{~s~}}
                    <div class="pa-positions__dictionary"> {{~s~}}
                        <div class="pa-positions__dictionary-inner"> {{~s~}}
                            {{~dictionary~}}
                        </div> {{~s~}}
                    </div> {{~s~}}
                    <ol> {{~s~}}
                        {{~#each pitches~}}
                            <li>
                                {{~> pitch-accent-item-disambiguation~}}
    
                                {{~#scope~}}
                                    {{~#set "any" false}}{{/set~}}
                                    {{~#each tags~}}
                                        {{~#if (get "any")}}, {{else}}({{/if~}}
                                        {{name}}
                                        {{~#set "any" true}}{{/set~}}
                                    {{~/each~}}
                                    {{~#if (get "any")}}) {{/if~}}
                                {{~/scope~}}
    
                                {{~> pitch-accent-item format="position"~}}
                            </li>
                        {{~/each~}}
                    </ol> {{~s~}}
                </div>
            {{~/each~}}
        {{~/if~}}
    {{/inline}}
    
    
    {{~!
        ==============
         dictionaries
        ==============
    ~}}
    
    
    {{~! primary def: first monolingual (or first bilingual if no monolingual dicts found) ~}}
    {{~! does the reverse if opt-first-definition-type is "bilingual" ~}}
    {{~#*inline "jpmn-primary-definition"~}}
    
        {{~#scope~}}
    
            {{~! output warning if no dictionaries are found ~}}
            {{~#if (op "===" definition.definitions.length undefined)~}}
    WARNING: JPMN Handlebars cannot find any definitions to export.
    This is usually because your Yomichan settings has "Result grouping mode"
    set to "No grouping". Please set this to "Group term-reading pairs".
            {{~/if~}}
    
            {{~#set "primary-dictionary"}}{{~> _jpmn-get-primary-definition-dict . ~}}{{/set~}}
    
            {{~#if (op "===" (get "primary-dictionary") "")~}}
                {{~> _jpmn-selection-text ~}}
            {{~else~}}
                {{~#set "selection"}}{{~> _jpmn-selection-text ~}}{{/set~}}
                {{~#set "selection-uses-glossary"~}}
                    {{~> _jpmn-selection-uses-glossary . ~}}
                {{~/set~}}
    
                {{~! not "" <=> is a filled string, i.e. selection uses glossary ~}}
                {{~#if (op "!==" (get "selection-uses-glossary") "")~}}
    
                    {{~! escape regex ~}}
                    {{~#set "search-selection"}}{{~#regexReplace "[.*+?^${}()|[\]\\]" "\$&" "g"~}}{{~> _jpmn-selection-text ~}}{{~/regexReplace~}}{{/set~}}
                    {{~#set "search-selection-bold"}}<b>{{~> _jpmn-selection-text ~}}</b>{{/set~}}
    
                    {{~#regexReplace (get "search-selection") (get "search-selection-bold") "g"~}}
                        {{~> _jpmn-get-primary-definition-value . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                    {{~/regexReplace~}}
    
                {{~else~}}
                    {{~#set "search-selection"}}{{/set~}}
                    {{~> _jpmn-get-primary-definition-value . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                {{~/if~}}
    
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    {{~! extra def: bilingual defs (excluding primary def) ~}}
    {{~#*inline "jpmn-secondary-definition"~}}
    
        {{~#scope~}}
    
            {{~#set "primary-dictionary"}}{{~> _jpmn-get-primary-definition-dict . ~}}{{/set~}}
    
            {{~! looks to see if another dictionary exists ~}}
            {{~! entry count must be gotten here in order to properly iterate through definition.definitions ~}}
            {{~#set "entry-count"}}{{~> _jpmn-primary-dict-entry-count . ~}}{{/set~}}
            {{~#set "has-valid-dict"}}{{~> _jpmn-non-primary-has-valid-dict . validDictType="bilingual" entryCount=(get "entry-count")~}}{{/set~}}
    
            {{~#if (op "===" (get "has-valid-dict") "true") ~}}
                <ol>
                {{~#each definition.definitions~}}
                    {{~#set "is-valid-dict"}}{{~> _jpmn-non-primary-is-valid-dict . validDictType="bilingual" entryCount=(get "entry-count") dictionaryName=dictionary ~}}{{/set~}}
                    {{~#if (op "===" (get "is-valid-dict") "true") ~}}
    
                        <li data-details="{{~dictionary~}}">
                            {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                        </li>
    
                    {{~/if~}}
                {{~/each~}}
                </ol>
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    {{~! extra def: monolingual defs (excluding primary def) ~}}
    {{~#*inline "jpmn-extra-definitions"~}}
    
        {{~#scope~}}
    
            {{~#set "primary-dictionary"}}{{~> _jpmn-get-primary-definition-dict . ~}}{{/set~}}
    
            {{~! looks to see if another dictionary exists ~}}
            {{~! entry count must be gotten here in order to properly iterate through definition.definitions ~}}
            {{~#set "entry-count"}}{{~> _jpmn-primary-dict-entry-count . ~}}{{/set~}}
            {{~#set "has-valid-dict"}}{{~> _jpmn-non-primary-has-valid-dict . validDictType="monolingual" entryCount=(get "entry-count")~}}{{/set~}}
    
            {{~#if (op "===" (get "has-valid-dict") "true") ~}}
                <ol>
                {{~#each definition.definitions~}}
                    {{~#set "is-valid-dict"}}{{~> _jpmn-non-primary-is-valid-dict . validDictType="monolingual" entryCount=(get "entry-count") dictionaryName=dictionary ~}}{{/set~}}
                    {{~#if (op "===" (get "is-valid-dict") "true") ~}}
                        <li data-details="{{~dictionary~}}">
                            {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                        </li>
                    {{~/if~}}
                {{~/each~}}
                </ol>
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    
    {{~! pitch accent info: all pitch accent info dictionaries ~}}
    
    {{~#*inline "jpmn-utility-dictionaries"~}}
    
        {{~#scope~}}
    
            {{~! looks to see if another dictionary exists ~}}
            {{~! this if-statement is much more simple than the ones above, since utility dictionaries usually aren't the primary definition (if it is, then it'll just be repeated again here) ~}}
            {{~#set "has-valid-dict"}}{{~> _jpmn-non-primary-has-valid-dict . validDictType="utility"~}}{{/set~}}
    
            {{~#if (op "===" (get "has-valid-dict") "true") ~}}
                <ol>
                {{~#each definition.definitions~}}
                    {{~#set "test-dict-name"}}{{~> jpmn-get-dict-type . dictionaryName=dictionary ~}}{{/set~}}
                    {{~#if (op "===" (get "test-dict-name") "utility")~}}
                        <li data-details="{{~dictionary~}}">
                            {{~> _jpmn-glossary-single . brief=../brief noDictionaryTag=../noDictionaryTag ~}}
                        </li>
                    {{~/if~}}
                {{~/each~}}
                </ol>
            {{~/if~}}
    
        {{~/scope~}}
    
    {{~/inline~}}
    
    
    
    {{~!
        =======
         other
        =======
    ~}}
    
    {{~#*inline "jpmn-word-reading-hiragana"~}}
        {{~#set "word-reading" ~}}{{> reading}}{{/set~}}
    
        {{~#if (op "" (get "word-reading")) ~}}
            {{~#set "word-reading" ~}}{{> expression}}{{/set~}}
        {{~/if~}}
    
        {{#hiragana (get "word-reading") keepProlongedSoundMarks=false}}{{/hiragana}}
    {{~/inline~}}
    
    
    
    {{~!
    thanks to:
    - https://github.com/FooSoft/yomichan/issues/1952#issuecomment-922671489 for the base code
    - DaNautics#8833 for finding the above + removing the span classes
    ~}}
    {{#*inline "jpmn-sentence-bolded-furigana-plain"}}
        {{~#if definition.cloze~}}
    
            {{~#regexReplace "(<span class=\"term\">)|(</span>)" "" "g"~}}
            {{~#regexReplace "<ruby>(.+?)<rt>(.+?)</rt></ruby>" " $1[$2]" "g"~}}
    
                {{~#if (hasMedia "textFurigana" definition.cloze.prefix)~}}
                    {{~#getMedia "textFurigana" definition.cloze.prefix escape=false}}{{/getMedia~}}
                {{~else~}}
                    {{~definition.cloze.prefix~}}
                {{~/if~}}
    
                <b>
                {{~#if (hasMedia "textFurigana" definition.cloze.body)~}}
                    {{~#getMedia "textFurigana" definition.cloze.body escape=false}}{{/getMedia~}}
                {{~else~}}
                    {{~definition.cloze.body~}}
                {{~/if~}}
                </b>
    
                {{~#if (hasMedia "textFurigana" definition.cloze.suffix)~}}
                    {{~#getMedia "textFurigana" definition.cloze.suffix escape=false}}{{/getMedia~}}
                {{~else~}}
                    {{~definition.cloze.suffix~}}
                {{~/if~}}
    
            {{~/regexReplace~}}
            {{~/regexReplace~}}
    
        {{~/if~}}
    {{/inline}}
    
    
    
    {{#*inline "jpmn-filled-if-word-is-hiragana"}}
        {{~#scope~}}
            {{~#set "expression" ~}}{{> expression}}{{/set~}}
            {{~#set "reading" ~}}{{> reading}}{{/set~}}
            {{~#set "expression-hiragana" ~}}{{> jpmn-word-reading-hiragana}}{{/set~}}
    
            {{~#if (op "&&" (op "===" (get "expression") (get "reading")) (op "===" (get "expression") (get "expression-hiragana")))~}}
                1
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    {{#*inline "jpmn-filled-if-word-is-not-hiragana"}}
        {{~#scope~}}
            {{~#set "filled" ~}}{{> jpmn-filled-if-word-is-hiragana}}{{/set~}}
            {{~#if (op "===" (get "filled") "")~}}
                1
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    
    
    {{#*inline "jpmn-filled-if-grammar-point"}}
        {{~#scope~}}
            {{~set "found-grammar-dict" false ~}}
    
            {{~! search for grammar dictionary ~}}
            {{~#each definition.definitions~}}
                {{~#set "rx-match-grammar-dicts" ~}}
                    {{~#regexMatch (get "opt-grammar-override-dict-regex") "gu"~}}{{this.dictionary}}{{~/regexMatch~}}
                {{/set~}}
                {{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
                {{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
                    {{~set "found-grammar-dict" true ~}}
                {{/if~}}
            {{~/each~}}
    
            {{~! Additional case when "Result grouping mode" is set to "No Grouping"~}}
            {{~#set "rx-match-grammar-dicts" ~}}
                {{~#regexMatch (get "opt-grammar-override-dict-regex") "gu"~}}{{this.definition.dictionary}}{{~/regexMatch~}}
            {{/set~}}
            {{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
            {{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
                {{~set "found-grammar-dict" true ~}}
            {{/if~}}
    
            {{~#if (get "found-grammar-dict") ~}}
                1
            {{~/if~}}
    
        {{~/scope~}}
    {{/inline}}
    
    {{#*inline "jpmn-filled-if-not-grammar-point"}}
        {{~#scope~}}
            {{~#set "filled" ~}}{{> jpmn-filled-if-grammar-point}}{{/set~}}
            {{~#if (op "===" (get "filled") "")~}}
                1
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    
    
    
    {{#*inline "jpmn-filled-if-on-mim"}}
        {{~#scope~}}
            {{~#set "rx-match-on-mim" ~}}
                {{~#regexMatch "(, |^)on-mim(, |$)" "gu"~}}{{> tags }}{{~/regexMatch~}}
            {{/set~}}
    
            {{~#if (op "!==" (get "rx-match-on-mim") "") ~}}
                1
            {{/if~}}
        {{~/scope~}}
    {{/inline}}
    
    {{#*inline "jpmn-filled-if-not-on-mim"}}
        {{~#scope~}}
            {{~#set "filled" ~}}{{> jpmn-filled-if-not-on-mim}}{{/set~}}
            {{~#if (op "===" (get "filled") "")~}}
                1
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    
    
    
    {{~! my personal settings:
    - sentence card if grammar point
    - otherwise, if it's on-mim, then hint card
    - otherwise, default
    ~}}
    
    {{#*inline "jpmn-is-sentence-card"}}
        {{~> jpmn-filled-if-grammar-point ~}}
    {{/inline}}
    
    {{#*inline "jpmn-is-hint-card"}}
        {{~#scope~}}
            {{~#set "filled" ~}}{{> jpmn-is-sentence-card}}{{/set~}}
            {{~#if (op "===" (get "filled") "")~}}
                {{~> jpmn-filled-if-on-mim ~}}
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    {{#*inline "jpmn-is-click-card"}}
        {{~#scope~}}
            {{~#set "filled1" ~}}{{> jpmn-is-hint-card}}{{/set~}}
            {{~#set "filled2" ~}}{{> jpmn-is-sentence-card}}{{/set~}}
            {{~#if (op "&&"
                (op "===" (get "filled1") "")
                (op "===" (get "filled2") "")
            )~}}
                1
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    
    
    
    {{~! a test to check if your dictionaries are correctly classified. ~}}
    {{~! Only meant to be used for debugging purposes, not Anki. ~}}
    {{~#*inline "jpmn-test-dict-type"~}}
    {{~#scope~}}
    {{~#each definition.definitions~}}
    {{dictionary}}」: {{> jpmn-get-dict-type . dictionaryName=dictionary}}
    {{/each~}}
    {{~/scope~}}
    {{~/inline~}}
    

Make an example card!

TODO re-record with renji's texthooker, and show result card

At this point, you should be able to make cards with Yomichan!

Click here to show some example Japanese sentences.

adding a card with Yomichan

Obviously, just Yomichan alone doesn't fill every field. Notably, the picture and sentence audio is missing.

Outside of that, there are some final settings you can adjust within the Yomichan templates if the card doesn't look quite right.


Monolingual Cards

If you want the first definition you see (the PrimaryDefinition field) to be monolingual, change the following line at the top of the templates code:

{{~set "opt-first-definition-type" "bilingual" ~}}
to
{{~set "opt-first-definition-type" "monolingual" ~}}

Additionally, a common thing that people want to do with monolingual dictionaries is to remove the first line of the definition, because it may contain extra info that the user does not want. See here to do exactly that.

Note

If you are using monolingual dictionaries, on your first few cards, please check that your dictionaries are in the expected places. Extra bilingual definitions should be under Secondary Definition, and extra monolingual definitions should be under Extra Definitions.

If your dictionaries are ending up in the wrong sections, then it is likely a problem with how the template code categorizes the dictionaries. See here for more info.


Enjoy your new one-click cards!

If you've made it this far, then congratulations! Most fields of the cards have been automatically filled out, just from Yomichan alone!

This concludes the minimal setup process for creating cards with Yomichan.

From here, you likely fall under one of the two categories below:

  1. I'm new to sentence mining.

    If you're new to sentence mining, there are likely some things things that you would like to set up. These include:

    1. Getting the actual text to use Yomichan on.
    2. Getting the pictures and/or sentence audio from the media into the card.

    Head over to the Setup: Text & Media page to see exactly that.

  2. I already have a sentence mining workflow.

    If you have a workflow already setup, you may have to do some minor tweaks to your current workflow to match the new field names. For example, the exporting sentence audio and picture fields may be different compared to your previous card, and have should be set to SentenceAudio and Picture respectively.

Finally, remember that up until now, this has been the minimum setup in order to use jp-mining-note. There are likely many ways you can improve this current setup. See the "Extra Setup" pages to the left sidebar for more information.


Last update: July 10, 2023