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.


Preliminary Steps

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

Additionally, if you downloaded Yomichan from a file, try updating that as well. Most users should have installed it from their browser's extension page, in which case nothing has to be done.

Warning for Firefox Users

There appears to be an issue where the default version for Yomichan on Firefox is three years old. 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).


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.
  5. Copy and paste the following values into the fields (the custom markers won't be available in the dropdown arrow):
Click here to see the fields to copy and paste.
Anki Fields Yomichan Format Notes
Key {expression}
Word {expression}
WordReading {furigana-plain}
PAOverride
PAOverrideText New in version 0.11.0.0
AJTWordPitch
PrimaryDefinition {jpmn-primary-definition}
PrimaryDefinitionPicture New in version 0.11.0.0
Sentence {cloze-prefix}<b>{cloze-body}</b>{cloze-suffix}
SentenceReading
AltDisplay
AltDisplayPASentenceCard
AdditionalNotes
*IsSentenceCard
*IsClickCard
*IsHoverCard
*IsTargetedSentenceCard
*PAShowInfo
*PATestOnlyWord
*PADoNotTest
*PASeparateWordCard
*PASeparateSentenceCard
*SeparateClozeDeletionCard
Hint
HintNotHidden
Picture
WordAudio {audio}
SentenceAudio
PAGraphs {jpmn-pitch-accent-graphs}
PAPositions {jpmn-pitch-accent-positions}
PASilence [sound:_silence.wav]
WordReadingHiragana {jpmn-word-reading-hiragana} New in version 0.11.0.0
FrequenciesStylized {jpmn-frequencies}
FrequencySort {jpmn-frequency-sort}
SecondaryDefinition {jpmn-secondary-definition}
ExtraDefinitions {jpmn-extra-definitions}
UtilityDictionaries {jpmn-utility-dictionaries}
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 binary fields, 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 here.

The custom markers like {jpmn-primary-definition} is not provided by Yomichan by default. See the section below to make these markers 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 markers 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.1                                 ~}}
    {{~!                                                                      ~}}
    {{~!       https://aquafina-water-bottle.github.io/jp-mining-note/        ~}}
    {{~!       -------------------------------------------------------        ~}}
    
    
    {{~! ================ Dictionary Categorization Options ================= ~}}
    
    {{~! valid values: "bilingual", "monolingual" ~}}
    {{~set "opt-first-definition-type" "bilingual" ~}}
    
    {{~! matches most JMdict dictionaries, 新和英 and 日本語文法辞典(全集)~}}
    {{~#set "bilingual-dict-regex"~}} ^(([Jj][Mm][Dd]ict)(?! Surface Forms)(.*)|新和英|日本語文法辞典\(全集\)|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"               false}}
    {{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" false ~}}
    
    
    
    
    
    
    
    
    {{~! ======================== 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.1                                 ~}}
    
    {{~!
        ==================
         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-bilingual" ~}}
                {{~#regexMatch (get "bilingual-dict-regex") "gu"~}}{{dictionaryName}}{{~/regexMatch~}}
            {{/set~}}
            {{~#set "rx-match-utility" ~}}
                {{~#regexMatch (get "utility-dict-regex") "gu"~}}{{dictionaryName}}{{~/regexMatch~}}
            {{/set~}}
    
    
            {{~#if (op "!==" (get "rx-match-ignored") "")~}}
                ignored
            {{~else if (op "!==" (get "rx-match-bilingual") "")~}}
                bilingual
            {{~else if (op "!==" (get "rx-match-utility") "")~}}
                utility
            {{~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) ~}}
    {{#*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 . 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 "===" 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~}}
    
            {{~#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 ~}}
                {{~#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!

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.


Yomichan Templates Options Summary

Monolingual Definition

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"}}{{/set~}}
to
{{~#set "opt-first-definition-type" "monolingual"}}{{/set~}}

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.


Selected Text as the Definition

If you want to select the text to use instead of the definition, simply set opt-selection-text-enabled to true.

By default, this enable the following behavior:

  1. If nothing is selected, then the first dictionary is chosen just like normal.
  2. If a dictionary is selected, then that dictionary will replace the first definition.
  3. If a section of text is selected, then that dictionary will replace the first definition. Additionally, that section of text will be highlighted (bolded).

Note

Selecting parts of a definition to bold the text does not always work, especially when used across text with formatting or newlines. See this for more details.

With this being said, selecting the dictionary should always work.


Additional Instructions for Other Platforms

Outside of creating cards on the PC, there are some other platforms that one can create cards from.


Android Setup

Warning

Actually using JPMN on mobile devices (e.g. for reviewing), is currently not stable. This simply shows how to make the cards on Android.

If you wish to add cards on Android, use AnkiconnectAndroid and follow the instructions on the AnkiconnectAndroid's README page. It might help to export a copy of Yomichan settings from your PC and import said settings on Android, instead of re-doing all of the steps on Android.

Note

Occasionally, importing your Yomichan settings from the PC may lead to AnkiconnectAndroid not working. If AnkiconnectAndroid doesn't work after going through the entire README, try resetting your Yomichan settings on Android and starting from scratch.

Note

There is currently no way to automatically add an image (e.g. a screenshot) automatically. Images must be added manually within AnkiDroid.

Although screenshots cannot be added automatically, the runtime options supports automatically adding images based off of tags. See here for more info.


Kindle Setup

One can use something like ann2html to export a Yomichan-able HTML file based on the Kindle's vocabulary builder. This allows you to add the cards through Yomichan on the PC.


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 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: Everything Else 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.

    Other than that, you are completely finished with the setup process!

    Note

    See Setup: Everything Else (Notes on Various Programs) for specific tips on a select few programs.


Last update: May 7, 2023