Skip to content

JPMN Handlebars Package

This section documents how to use the jp-mining-note handlebars for Yomichan on any template that is not jp-mining-note. If you are using jp-mining-note, please see the Definitions page instead.


Features

This handlebars package provides all of the features that comes with the standard jp-mining-note installation:

  • A primary dictionary selector that automatically chooses the first bilingual or monolingual dictionary (depending on your settings)
  • Ability to manually select a dictionary or highlight a definition, to override the primary dictionary selector
  • Automatic separation of auxiliary dictionaries into monolingual and bilingual dictionaries
  • Option to hide the first line of monolingual dictionaries
  • Compatibility with other portable handlebars

The main difference between these handlebars and the handlebars used by jp-mining-note is that some default settings have been manually changed, so that definitions are exported in a minimalistic HTML format. This minimal format (almost) completely conforms with the default Yomichan handlebars, so it should work for any note type.


Setup Handlebars

Before doing anything, please make a backup of your Yomichan settings.

Video demo (click here)

  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" true ~}} {{~! jpmn default: false ~}}
    {{~set "opt-jmdict-list-format" false ~}} {{~! jpmn default: 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"                     true ~}} {{~! jpmn default: false ~}}
    {{~set "opt__plaintext__one-dict-entry-only-no-list" true ~}} {{~! jpmn default: false ~}}
    {{~set "opt__plaintext__remove-dictionary-tag"       true ~}} {{~! jpmn default: false ~}}
    {{~set "opt__plaintext__remove-first-line-enabled"   true ~}} {{~! jpmn default: 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~}}
    

Monolingual definitions

By default, the handlebars exports bilingual cards. Set opt-first-definition-type to monolingual if you want monolingual Anki cards. See here for more info.


Setup Fields

Video demo TODO (click here)

TODO video

  1. Navigate to Yomichan Settings.
  2. Go to the Anki section.
  3. Select Anki card format....
  4. Under your definition field (Glossary, VocabDef, etc.), type {jpmn-primary-definition} into the input box.
  5. If you have a field for bilingual definitions, set that field to {jpmn-secondary-definition}
  6. If you have a field for all other definitions, set that field to {jpmn-extra-definitions}

Common Problems

  1. If you transferred from the legacy Anime Cards handlebars (step 6 of this), then your pitch accent graphs might look a bit different. This is because the legacy Anime Cards handlebars removes a bunch of extra styling from the exported SVG, which is unfortunately non-standard.

    Nonetheless, the easy way to fix this is by simply replacing the current pitch accent handlebars with Anime Card's modified pitch accent handlebars:

    Legacy pitch accent handlebars (click here)
    {{! Pitch Accents }}
    {{#*inline "pitch-accent-item"}}
        {{~#pronunciation format=format reading=reading downstepPosition=position nasalPositions=nasalPositions devoicePositions=devoicePositions~}}{{~/pronunciation~}}
    {{/inline}}
    
    {{#*inline "pitch-accent-item-disambiguation"}}
        {{~#scope~}}
            {{~#set "exclusive" (spread exclusiveExpressions exclusiveReadings)}}{{/set~}}
            {{~#if (op ">" (property (get "exclusive") "length") 0)~}}
                {{~#set "separator" ""~}}{{/set~}}
                <em>({{#each (get "exclusive")~}}
                    {{~#get "separator"}}{{/get~}}{{{.}}}
                {{~/each}} only) </em>
            {{~/if~}}
        {{~/scope~}}
    {{/inline}}
    
    {{#*inline "pitch-accent-list"}}
        {{~#if (op ">" pitchCount 0)~}}
            {{~#if (op ">" pitchCount 1)~}}{{~/if~}}
            {{~#each pitches~}}
                {{~#each pitches~}}
                    {{~#if (op ">" ../../pitchCount 1)~}}{{~/if~}}
                        {{~> pitch-accent-item-disambiguation~}}
                        {{~> pitch-accent-item format=../../format~}}
                    {{~#if (op ">" ../../pitchCount 1)~}}{{~/if~}}
                {{~/each~}}
            {{~/each~}}
            {{~#if (op ">" pitchCount 1)~}}{{~/if~}}
        {{~else~}}
        {{~/if~}}
    {{/inline}}
    
    {{#*inline "pitch-accents"}}
        {{~> pitch-accent-list format='text'~}}
    {{/inline}}
    
    {{#*inline "pitch-accent-graphs"}}
        {{~> pitch-accent-list format='graph'~}}
    {{/inline}}
    
    {{#*inline "pitch-accent-positions"}}
        {{#regexReplace "<(.|\n)*?>" ""}}{{~> pitch-accent-list format='position'~}}{{/regexReplace}}
    {{/inline}}
    {{! End Pitch Accents }}
    

    Alternatively, you can use these handlebars to get one pitch accent only. This does not modify existing handlebars.


Introduced Handlebars

Definitions

Main Page: Definitions: Dictionary Placement

The most important handlebars that this package introduces is {jpmn-primary-definition}. This handlebars automatically selects the first monolingual or bilingual dictionary, depending on the opt-first-definition-type option.

To summarize the introduced definition handlebars:

Handlebars Description
{jpmn-primary-definition} The highest priority monolingual or bilingual dictionary (depending on the value of opt-first-definition-type).
{jpmn-secondary-definition} All bilingual dictionaries outside of the one selected in the primary definition.
{jpmn-extra-definitions} All monolingual dictionaries outside of the one selected in the primary definition.
{jpmn-utility-dictionaries} All dictionaries that fall outside the category of bilingual or monolingual. For example, JMnedict or JMdict Forms.

If you want to select a different dictionary, highlight the dictionary, or a portion of the definition before importing. This will override the primary definition with the selected dictionary / definition.

Frequency Sorting

This package introduces {jpmn-frequency-sort}, which behaves the exact same as Marv's {freq} handlebars. The only difference is that the options are placed at the very top of the handlebars, instead of within the function.

In other words, feel free to use this in the exact same way as you would with {freq}.

Other handlebars

  • TODO jpmn-sentence-bolded-furigana-plain
  • TODO binary field handlebars
  • link to appropriate yomichan template section

Plaintext Options

This section describes all the plaintext options, which are all prefixed with opt__plaintext__.

  • If you are not using jp-mining-note, all these options should be set to true by default. This means definitions are as minimal as possible in both internal HTML structure and in content.

  • If you are using jp-mining-note, then all of these should be set to false by default.

If you are looking for information about the other options, please see the Definitions page.

opt__plaintext__stylize-glossary

Setting this option to true will no longer stylize the definition handlebars for jp-mining-note usage, and instead stylizes it to be virtually the same as Yomichan's default HTML structure.

Differences between default Yomichan format and JPMN plaintext (click here)

There are a few minor differences between Yomichan's format and these non-stylized definitions:

  • The dictionary and tags are not italicized. This is to avoid seeing italic kanjis/kana.
  • The div that left-aligns the text is not present. If this breaks your card, (for example, the definition gets centered), try surrounding your definition field. For example, if your field name is Definition, then within your Anki card templates, surround {{ Definition }} with the following:

    <div style="text-align: left"> {{Definition}} </div>
    
  • Dictionaries with only one entry is formatted as a list of one element by default. This is usually not desired. To disable this behavior and make the behavior more like Yomichan, set opt__plaintext__one-dict-entry-only-no-list to true.

  • The first line for most dictionaries are removed by default. This can be controlled with the following options:

    • opt__plaintext__remove-first-line-enabled
    • opt-first-line-dicts-regex

    There are som dictionaries simply cannot have their first line be removed by the handlebars, due to its complicated internal structure. Those dictionaries are specified under opt-first-line-dicts-regex by default.

opt__plaintext__one-dict-entry-only-no-list

If this is true, then a definition that only contains one dictionary entry will export without being in a list.

For the following examples, we take the definition of 絨毯 from the 旺文社国語辞典 第十一版 dictionary.

床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
《季・冬》

  1. 床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
    《季・冬》

Note

If there are multiple definitions, then it is exported in a list format by default. This is almost never present in monolingual dictionaries, but almost always present for JMdict. For example, 地雷 (in the old JMdict dictionary) will always be exported as the following, regardless of the setting:

  1. (n, JMdict (English)) land mine
  2. (n, col, JMdict (English)) topic that sets someone off | sensitive topic | taboo topic | trigger
  3. (n, col, JMdict (English)) something that seems fine at first but turns out to be very bad (e.g. product, business) | booby trap | pitfall

opt__plaintext__remove-dictionary-tag

Whether the dictionary tag is exported or not.

じゅう‐たん【△絨△毯・△絨△緞】
床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
《季・冬》

(旺文社国語辞典 第十一版) じゅう‐たん【△絨△毯・△絨△緞】
床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
《季・冬》

opt__plaintext__remove-first-line-enabled

Whether the first line is exported or not.

床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
《季・冬》

じゅう‐たん【△絨△毯・△絨△緞】
床の敷物にする厚い毛織物。カーペット。「床に―を敷く」
《季・冬》

This affects almost all dictionaries by default. If you want to ignore certain dictionaries, use the opt-first-line-dicts-regex option as described here.


Compatibility with other Handlebars

These handlebars are fully compatable SO LONG AS your other handlebars are based off of the most recent set of default handlebars. A non-example is the classic animecard's {test}. {test} requires outdated handlebars in order to work, and is therefore incompatible with these handlebars.

There are two reasons why these handlebars are compatible with most other handlebars:

  • Everything is prefixed with jpmn (or _jpmn). These prefixes prevent the JPMN handlebars from overriding any other custom handlebars you may have defined.
  • These handlebars do not modify the default handlebars code. This is in order to preserve the original handlebars functionality, and so other handlebars can rely on the original handlebars to work properly.

Last update: July 10, 2023