Jump to content
Chinese-Forums
  • Sign Up

Anki: Add Tone Colours to Pinyin Automatically


markhavemann

Recommended Posts

Update 16 Aug 2023:

- Improved code to make things cleaner and easier to use

- Added support for multiple separate pinyin fields to be coloured at the same time

 

Automatically add tone colours to your pinyin

I couldn't find any solutions that I liked on the internet, so I made my own to do this.
 

- Works on mobile (ankidroid, anki mobile) and desktop.

- Different colours for day/night mode

 

Here is a sample deck with a note type with all the code working, and instructions below:

?Pinyin Colour Test?.apkg

Alternate download link: here

 

Video showing what it looks like and how to use it: https://www.youtube.com/watch?v=kR7vMMCVlcs

 

Description:

- This is Javascript and not an Anki plugin, so it can work ok mobile too.

- It adds colours on the fly every time you load a card, this is to avoid adding styles directly to the pinyin data in every single card, making it much more flexible, and keeping notes cleaner and easier to edit.

 

From:

image.thumb.png.a24f5275ddf78892f5be8748fd41dbce.png

To:

image.thumb.png.8a177a9abdd4ea50527663ab0cc1b2fc.png
 

 

What it can add colours to:

  • pòfǔchénzhōu (no spaces between syllables)
  • pò fǔ chén zhōu (spaces between syllables)
  • pòfǔ chénzhōu (a combination of the two)
  • pòfǔchén<b>zhōu</b> (also works with html tags, but not thoroughly tested)

 

What it doesn't work for:

  • "My chengyu is: pòfǔ chénzhōu"  (other text mixed in with pinyin - you will get weird results. I might fix this later and make it more flexible)

 

The Code:

 

Pinyin Field:

Spoiler

<span class="auto-pinyin">{{ChangeThisToYourPinyinFieldName}}</span>

OR

Spoiler

<div class="auto-pinyin">{{ChangeThisToYourPinyinFieldName}}</div>

OR

Spoiler

any other tag with the auto-pinyin class

 

Note: Multiple different instances are supported, so you can add multiple different <span>'s or <div>'s with this class, and colours will be added to all of them.

 

Main Code (put this at the bottom of the side of the card which has the pinyin field):

Note: copy this from the downloaded anki deck template. Copying directly from chrome seems to mess something up and causes the code to not work

Spoiler

<!-- ------- -->
<!-- ------- -->
<!-- ------- -->
<!-- SCRIPTS -->
<!-- ------- -->
<!-- ------- -->
<!-- ------- -->

<script>

window.Syllables = populateSyllables();
    
initialise();

function initialise()
{

    let allPinyin = document.getElementsByClassName("auto-pinyin");

    for(const pinyinDomObject of allPinyin)
    {
        pinyinDomObject.innerHTML = colourisePinyin(pinyinDomObject.innerText);
    }
}

// <!-- --------------------------------- -->
// <!-- SPLIT & COLORIZE PINYIN FUNCTIONS -->
// <!-- --------------------------------- -->

// Pinyin splitter adapted from: 
// https://github.com/pepebecker/pinyin-split
function normalizePinyin(text){
  text = text.normalize('NFD').replace(/\u0304|\u0301|\u030c|\u0300/g, '')
  return text.normalize('NFC').replace(/(\w|ü)[1-5]/gi, '$1').toLowerCase()
}

function colourisePinyin(pinyinContent)
{
    output = '';
    pinyinContent = pinyinContent.toString();
    //replace nbsp with space char - necessary in Anki
    pinyinContent = pinyinContent.replace(/\u00a0/g, " "); 
    //replace html nbsp with space char
    pinyinContent = pinyinContent.replace('&nbsp;', " "); 

    pinyinContent = pinyinContent.split(' ');
    pinyinContent = pinyinSplit(pinyinContent);

    for (i = 0; i < pinyinContent.length; i++) {
        if(pinyinContent.match(/.*[āēīōūǖĀĒĪŌŪǕ].*/g))
            output = output + '<span class="t1">' + pinyinContent + '</span> '; 
        else if(pinyinContent.match(/.*[áéíóúǘÁÉÍÓÚǗ].*/g))
            output = output + '<span class="t2">' + pinyinContent + '</span> '; 
        else if(pinyinContent.match(/.*[ǎěǐǒǔǚǍĚǏǑǓǙ].*/g))
            output = output + '<span class="t3">' + pinyinContent + '</span> '; 
        else if(pinyinContent.match(/.*[àèìòùǜÀÈÌÒÙǛ].*/g))
            output = output + '<span class="t4">' + pinyinContent + '</span> '; 
        else 
            output = output + '<span class="t5">' + pinyinContent + '</span> '; 
    }
    return output
}

function pinyinSplit(text, everything=false, wrapInList=false) 
{
    const list = Array()
    text = text.toString();
    let prevWordFound = false
    let wordEnd = text.length
    while (wordEnd > 0) {
    let count = wordEnd
    let wordFound = false
    while (count > 0) {
      const word = text.substring(wordEnd - count, wordEnd)
      if (window.Syllables.includes(normalizePinyin(word))) {
        wordFound = true
        list.push(wrapInList ? [word] : word)
        wordEnd -= (count - 1)
        break
      }
      count--
    }
    if (!wordFound && everything) {
      const prevIndex = list.length - 1
      const prevEntry = list[prevIndex]
      if (wordEnd === text.length || typeof prevEntry === 'object' || prevWordFound) {
        list.push(text[wordEnd - 1])
      }
      else if (typeof prevEntry === 'string') {
        list[prevIndex] = text[wordEnd - 1] + prevEntry
      }
    }
    wordEnd --
    prevWordFound = wordFound
    }
    return list.reverse()
}

function populateSyllables()
{
    return [
        "a",
        "ai",
        "an",
        "ang",
        "ao",
        "ba",
        "bai",
        "ban",
        "bang",
        "bao",
        "bei",
        "ben",
        "beng",
        "bi",
        "bian",
        "biao",
        "bie",
        "bin",
        "bing",
        "bo",
        "bu",
        "ca",
        "cai",
        "can",
        "cang",
        "cao",
        "ce",
        "cei",
        "cen",
        "ceng",
        "cha",
        "chai",
        "chan",
        "chang",
        "chao",
        "che",
        "chen",
        "cheng",
        "chi",
        "chong",
        "chou",
        "chu",
        "chua",
        "chuai",
        "chuan",
        "chuang",
        "chui",
        "chun",
        "chuo",
        "ci",
        "cong",
        "cou",
        "cu",
        "cuan",
        "cui",
        "cun",
        "cuo",
        "da",
        "dai",
        "dan",
        "dang",
        "dao",
        "de",
        "dei",
        "den",
        "deng",
        "di",
        "dian",
        "diao",
        "die",
        "ding",
        "diu",
        "dong",
        "dou",
        "du",
        "duan",
        "dui",
        "dun",
        "duo",
        "e",
        "ei",
        "en",
        "er",
        "fa",
        "fan",
        "fang",
        "fei",
        "fen",
        "feng",
        "fo",
        "fou",
        "fu",
        "ga",
        "gai",
        "gan",
        "gang",
        "gao",
        "ge",
        "gei",
        "gen",
        "geng",
        "gong",
        "gou",
        "gu",
        "gua",
        "guai",
        "guan",
        "guang",
        "gui",
        "gun",
        "guo",
        "ha",
        "hai",
        "han",
        "hang",
        "hao",
        "he",
        "hei",
        "hen",
        "heng",
        "hm",
        "hng",
        "hong",
        "hou",
        "hu",
        "hua",
        "huai",
        "huan",
        "huang",
        "hui",
        "hun",
        "huo",
        "ji",
        "jia",
        "jian",
        "jiang",
        "jiao",
        "jie",
        "jin",
        "jing",
        "jiong",
        "jiu",
        "ju",
        "juan",
        "jue",
        "jun",
        "ka",
        "kai",
        "kan",
        "kang",
        "kao",
        "ke",
        "kei",
        "ken",
        "keng",
        "kong",
        "kou",
        "ku",
        "kua",
        "kuai",
        "kuan",
        "kuang",
        "kui",
        "kun",
        "kuo",
        "lü",
        "la",
        "lai",
        "lan",
        "lang",
        "lao",
        "le",
        "lüe",
        "lei",
        "leng",
        "li",
        "lia",
        "lian",
        "liang",
        "liao",
        "lie",
        "lin",
        "ling",
        "liu",
        "long",
        "lou",
        "lu",
        "luan",
        "lun",
        "luo",
        "m",
        "ma",
        "mai",
        "man",
        "mang",
        "mao",
        "me",
        "mei",
        "men",
        "meng",
        "mi",
        "mian",
        "miao",
        "mie",
        "min",
        "ming",
        "miu",
        "mo",
        "mou",
        "mu",
        "n",
        "nü",
        "na",
        "nai",
        "nan",
        "nang",
        "nao",
        "ne",
        "nüe",
        "nei",
        "nen",
        "neng",
        "ng",
        "ni",
        "nian",
        "niang",
        "niao",
        "nie",
        "nin",
        "ning",
        "niu",
        "nong",
        "nou",
        "nu",
        "nuan",
        "nuo",
        "o",
        "ou",
        "pa",
        "pai",
        "pan",
        "pang",
        "pao",
        "pei",
        "pen",
        "peng",
        "pi",
        "pian",
        "piao",
        "pie",
        "pin",
        "ping",
        "po",
        "pou",
        "pu",
        "qi",
        "qia",
        "qian",
        "qiang",
        "qiao",
        "qie",
        "qin",
        "qing",
        "qiong",
        "qiu",
        "qu",
        "quan",
        "que",
        "qun",
        "ran",
        "rang",
        "rao",
        "re",
        "ren",
        "reng",
        "ri",
        "rong",
        "rou",
        "ru",
        "rua",
        "ruan",
        "rui",
        "run",
        "ruo",
        "sa",
        "sai",
        "san",
        "sang",
        "sao",
        "se",
        "sei",
        "sen",
        "seng",
        "sha",
        "shai",
        "shan",
        "shang",
        "shao",
        "she",
        "shei",
        "shen",
        "sheng",
        "shi",
        "shou",
        "shu",
        "shua",
        "shuai",
        "shuan",
        "shuang",
        "shui",
        "shun",
        "shuo",
        "si",
        "song",
        "sou",
        "su",
        "suan",
        "sui",
        "sun",
        "suo",
        "ta",
        "tai",
        "tan",
        "tang",
        "tao",
        "te",
        "teng",
        "ti",
        "tian",
        "tiao",
        "tie",
        "ting",
        "tong",
        "tou",
        "tu",
        "tuan",
        "tui",
        "tun",
        "tuo",
        "wa",
        "wai",
        "wan",
        "wang",
        "wei",
        "wen",
        "weng",
        "wo",
        "wu",
        "xi",
        "xia",
        "xian",
        "xiang",
        "xiao",
        "xie",
        "xin",
        "xing",
        "xiong",
        "xiu",
        "xu",
        "xuan",
        "xue",
        "xun",
        "ya",
        "yan",
        "yang",
        "yao",
        "ye",
        "yi",
        "yin",
        "ying",
        "yong",
        "you",
        "yu",
        "yuan",
        "yue",
        "yun",
        "za",
        "zai",
        "zan",
        "zang",
        "zao",
        "ze",
        "zei",
        "zen",
        "zeng",
        "zha",
        "zhai",
        "zhan",
        "zhang",
        "zhao",
        "zhe",
        "zhei",
        "zhen",
        "zheng",
        "zhi",
        "zhong",
        "zhou",
        "zhu",
        "zhua",
        "zhuai",
        "zhuan",
        "zhuang",
        "zhui",
        "zhun",
        "zhuo",
        "zi",
        "zong",
        "zou",
        "zuan",
        "zui",
        "zun",
        "zuo",
        "zu"
    ]
}
 </script>
 

 

Styles:

Spoiler

.t1{ color: #FF6666; display: inline;}

.t2{ color: #02B31C; display: inline;}

.t3{ color: #1510F0; display: inline;}

.t4{ color: #E299FF; display: inline;}

.t5{ color: #777; display: inline;}

 

.nightMode .t1{ color: #FF6666; display: inline;}

.nightMode .t2{ color: #02B31C; display: inline;}

.nightMode .t3{ color: #ACABF8; display: inline;}

.nightMode .t4{ color: #E299FF; display: inline;}

.nightMode .t5{ color: #B0B0B0; display: inline;}

 

 

 How To Do It:

 

 

1. Use an existing note type, or create a new note with a pinyin field.

 

 Note: You don't need to call it "Pinyin", you can call it whatever you want and just use your own field name.

image.thumb.png.bf560482d59c8272d2724f89afaf2045.png

 

2. Edit the card type that you want to add colours to. Go to the side that you want to (front or back) Add the pinyin field like this:

 

<span class="auto-pinyin">{{YourPinyinFieldName}}</span> 

 

(Note: change "YourPinyinFieldName" to whatever you called your pinyin field in Anki.)

 

3. At the very bottom of the same card side, paste the "main code" content:

 

image.thumb.png.c385d1f6079435670dfb70b2f162ed11.png

 

4. Go to the "styling" section. Add the styling code from above:

 

image.thumb.png.865b0f2b7624c2950c16ad06579fb26a.png

 

5. Your pinyin should now have colours added automatically

 

  • Like 2
  • Helpful 1
Link to comment
Share on other sites

  • 6 months later...
  • New Members

Hi Mark, I tried to use your solution in my Anki, however, it didn't work. I am not sure what I did wrong, as your explanation is very straightforward.

Would it maybe be possible to upload a sample deck with the note type that I can just import? I really would like to use color coded pinyin.

Thank you!

  • Like 1
Link to comment
Share on other sites

On 5/6/2023 at 11:03 AM, 麻辣香锅 said:

Hi Mark, I tried to use your solution in my Anki, however, it didn't work. I am not sure what I did wrong, as your explanation is very straightforward.

Would it maybe be possible to upload a sample deck with the note type that I can just import? I really would like to use color coded pinyin.

Thank you!

I should have done this from the start. I've uploaded a deck above with a more simplified version of what I already made.

 

I can't link the file that I uploaded in this reply, so you need to scroll all the way to the top of the main post to get the Anki deck file.

 

I'll update the main post when I have time but the new version supports multiple pinyin fields. Anything with a class of "auto-pinyin" will have colour added according to its contents.

 

You're also welcome to post an export of a sample of your note type and I'll figure out what's wrong for you.

Link to comment
Share on other sites

  • 3 months later...
  • 2 months later...

Hi Mark, would you be able to link to your sample deck on your youtube channel or somewhere else where I can downlaod the Anki deck? Copying and pasting the code isn't working for me and I can't access the anki deck from here without making an account and I can't seem to make an account no matter if its through FB, X, or using my gmail. Thanks!

Link to comment
Share on other sites

On 10/30/2023 at 10:41 AM, davidadrian said:

Hi Mark, would you be able to link to your sample deck on your youtube channel or somewhere else where I can downlaod the Anki deck? Copying and pasting the code isn't working for me and I can't access the anki deck from here without making an account and I can't seem to make an account no matter if its through FB, X, or using my gmail. Thanks!

Try downloading from here and let me know if it doesn't work.

 

I've added an alternate link to the main post and I'll add to YouTube too.

Link to comment
Share on other sites

Join the conversation

You can post now and select your username and password later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Click here to reply. Select text to quote.

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...