Making stardict dictionary imports prettier using .lua script

I use FastWordQuery to import definitions from local stardict dictionaries to Anki. But the same dictionary looks pretty on Koreader (right) & but not so pretty on Ankidroid (left): (device onyx eink reader)

The .lua script inside the dictionary folder contains the following code:

return function(html)

    html = html:gsub('<rref[^>]*>[^<]*%.wav</rref>', '🔊')
    html = html:gsub('<rref[^>]*>[^<]*%.jpg</rref>', '⛶')
    html = html:gsub('<k[^>]*>[^<]*</k>', '')
    html = html:gsub('<c>', '<span>')
    html = html:gsub('</c>', '</span>')
    html = html:gsub('<c c="', '<span style="color:')
    html = html:gsub('"color:indigo"', '"color:#4B0082"')
    html = html:gsub('"color:darkgray"', '"color:#A9A9A9"')
    html = html:gsub('"color:lightcoral"', '"color:#F08080"')
    html = html:gsub('"color:lightseagreen"', '"color:#20B2AA"')
    html = html:gsub('"color:darkgoldenrod"', '"color:#B8860B"')   
    html = html:gsub('"color:orangered"', '"color:#B8860B"')   
    html = html:gsub('"color:sienna"', '"color:#B8860B"')   
    html = html:gsub('"color:darkred"', '"color:#B8860B"')   
    html = html:gsub('"color:navy"', '"color:#B8860B"')   
    html = html:gsub('"color:red"', '"color:#B8860B"')   

    return html
end

This code changes the .wav / .jpg text to icons, changes the color of some annoying words to grey etc. But this does not work on Anki.

How can I use the same .lua script to make it look as good as Koreader?

Anki does not support styling your HTML with lua. So your options are:

  • Translating your lua script to JavaScript. This might include one or more of the following:
    • Learn enough about lua and JavaScript to be able to do this by hand.
    • Use a lua to js transpiler. With a quick search i found lua.js, but i have not used it and cannot say if it is up for the task.
    • Use AI™. Paste in the lua script and ask for a JavaScript equivalent. Or past in your own translation efforts and ask for improvements. Or paste in the transpilation from lua.js and ask for improvements. In general, expect some errors and some nonsense code. But it might still be useful.
  • Throw your existing lua script away, and start from scratch with JavaScript and CSS.
1 Like

Thanks for the suggestions. I am trying ChatGPT to conver the lua file to js. It is telling me to put this code in styling tab:

<script>
function convertHtml(html) {
    html = html.replace(/<rref[^>]*>[^<]*\.wav<\/rref>/g, '🔊');
    html = html.replace(/<rref[^>]*>[^<]*\.jpg<\/rref>/g, '⛶');
    html = html.replace(/<k[^>]*>[^<]*<\/k>/g, '');
    html = html.replace(/<c>/g, '<span>');
    html = html.replace(/<\/c>/g, '</span>');
    html = html.replace(/<c c="/g, '<span style="color:');
    html = html.replace(/"color:indigo"/g, '"color:#4B0082"');
    html = html.replace(/"color:darkgray"/g, '"color:#A9A9A9"');
    html = html.replace(/"color:lightcoral"/g, '"color:#F08080"');
    html = html.replace(/"color:lightseagreen"/g, '"color:#20B2AA"');
    html = html.replace(/"color:darkgoldenrod"/g, '"color:#B8860B"');
    html = html.replace(/"color:orangered"/g, '"color:#B8860B"');
    html = html.replace(/"color:sienna"/g, '"color:#B8860B"');
    html = html.replace(/"color:darkred"/g, '"color:#B8860B"');
    html = html.replace(/"color:navy"/g, '"color:#B8860B"');
    html = html.replace(/"color:red"/g, '"color:#B8860B"');

    return html;
}
</script>

It is also telling me to use something like this in front / back back template:

{{Oxford ALD 8th Ed}}
{{#convertHtml}}{{Oxford ALD 8th Ed}}{{/convertHtml}}

I did both. But nothing is happening. Did I do something wrong? or is the code incorrect?

For reference, here is the code from stardict entry:

<k>society</k>
<c c="darkgray"> </c><b><c c="red">so·ci·ety</c></b>  <c c="rosybrown">[</c><c c="darkslategray"><b>society</b></c> <c c="darkslategray"><b>societies</b></c><c c="rosybrown">]</c> <abr>BrE</abr> <c c="darkgray"> </c><c c="darkcyan">[səˈsaɪəti]</c> <rref>z_society__gb_1.wav</rref> <abr>NAmE</abr> <c c="darkgray"> </c><c c="darkcyan">[səˈsaɪəti]</c> <rref>z_society__us_1.wav</rref> <c c="orange"> noun</c> <c c="darkgray">(</c><c c="rosybrown">pl.</c> <c c="darkgray"> </c><c c="darkslategray"><b>so·ci·eties</b></c><c c="darkgray">)</c>
<blockquote><c c="red"><b>1.</b></c> <c c="orangered">uncountable</c> <c c="darkgray"> </c>people in general, living together in communities</blockquote>

The javascript code you got was correctly converted, but the anki template seems completely hallucinated by AI. {{#name}} is used to conditionally show a part of your template, it will not invoke a function, and the template is nonsense.

The dictionary entrees are already converted in some way - anki does not understand the elements used in it, yet it still shows some formating - so a script that converts from them would have no use in your templates, you would have to somehow run it in koreader, before adding it to anki.

Can you please show the html code of your anki flashcard? On desktop it’s the <> button in the editor and ankidroid should just show it.

Here is the html code from Anki:

<k>society</k><br><c c="darkgray"> </c><b><c c="red">so·ci·ety</c></b>  <c c="rosybrown">[</c><c c="darkslategray"><b>society</b></c> <c c="darkslategray"><b>societies</b></c><c c="rosybrown">]</c> <abr>BrE</abr> <c c="darkgray"> </c><c c="darkcyan">[səˈsaɪəti]</c> <rref>z_society__gb_1.wav</rref> <abr>NAmE</abr> <c c="darkgray"> </c><c c="darkcyan">[səˈsaɪəti]</c> <rref>z_society__us_1.wav</rref> <c c="orange"> noun</c> <c c="darkgray">(</c><c c="rosybrown">pl.</c> <c c="darkgray"> </c><c c="darkslategray"><b>so·ci·eties</b></c><c c="darkgray">)</c><br><blockquote><c c="red"><b>1.</b></c> <c c="orangered">uncountable</c> <c c="darkgray"> </c>people in general, living together in communities</blockquote><br><blockquote><blockquote><ex>• </ex><ex>policies that will benefit society as a whole </ex></blockquote></blockquote>

Screenshot:

Wow thats… a mess. It’s not remotely valid html! I don’t know why is koreader (or whatever plugin this is) is not performing at least a rudimentary conversion to html…
I was able to slightly clean it up with this code, but you might need to tinker with it a bit more. Put this in styling alongside the rest of your flashcard styles:

blockquote{
  margin:0;
  margin-top: 10px;
}
rref{
  display:none;
}
[c="orange"],[c="red"],blockquote>ex:first-of-type{
  color: #aaa;
}
ex{
  margin-left:16px
}
br{
content: " ";
}

Also, remove that javascript function from the template, it’s not needed (and not meant to be in styling).

1 Like

Thanks a lot buddy. This is exaclty what I wanted. I did some tinkering to change the indentation for more readablity

It seems the Cambridge dictionary is not being affected by the code:

Here is the HTML code for that dictionary:

{
    [1] = {
        [1] = {
            ["definition"] = "\
h<div style=\"margin-left:1em\">—<span style=\"color:blue\"><b>hump</b></span> <i class=\"p\" style=\"color:green\">UK</i>  <i class=\"p\" style=\"color:green\">US</i>  /hʌmp/</div>\
<div style=\"margin-left:1em\"><span style=\"color:crimson\"><b>Ⅰ.</b></span> <i class=\"p\" style=\"color:green\">noun</i> <span style=\"color:mediumvioletred\"><b>(LUMP)</b></span></div>\
<div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>1.</b></span> <i class=\"p\" style=\"color:green\">F0</i> [<i class=\"p\" style=\"color:green\">C</i>] a large, round raised area or part: </div>\
<div style=\"margin-left:1em\"><span class=\"sec\">» <span class=\"ex\" style=\"color:steelblue\">The car hit a hump in the road and swerved.</span></span></div>\
<div style=\"margin-left:1em\">» <span style=\"color:indigo\"><sub>UK</sub></span> <span class=\"sec ex\" style=\"color:steelblue\">Local residents are asking for <b>speed</b> humps <span style=\"color:limegreen\">(= raised areas across the road which make people drive slowly)</span> to be installed in their street.</span></div>\
<div style=\"margin-left:1em\"><span style=\"color:olive\"><u>Thesaurus</u><sup>+</sup></span>: <a href=\"↑Masses and large amounts of things\">↑Masses and large amounts of things</a></div>\
<div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>2.</b></span> <i class=\"p\" style=\"color:green\">F0</i> [<i class=\"p\" style=\"color:green\">C</i>] a round raised part on a person's or animal's back: </div>\
<div style=\"margin-left:1em\"><span class=\"sec\">» <span class=\"ex\" style=\"color:steelblue\">Some types of camel have two humps and others have one.</span></span></div>\
<div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>→</b></span> <sub>SEE ALSO</sub> <span style=\"color:dodgerblue\"><b>HUMPBACKED</b></span>(<i class=\"p\" style=\"color:green\">Cf.</i> ↑<a href=\"humpbacked\">humpbacked</a>)</div>\
<div style=\"margin-left:1em\"><span style=\"color:olive\"><u>See picture</u></span>: hump</div>\
<div style=\"margin-left:1em\"><img align=\"top\" src=\"animals 1.jpg\" alt=\"animals 1.jpg\" /></div>\
<div style=\"margin-left:1em\"><span style=\"color:olive\"><u>Thesaurus</u><sup>+</sup></span>: <a href=\"↑Physical irregularities\">↑Physical irregularities</a></div>\
<div style=\"margin-left:1em\"><span style=\"color:crimson\"><b>Ⅱ.</b></span> <i class=\"p\" style=\"color:green\">verb</i> [<i class=\"p\" style=\"color:green\">I</i> or <i class=\"p\" style=\"color:green\">T</i>] <span style=\"color:indigo\"><sub>OFFENSIVE</sub></span> <span style=\"color:mediumvioletred\"><b>(HAVE SEX)</b></span> ↑<a href=\"Verb Endings for hump\">Verb Endings for hump</a></div>\
<div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>▸</b></span> <i class=\"p\" style=\"color:green\">F0</i> to have sex (with someone)</div>\
<div style=\"margin-left:1em\"><span style=\"color:olive\"><u>Thesaurus</u><sup>+</sup></span>: <a href=\"↑Sexual intercourse\">↑Sexual intercourse</a></div>\
<div style=\"margin-left:1em\"><span style=\"color:crimson\"><b>Ⅲ.</b></span> <i class=\"p\" style=\"color:green\">verb</i> [<i class=\"p\" style=\"color:green\">T</i> <i class=\"p\" style=\"color:green\">usually</i> <i class=\"p\" style=\"color:green\">+ adv/prep</i>] <span style=\"color:indigo\"><sub>INFORMAL</sub></span> <span style=\"color:mediumvioletred\"><b>(CARRY)</b></span> ↑<a href=\"Verb Endings for hump\">Verb Endings for hump</a></div>\
<div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>▸</b></span> <i class=\"p\" style=\"color:green\">F0</i> to carry or lift something heavy with difficulty: </div>\
<div style=\"margin-left:1em\"><span class=\"sec\">» <span class=\"ex\" style=\"color:steelblue\">My back really aches after humping those heavy boxes around all day.</span></span></div>\
<div style=\"margin-left:1em\"><span style=\"color:olive\"><u>Thesaurus</u><sup>+</sup></span>: <a href=\"↑Transferring and transporting objects\">↑Transferring and transporting objects</a></div>",
            ["dict"] = "Cambridge ALD 4th Ed.",
            ["word"] = "hump",
        },
    },
}

Can you please provide a similar code that will make it look like the Oxford dictionary? Also how do i remove the letter ‘h’ found at the beginning?

ChaGTP is suggesting the follwoing css code:

/* Custom CSS for the "oxstyle" field */
.oxstyle {
  font-family: bookerly;
  font-size: 20px;
  background-color: white;
  margin-left: 1em;
  margin-top: 10px;
}

.oxstyle rref {
  display: none;
}

.oxstyle [style*="color:orange"],
.oxstyle [style*="color:red"],
.oxstyle [style*="color:orangered"],
.oxstyle [style*="color:sienna"],
.oxstyle [style*="color:rosybrown"],
.oxstyle blockquote>ex:first-of-type {
  color: #aaa;
}

.oxstyle ex {
  margin-left: 5px;
}

.oxstyle br {
  content: " ";
}

But it is not working. Can anybody help?

The html code has been given in the post above it.

Nevermind. I used JS to do the same.

<br>
<br>
<div style='font-family: "Arial"; font-size: 25px; text-align: left;color: #aaa;'>---- Cambridge  ----</div>
<br>
<br>


<div 
 style="
  font-family: arial;
  font-size: 20px;
   sub { color: #aaa};
"
 class="camstyle"
>
  {{Cambridge ALD 4th Ed}}
</div>

<style>.camstyle sub{color:#aaa;}</style>


<script>
  function replaceWords() {
    var fieldContainer = document.querySelector('.camstyle');
    fieldContainer.innerHTML = fieldContainer.innerHTML

      .replace(/h<div style="margin-left:1em">/g, '<div style="margin-left:1em">')
      .replace(/<div style=\"margin-left:1em\">—/g, '<div style=\"margin-left:0em\">—')
      .replace(/<div style="margin-left:1em"><span style="color:crimson">/g, '<div style="margin-left:0.0em"><span style="color:crimson">')
      .replace(/<div style="margin-left:1em"><span class="sec">/g, '<div style="margin-left:2.3em"><span class="sec">')
      .replace(/<div style=\"margin-left:1em\">» <span style=\"color:indigo\">/g, '<div style=\"margin-left:2.3em\">» <span style=\"color:indigo\">')

      .replace(/<br><div style="margin-left:1em"><span style="color:olive"><u>Word Builder<\/u><\/span>:/g, '')
      .replace(/<br><div style=\"margin-left:1em\"><span style=\"color:olive\"><u>Thesaurus/g, '<div style="display:none;">')
      .replace(/<br><div style=\"margin-left:1em\"><img align=\"top\" src/g, '<div style="display:none;">')
      .replace(/ ↑<a href/g, '<a style="display:none;"')
      .replace(/<br><div style=\"margin-left:1em\"><span style=\"color:darkred\"><b>→/g, '<div style="display:none;">')
      .replace(/<br><div style=\"margin-left:1em\"><span style=\"color:olive\"><u>See picture</g, '<div style="display:none;">')
      .replace(/\[([^\]]+)\]/g, '<span style="color: #aaa">[$1]</span>')
      .replace(/<br><div style="margin-left:1em"><span style="color:lightgray">• • •<\/span><\/div>/g, '')
      .replace(/<br><div style="margin-left:1em">–<i><span style="color:darkgreen">/g, '<div style="display:none">')

      .replace(/style="color:midnightblue"/g, 'style="color: #aaa"')
      .replace(/style="color:darkblue"/g, 'style="color: #aaa"')
      .replace(/color:steelblue/g, '')
      .replace(/color:darkred/g, '')
      .replace(/color:crimson/g, '')
      .replace(/color:blue/g, '')
      .replace(/color:green/g, 'color: #aaa')
      .replace(/color:mediumvioletred/g, 'color: #aaa')
      .replace(/color:indigo/g, 'color: #aaa')
      .replace(/color:limegreen/g, 'color: #aaa')
      .replace(/color:olive/g, 'color: #aaa')
      .replace(/color:dodgerblue/g, 'color: #aaa');

  }

  setTimeout(replaceWords, 0);
</script>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.