markhavemann Posted October 12, 2022 at 03:16 AM Report Share Posted October 12, 2022 at 03:16 AM 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: To: 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(' ', " "); 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. 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: 4. Go to the "styling" section. Add the styling code from above: 5. Your pinyin should now have colours added automatically 2 1 Quote Link to comment Share on other sites More sharing options...
New Members 麻辣香锅 Posted May 6, 2023 at 03:03 AM New Members Report Share Posted May 6, 2023 at 03:03 AM 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! 1 Quote Link to comment Share on other sites More sharing options...
markhavemann Posted May 7, 2023 at 12:07 AM Author Report Share Posted May 7, 2023 at 12:07 AM 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. Quote Link to comment Share on other sites More sharing options...
New Members 麻辣香锅 Posted May 9, 2023 at 03:28 AM New Members Report Share Posted May 9, 2023 at 03:28 AM Thank you for the sample deck! It is now working without issues. 1 Quote Link to comment Share on other sites More sharing options...
markhavemann Posted August 16, 2023 at 02:27 AM Author Report Share Posted August 16, 2023 at 02:27 AM I've updated the code to work better, and the main post to make this a little clearer and easier to use hopefully. Quote Link to comment Share on other sites More sharing options...
davidadrian Posted October 30, 2023 at 02:41 AM Report Share Posted October 30, 2023 at 02:41 AM 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! Quote Link to comment Share on other sites More sharing options...
markhavemann Posted November 1, 2023 at 03:16 AM Author Report Share Posted November 1, 2023 at 03:16 AM 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.