Skip to content

joaocarvalhomiranda/TheUnofficialTinycardsDeckExporter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 

Repository files navigation

The Unofficial Tinycards Deck Exporter

What is The Unofficial Tinycards Deck Exporter?

The Unofficial Tinycards Deck Exporter is a tool to export Tinycards decks.

What was Tinycards?

Tinycards was an application (and website) created by Duolingo that enabled users to create and share flashcard decks. It served as a companion tool to their main application (Duolingo) for the memorization of language vocabulary but also for any other knowledge area, as it was not language-restricted.

On June 1, 2020, Duolingo announced that Tinycards would be disabled on September 1, 2020. The creation of new decks and edition of unfinished decks was disabled at the time of the announcement.

Duolingo provided a way for the users to download their existing data in CSV, a format received with strangeness by users accustomed to the user-friendly design of Tinycards. From the comments it was visible that many users perceived the cards as existing on their own and not as a group of different types of information rendered on the screen to create virtual cards that can be represented in different platforms: "I can see the data in the CSV, but I don't see the cards". A forum thread was created by users just to help each other make sense of the data exported.

This motivated the creation of the deck exporter, for users to keep both their data and the cards as they were used to see them in Tinycards.

How does the deck exporter work?

There are two ways of using it: with a bookmarklet or with Tampermonkey. Both of them will create a zip file that you can download with the exported deck. The zip file will contain, among other relevant data, the multimedia resources associated with the deck you're exporting, the cards, a CSV file and an HTML file, which you can use to easily process the exported info and move it to a new flashcard system of your choice.

Bookmarklet

Create a new bookmark in your bookmarks toolbar, give it a name (e.g. "Export"), and copy this code to the URL field:

javascript:(function()%7Bconst%20proxyAddress%3D%22https%3A%2F%2Fapi.allorigins.win%2Fraw%3Furl%3D%22%3Bvar%20logData%3D%22%22%2CerrorsFound%3D!1%2CerrorsFileDownload%3D!1%2CerrorGettingDeckData%3D!1%3Bfunction%20log(e%2Cr%2Ct)%7Bswitch(r%3D(new%20Date).toLocaleString()%2B%22%20%22%2Br%2Cvoid%200!%3D%3Dt%26%26(t%3DJSON.stringify(t%2Cnull%2C4))%2Ce)%7Bcase%22log%22%3Avoid%200%3D%3D%3Dt%3Fconsole.log(r)%3Aconsole.log(r%2Ct)%3Bbreak%3Bcase%22error%22%3AerrorsFound%3D!0%2Cvoid%200%3D%3D%3Dt%3Fconsole.error(r)%3Aconsole.error(r%2Ct)%3Bbreak%3Bdefault%3Aconsole.log(%22Unknown%20log%20type%3A%20%22%2Ce)%2Cvoid%200%3D%3D%3Dt%3Fconsole.log(%22Message%20to%20log%20was%3A%20%22%2Cr)%3Aconsole.log(%22Message%20to%20log%20was%3A%20%22%2Cr%2Ct)%7DlogData%2B%3Dvoid%200%3D%3D%3Dt%3F%22%5Cn%22%2Br%3A%22%5Cn%22%2Br%2Bt%7Dfunction%20loadScripts()%7Btry%7Bfor(var%20scriptsJS%3D%5B%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjszip%2F3.3.0%2Fjszip.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjszip-utils%2F0.1.0%2Fjszip-utils.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2FFileSaver.js%2F1.3.8%2FFileSaver.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fdom-to-image%2F2.6.0%2Fdom-to-image.min.js%22%5D%2Cindex%3D0%3Bindex%3CscriptsJS.length%3B%2B%2Bindex)%7Bvar%20script%3Ddocument.createElement(%22script%22)%3Bscript.src%3DscriptsJS%5Bindex%5D%2Cscript.type%3D%22text%2Fjavascript%22%2CinjectScript(script.src).then(()%3D%3E%7Blog(%22log%22%2C%22Script%20loaded!%22)%7D).catch(e%3D%3E%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20injectScript%3A%20%22%2Ce)%7D)%7Dfunction%20injectScript(e)%7Breturn%20new%20Promise((r%2Ct)%3D%3E%7Blog(%22log%22%2C%22Loading%20script%3A%20%22%2Ce)%3Bconst%20o%3Ddocument.createElement(%22script%22)%3Bo.src%3De%2Co.addEventListener(%22load%22%2Cr)%2Co.addEventListener(%22error%22%2Ce%3D%3Et(e.error))%2Cdocument.head.appendChild(o)%7D)%7Dvar%20scriptsJQuery%3D%5B%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjquery%2F3.5.1%2Fjquery.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjquery.blockUI%2F2.70%2Fjquery.blockUI.min.js%22%5D%3B(async()%3D%3E%7Bfor(let%20i%3D0%3Bi%3CscriptsJQuery.length%3Bi%2B%2B)%7Bconst%20resp%3Dawait%20fetch(scriptsJQuery%5Bi%5D)%2Ctext%3Dawait%20resp.text()%3Beval(text)%7D%7D)()%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20loadScripts%3A%20%22%2Ce)%7D%7Dfunction%20updateProgress(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20updateProgress%3A%20message%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bdocument.querySelectorAll(%22.blockMsg%22)%5B0%5D.innerText%3De%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20updateProgress%3A%20%22%2Ce)%7D%7Dasync%20function%20doIt()%7Btry%7B!function%20e(r)%7Bwindow.jQuery%26%26window.%24.blockUI%3Fr()%3AsetTimeout(function()%7Be(r)%7D%2C100)%7D(function()%7B!async%20function()%7Btry%7Blog(%22log%22%2C%22Starting%20export%22)%3Bvar%20e%3Dwindow.location.pathname.split(%22%2Fdecks%2F%22).pop().split(%22%2F%22)%5B0%5D%3B0%3D%3De.length%7C%7C0%3D%3Ddocument.getElementsByClassName(%22_15CbF%22).length%3Falert(%22This%20is%20not%20a%20deck%20page!%20You%20need%20to%20go%20to%20the%20Tinycards%20page%20of%20the%20deck%20you%20want%20to%20export!%22)%3A(window.%24.blockUI(%7Bmessage%3A%22Exporting%20deck...%22%7D)%2Cdocument.getElementsByClassName(%22_15CbF%22)%5B1%5D.click()%2CupdateProgress(%22Retrieving%20style%20sheets...%22)%2Cawait%20embedStyleSheets()%2CupdateProgress(%22Retrieving%20fonts...%22)%2Cawait%20embedFonts()%2CupdateProgress(%22Retrieving%20images...%22)%2CproxifyImages()%2CembedImages()%2Cwindow.%24.getJSON(%22https%3A%2F%2Ftinycards.duolingo.com%2Fapi%2F1%2Fdecks%2Fuuid%3FcompactId%3D%22%2Be%2Cfunction(e)%7Bvar%20r%3De.uuid%3BupdateProgress(%22Retrieving%20deck's%20information...%22)%2CgetDeck(r)%7D))%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20startExport%3A%20%22%2Ce)%7D%7D()%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20doIt%3A%20%22%2Ce)%7D%7Dfunction%20getDeck(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getDeck%3A%20deckLongId%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blog(%22log%22%2C%22Getting%20deck%22)%2Cwindow.%24.getJSON(%22https%3A%2F%2Ftinycards.duolingo.com%2Fapi%2F1%2Fdecks%2F%22%2Be%2B%22%3Fattribution%3Dtrue%26expand%3Dtrue%22%2Casync%20function(e)%7Blog(%22log%22%2C%22deckData%3A%20%22%2Ce)%3Bvar%20r%3De.cardCount%2Ct%3Dnull!%3De.coverImageUrl%3Fe.coverImageUrl%3Ae.imageUrl%2Co%3De.description%2Cn%3De.fullname%2Ca%3De.name%2Ci%3De.picture.replace(%22https%22%2CproxyAddress%2B%22https%22)%2Cs%3De.username%2Cl%3De.slug%2B%22_%22%2Be.compactId%2Cd%3D%5B%5B%22Deck%20name%22%2Ca%5D%2C%5B%22Deck%20description%22%2Co%5D%2C%5B%22Creator%20username%22%2Cs%5D%2C%5B%22Creator%20name%22%2Cn%5D%2C%5B%22Number%20of%20cards%22%2Cr%5D%2C%5B%22Deck%20URL%22%2Cwindow.location%5D%5D.map(e%3D%3E'%22'%2Be.join('%22%2C%22')%2B'%22').join(%22%5Cn%22)%3Blog(%22log%22%2C%22deckMainInfo%3A%20%22%2Cd)%3Bvar%20c%3Dnew%20JSZip%3Bc.file(%22deckFullInfo.json%22%2CJSON.stringify(e%2Cnull%2C4))%2Cc.file(%22coverImage.jpg%22%2Ct.startsWith(%22data%3A%22)%3Ft.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(t)%2Ct.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2Cc.file(%22creatorPicture.png%22%2Ci.startsWith(%22data%3A%22)%3Fi.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(i)%2Ci.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2CupdateProgress(%22Retrieving%20cards'%20info...%22)%2Cc%3Dawait%20getDeckCardsInfo(e%2Cd%2Cc)%2CupdateProgress(%22Retrieving%20cards...%22)%2Cc%3Dawait%20everyoneSmile(c)%2CupdateProgress(%22Almost%20done.%20Generating%20the%20zip%20file...%22)%2Cawait%20new%20Promise(e%3D%3EsetTimeout(e%2C1e3))%2Clog(%22log%22%2C%22Generating%20zip%20file%22)%2Cc.file(%22log.txt%22%2ClogData)%2Cc.generateAsync(%7Btype%3A%22blob%22%7D).then(function(e)%7Bwindow.%24.unblockUI()%2CerrorGettingDeckData%3Falert(%22Could%20not%20download%20deck%20data.%20Please%20try%20again.%5CnYou%20can%20also%20check%20for%20errors%20found%20in%20the%20browser's%20console%20(F12)%20or%20in%20the%20log%20file%20included%20in%20the%20zip.%22)%3AerrorsFileDownload%3Falert(%22Some%20files%20could%20not%20be%20downloaded.%20Please%20check%20the%20zip%20file%20contents.%5CnYou%20can%20also%20check%20for%20errors%20found%20in%20the%20browser's%20console%20(F12)%20or%20in%20the%20log%20file%20included%20in%20the%20zip.%22)%3AerrorsFound%26%26alert(%22Some%20errors%20were%20found%20during%20the%20export%20process.%20Please%20check%20the%20browser's%20console%20(F12)%20or%20the%20log%20file%20in%20the%20zip.%22)%2CsaveAs(e%2Cl)%2CsetTimeout(function()%7Bwindow.location.reload()%7D%2C2e3)%7D).catch(e%3D%3E%7BerrorsFound%3D!0%2Cwindow.%24.unblockUI()%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20zip.generateAsync%3A%20%22%2Ce)%7D)%7D).fail(function(e%2Cr%2Ct)%7BerrorGettingDeckData%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20error%20getting%20deck%20data%3A%20%22%2Cr%2B%22%2C%20%22%2Bt)%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20%22%2Ce)%7D%7Dasync%20function%20getDeckCardsInfo(e%2Cr%2Ct)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20deckData%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20deckMainInfo%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dt)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blog(%22log%22%2C%22Getting%20deck%20cards%20info%22)%3Bfor(var%20o%3D%22%22%2Cn%3De.cards%2Ca%3D0%3Ba%3Cn.length%3Ba%2B%2B)%7Bvar%20i%3Dn%5Ba%5D%3Blog(%22log%22%2C%22card%20number%3A%20%22%2Ca)%3Bvar%20s%3D%22%22%2Cl%3D%22%22%2Cd%3D%22%22%2Cc%3D%22%22%2Cg%3Di.sides%3Blog(%22log%22%2C%22sides%20length%3A%20%22%2Cg.length)%3Bfor(var%20u%3D0%3Bu%3Cg.length%3Bu%2B%2B)%7Bvar%20f%3Dg%5Bu%5D%3Blog(%22log%22%2C%22side%3A%20%22%2Cf)%3Bvar%20p%3DNumber(a%2B1)%2Cm%3Dn.length.toString().length%2Ch%3D%22cardsUI%2Fcard_%22%2Bzerofy(p%2Cm)%2B%22_%22%2B(u%3F%22back%22%3A%22front%22)%2B%22.png%22%3Bu%3Fd%3Dh%3As%3Dh%3Bfor(var%20y%3D%22%22%2CR%3D0%3BR%3Cf.concepts.length%3BR%2B%2B)%7Bvar%20v%3Df.concepts%5BR%5D%3Blog(%22log%22%2C%22side%3A%20%22%2Cf)%3Bvar%20w%3Dv.fact%3Blog(%22log%22%2C%22fact%3A%20%22%2Cw)%3Bvar%20b%3DNumber(u%2B1)%2Cx%3Dg.length.toString().length%2CE%3DNumber(R%2B1)%2CS%3Df.concepts.length.toString().length%2Ck%3D%22%22%3B%22IMAGE%22%3D%3Dw.type%3F(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.jpg%22%2Clog(%22log%22%2C%22found%20image%20side%20at%20url%3A%20%22%2Cw.imageUrl)%2Ct.file(%22cards%2F%22%2Bk%2Cw.imageUrl.startsWith(%22data%3A%22)%3Fw.imageUrl.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(w.imageUrl)%2Cw.imageUrl.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D))%3A%22TEXT%22%3D%3Dw.type%3F(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.txt%22%2Clog(%22log%22%2C%22found%20text%20side%3A%20%22%2Cw.text)%2Cy%3Dy.concat(R%3F%22%20%2F%20%22%3A%22%22).concat(w.text)%2Ct.file(%22cards%2F%22%2Bk%2Cw.text)%2Cvoid%200!%3D%3Dw.ttsUrl%26%26(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.mp3%22%2Clog(%22log%22%2C%22found%20tts%3A%20%22%2Cw.ttsUrl)%2Ct.file(%22cards%2F%22%2Bk%2Cw.ttsUrl.startsWith(%22data%3A%22)%3Fw.ttsUrl.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(w.ttsUrl)%2Cw.ttsUrl.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)))%3Alog(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20Unexpected%20concept%20type%3A%20%22%2Bw.type%2Cw)%3Bfor(var%20P%3Dv.noteFacts%2CC%3D0%3BC%3CP.length%3BC%2B%2B)%7Bvar%20F%3DP%5BC%5D%2CO%3DNumber(C%2B1)%2CI%3DP.length.toString().length%2CT%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22_noteFact_%22%2Bzerofy(O%2CI)%2B%22.txt%22%3Blog(%22log%22%2C%22found%20note%20fact%3A%20%22%2CF)%2Ct.file(%22cards%2F%22%2BT%2CF)%7D%7Du%3Fc%3Dy%3Al%3Dy%7Do%3Do%2B'%22'%2Bs%2B'%22%2C%22'%2Bd%2B'%22%2C%22'%2Bl%2B'%22%2C%22'%2Bc%2B'%22%5Cn'%7Dt.file(%22cardsInfo.csv%22%2Cr%2B'%5Cn%22%22%5Cn%22%22%5Cn%22Front%20Card%20Image%22%2C%22Front%20Card%20Text%22%2C%22Back%20Card%20Image%22%2C%22Back%20Card%20Text%22%5Cn'%2Bo)%3Bvar%20D%3D%22%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3Cmeta%20charset%3D'utf-8'%2F%3E%3Cstyle%3Etable%2C%20th%2C%20td%20%7Bborder%3A%200px%20solid%20gray%3B%20border-collapse%3A%20collapse%3B%7D%20%23cards%20td%20%7Bmax-width%3A%20300px%3B%20min-width%3A%20200px%3B%7D%20%23deckInfo%20%7Bmargin-bottom%3A%2010px%3B%7D%20%23deckInfo%20td%20%7Bpadding%3A0%2020px%200%200%3B%7D%20img%20%7Bbox-shadow%3A%200%208px%2016px%200%20rgba(0%2C0%2C0%2C0.2)%3B%20border-radius%3A%2025px%2025px%2025px%2025px%7D%3C%2Fstyle%3E%3C%2Fhead%3E%3Cbody%3E%3Ch1%3E%22%2Br.split(%22%5Cn%22%2C1)%5B0%5D.split(%22%2C%22)%5B1%5D.replace(%2F(%5E%22)%7C(%22%24)%2Fg%2C%22%22)%2B%22%3C%2Fh1%3E%3Cdiv%3E%3Ctable%20id%3D'deckInfo'%3E%22%2Br.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Ctd%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Ftd%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Ftd%3E%3Ctd%3E%22).concat(%22%3C%2Ftable%3E%3C%2Fdiv%3E%22).replace(%2F(http%5B%5E%3C%5D%2B)(%3F%3D%3C)%2F%2C%22%3Ca%20href%3D'%241'%3E%241%3C%2Fa%3E%22)%2B%22%3Cdiv%3E%3Cp%3E%3Ca%20href%3D'.%2F'%3EBase%20folder%3C%2Fa%3E%3C%2Fp%3E%3C%2Fdiv%3E%5Cn%3Cdiv%3E%3Ctable%20id%3D'cards'%3E%22%2B'%22Front%20Card%20Image%22%2C%22Back%20Card%20Image%22%2C%22Front%20Card%20Text%22%2C%22Back%20Card%20Text%22%5Cn'.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Cth%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Fth%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Fth%3E%3Cth%3E%22)%2Bo.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Ctd%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Ftd%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Ftd%3E%3Ctd%3E%22).replace(%2F%3Ctd%3EcardsUI%5C%2F%2Fg%2C%22%3Ctd%3E%3Cimg%20src%3D'.%2FcardsUI%2F%22).replace(%2F.png%3C%5C%2Ftd%3E%2Fg%2C%22.png'%2F%3E%3C%2Ftd%3E%22).replace(%2Fsrc%3D%5C'(%5B%5E%5C'%5D%2B)%5C'%2Fg%2Cfunction(e%2Cr)%7Breturn%22alt%3D'%22%2Br.replace(%2F%5C.%5C%2Fcards%5B%5E%5C%2F%5D%2B%5C%2F(%5B%5E%5C.%5D%2B)%5C.png%2Fg%2C%22%241%22).replace(%2F_%2Fg%2C%22%20%22)%2B%22'%20src%3D'%22%2Br%2B%22'%22%7D)%2B%22%3C%2Ftable%3E%3C%2Fdiv%3E%3C%2Fbody%3E%3C%2Fhtml%3E%22%3Breturn%20t.file(%22cardsInfo.html%22%2CD)%2Ct%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20%22%2Ce)%7D%7Dfunction%20getBinaryFile(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getBinaryFile%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Breturn%20e.startsWith(%22data%3A%22)%3Flog(%22log%22%2C%22Getting%20binary%20file%3A%20data%20url%20received%22)%3Alog(%22log%22%2C%22Getting%20binary%20file%3A%20%22%2Ce)%2Cnew%20Promise(function(r%2Ct)%7BJSZipUtils.getBinaryContent(e%2Cfunction(e%2Co)%7Be%3Ft(e)%3Ar(o)%7D)%7D).catch(function(e)%7Breturn%20errorsFileDownload%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBinaryContent%3A%20%22%2Be)%2C%22ERROR%3A%20could%20not%20download%20this%20file%3A%20%22%2Be%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBinaryFile%3A%20%22%2Ce)%7D%7Dasync%20function%20flipCards()%7Btry%7Blog(%22log%22%2C%22Flipping%20cards%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22.ALWo1%22)%3Bfor(let%20r%20of%20e)r.classList.contains(%22PemDv%22)%3F(r.style.transform%3D%22rotateY(180deg)%22%2Cr.classList.remove(%22PemDv%22))%3A(r.style.transform%3D%22rotateY(0deg)%22%2Cr.classList.add(%22PemDv%22))%2Cr.removeAttribute(%22style%22)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C1e3))%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20flipCards%3A%20%22%2Ce)%7D%7Dfunction%20proxifyImages()%7Btry%7Blog(%22log%22%2C%22Proxifying%20images%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22img%22)%3Bfor(let%20r%20of%20e)r.src.startsWith(proxyAddress)%7C%7Cr.src.startsWith(%22data%3A%22)%7C%7C(r.src%3DproxyAddress%2Br.src)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20flipCards%3A%20%22%2Ce)%7D%7Dfunction%20embedImages()%7Btry%7Bfunction%20e(e%2Cr%2Ct)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20callback%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20o%3Ddocument.createElement(%22CANVAS%22)%2Cn%3Do.getContext(%222d%22)%2Ca%3Dnew%20Image%3Ba.crossOrigin%3D%22Anonymous%22%2Ca.onload%3Dfunction()%7Bo.height%3Da.height%2Co.width%3Da.width%2Cn.drawImage(a%2C0%2C0)%3Bvar%20e%3Do.toDataURL(t%7C%7C%22image%2Fpng%22)%3Br.call(this%2Ce)%2Co%3Dnull%7D%2Ca.src%3De%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20%22%2Ce)%7D%7Dlog(%22log%22%2C%22Embedding%20images%22)%3Bvar%20r%3Ddocument.querySelectorAll(%22img%22)%3Bfor(let%20t%20of%20r)e(t.src%2Cfunction(e)%7Bt.src%3De%7D)%2Ct.removeAttribute(%22srcset%22)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedImages%3A%20%22%2Ce)%7D%7Dasync%20function%20everyoneSmile(e)%7Btry%7Bif(log(%22log%22%2C%22Everyone%20smile%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20everyoneSmile%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Breturn%20e%3Dawait%20cardsSayCheese(e%2C%22front%22)%2Ce%3Dawait%20allTogetherNow(e%2C%22front%22)%2Cawait%20flipCards()%2Ce%3Dawait%20cardsSayCheese(e%2C%22back%22)%2Ce%3Dawait%20allTogetherNow(e%2C%22back%22)%2Cawait%20flipCards()%2Ce%7Dcatch(e)%7Blog(%22error%22%2C%22ERROR%3A%20everyoneSmile%3A%20%22%2Ce)%7D%7Dasync%20function%20convertToPng(e%2Cr%2Ct)%7Btry%7Bif(log(%22log%22%2C%22Converting%20to%20png%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20element%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(r%26%26void%200%3D%3D%3Dt)throw%20log(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20width%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blet%20o%3De.style.position%2Cn%3De.style.left%3Br%26%26(e.style.position%3D%22absolute%22%2Ce.style.left%3D%22-9999px%22%2Ce.style.width%3Dt%2B%22px%22%2Cdocument.body.appendChild(e))%3Bconst%20a%3Dawait%20domtoimage.toPng(e%2C%7Bstyle%3A%7Bposition%3Ao%2Cleft%3An%7D%7D).catch(function(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20domtoimage%3A%20%22%2Ce)%7D)%3Breturn%20r%26%26document.body.removeChild(e)%2Ca%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20%22%2Ce)%7D%7Dasync%20function%20cardsSayCheese(e%2Cr)%7Btry%7Bif(log(%22log%22%2C%22Cards%20say%20cheese%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20side%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20t%3Ddocument.querySelectorAll(%22.PemDv%22)%2Co%3Dt.length.toString().length%2Cn%3D0%3Bfor(let%20i%20of%20t)%7BupdateProgress(%22Retrieving%20card's%20%22%2Br%2B%22%20%22%2B(n%2B%3D1)%2B%22%2F%22%2Bt.length%2B%22...%22)%3Bvar%20a%3Dawait%20convertToPng(i)%3Bvoid%200%3D%3D%3Da%3Flog(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20data%20returned%20from%20convertToPng%20is%20undefined%22)%3Ae.file(%22cardsUI%2Fcard_%22%2Bzerofy(n%2Co)%2B%22_%22%2Br%2B%22.png%22%2Ca.startsWith(%22data%3A%22)%3Fa.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(a)%2Ca.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%7Dreturn%20e%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20%22%2Ce)%7D%7Dfunction%20zerofy(e%2Cr)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20zerofy%3A%20number%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20zerofy%3A%20length%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bfor(var%20t%3D%22%22%2Be%3Bt.length%3Cr%3B)t%3D%220%22%2Bt%3Breturn%20t%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20zerofy%3A%20%22%2Ce)%7D%7Dasync%20function%20allTogetherNow(e%2Cr)%7Btry%7Bif(log(%22log%22%2C%22All%20together%20now%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20side%20is%20undefined%22)%2C%22Parameter%20undefined%22%3BupdateProgress(%22Retrieving%20deck's%20%22%2Br%2B%22.%20This%20may%20take%20a%20while%20and%20slow%20down%20your%20browser%20temporarily.%20Please%20wait...%22)%2Cawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bvar%20t%3Ddocument.querySelectorAll(%22.ALWo1%3Anot(.PemDv)%22)%3Bfor(let%20e%20of%20t)e.style.display%3D%22none%22%3Bvar%20o%3Ddocument.querySelector(%22body%22).cloneNode(!0)%2Cn%3Do.querySelector(%22%23export%22)%3Bnull!%3Dn%26%26n.parentNode.removeChild(n)%3Bvar%20a%3Do.querySelectorAll(%22.blockOverlay%2C%20.blockMsg%22)%3Bif(null!%3Da)for(let%20e%20of%20a)null!%3De%26%26e.parentNode.removeChild(e)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bvar%20i%3Dawait%20convertToPng(o%2C!0%2Cdocument.querySelector(%22body%22).clientWidth)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bfor(let%20e%20of%20t)e.removeAttribute(%22style%22)%3Breturn%20void%200%3D%3D%3Di%3Flog(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20data%20returned%20from%20convertToPng%20is%20undefined%22)%3Ae.file(%22deck%22%2Br.charAt(0).toUpperCase()%2Br.slice(1)%2B%22.png%22%2Ci.startsWith(%22data%3A%22)%3Fi.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(i)%2Ci.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2Ce%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20%22%2Ce)%7D%7Dasync%20function%20getBase64File(e)%7Btry%7Bif(log(%22log%22%2C%22Getting%20a%20base64%20representation%20of%3A%20%22%2Ce)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getBase64File%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bconst%20r%3Dawait%20fetch(e)%2Ct%3Dawait%20r.blob()%2Co%3Dnew%20FileReader%3Breturn%20await%20new%20Promise((e%2Cr)%3D%3E%7Bo.onload%3De%2Co.onerror%3Dr%2Co.readAsDataURL(t)%7D)%2Co.result%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBase64File%3A%20%22%2Ce)%7D%7Dasync%20function%20embedFonts()%7Btry%7Blog(%22log%22%2C%22Embedding%20fonts%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22style%5Btype%3D'text%2Fcss'%5D%22)%3Bfor(let%20c%20of%20e)%7Bc.textContent%3Dc.textContent.replace(%2Furl%5C(%5C%2F%5C%2F%5B%5E%2C%5D%2B(woff%7Ctruetype%7Csvg)%22%5C)%2C%3F%2Fg%2C%22%22)%2Cc.textContent%3Dc.textContent.replace(%2Fformat%5C(%22woff2%5C%22%5C)%2C%2Fg%2C'format(%22woff2%22)')%2Cc.textContent%3Dc.textContent.replace(%2F%40font-face%2Fg%2C%22%5Cn%40font-face%22)%3Bfor(var%20r%2Ct%3D%2Furl%5C(%5C%2F%5C%2F%5B%5E)%5D%2B%5C)%2Fg%2Co%3D%5B%5D%3Bnull!%3D%3D(r%3Dt.exec(c.textContent))%3B)r%5B0%5D%3Dr%5B0%5D.replace(%2F%5C)%24%2F%2C%22%22).replace(%2F%5Eurl%5C(%2F%2C%22%22)%2Co.push(r%5B0%5D)%3Bfor(var%20n%3D%5B...new%20Set(o)%5D.sort()%2Ca%3D0%3Ba%3Cn.length%3Ba%2B%2B)%7Bvar%20i%3Dn%5Ba%5D%2Cs%3D%22%22%3Bi.startsWith(proxyAddress)%7C%7C(s%3DproxyAddress%2B%22https%3A%22%2Bi)%3Bvar%20l%3Dawait%20getBase64File(s)%2Cd%3Dnew%20RegExp(i%2C%22g%22)%3Bc.textContent%3Dc.textContent.replace(d%2Cl)%7D%7D%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedFonts%3A%20%22%2Ce)%7D%7Dasync%20function%20embedStyleSheets()%7Btry%7Basync%20function%20e(e)%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getExternalCSS%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20r%3Dnew%20XMLHttpRequest%3Breturn%20new%20Promise(function(t%2Co)%7Btry%7Br.onreadystatechange%3Dfunction()%7B4%3D%3Dr.readyState%26%26(r.status%3E%3D300%3Fo(%22ERROR%3A%20status%20code%20%3D%20%22%2Br.status)%3At(r.responseText))%7D%2Cr.open(%22get%22%2Ce)%2Cr.send()%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20getExternalCSS%3A%20Promise%3A%20%22%2Ce)%7D%7D)%7Dlog(%22log%22%2C%22Embedding%20style%20sheets%22)%3Bvar%20r%3Ddocument.querySelectorAll(%22LINK%5Bhref*%3D'.css'%5D%22)%3Bfor(let%20o%20of%20r)%7Bvar%20t%3Do.href%3Bt.startsWith(%22moz-extension%22)%7C%7C(t.startsWith(proxyAddress)%7C%7C(t%3DproxyAddress%2Bt)%2Cawait%20e(t).then(function(e)%7Bvoid%200%3D%3D%3De%26%26log(%22error%22%2C%22ERROR%3A%20getExternalCSS%3A%20result%20is%20undefined%22)%3Bvar%20r%3Ddocument.head%7C%7Cdocument.getElementsByTagName(%22head%22)%5B0%5D%2Ct%3Ddocument.createElement(%22style%22)%3Bt.type%3D%22text%2Fcss%22%2Ct.styleSheet%3Ft.styleSheet.cssText%3De%3At.appendChild(document.createTextNode(e))%2Cr.appendChild(t)%7D%2Cfunction(e)%7Blog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20%22%2Ce)%7D)%2Co.remove())%7D%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20%22%2Ce)%7D%7DloadScripts()%2CdoIt()%3B%7D)()%3B

The link you have now on your bookmarks toolbar is called a bookmarklet.

Then visit the Tinycards deck page you want to export and click on the bookmarklet from your bookmarks toolbar.

Tampermonkey

If you're familiar with Tampermonkey, use the following code:

// ==UserScript==
// @name         The Unofficial Tinycards Deck Exporter
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  Adds an Export button to a deck's page
// @description  https://github.com/joaocarvalhomiranda/TheUnofficialTinycardsDeckExporter
// @author       Joao Miranda
// @include      https://tinycards.duolingo.com/decks/*
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require      https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant        GM_addStyle
/* globals jQuery, $, waitForKeyElements */
// ==/UserScript==

(function() {
    'use strict';

    waitForKeyElements (".DFnrK", insertButton);

    function insertButton (node) {
        // get the deck long id
        var deckShortId = window.location.pathname.split('/decks/').pop().split('/')[0];

        // check if we are in a cards page
        // _15CbF is the class for the tab pair Lessons/Cards in the page
        if (deckShortId.length != 0 && document.getElementsByClassName('_15CbF').length != 0) {
            var element = document.createElement('a');
            element.id = 'export';
            element.innerHTML = '<button class="_3qc77 _3cTMR _1wpPZ">Export</button>';
            element.href = "javascript:(function()%7Bconst%20proxyAddress%3D%22https%3A%2F%2Fapi.allorigins.win%2Fraw%3Furl%3D%22%3Bvar%20logData%3D%22%22%2CerrorsFound%3D!1%2CerrorsFileDownload%3D!1%2CerrorGettingDeckData%3D!1%3Bfunction%20log(e%2Cr%2Ct)%7Bswitch(r%3D(new%20Date).toLocaleString()%2B%22%20%22%2Br%2Cvoid%200!%3D%3Dt%26%26(t%3DJSON.stringify(t%2Cnull%2C4))%2Ce)%7Bcase%22log%22%3Avoid%200%3D%3D%3Dt%3Fconsole.log(r)%3Aconsole.log(r%2Ct)%3Bbreak%3Bcase%22error%22%3AerrorsFound%3D!0%2Cvoid%200%3D%3D%3Dt%3Fconsole.error(r)%3Aconsole.error(r%2Ct)%3Bbreak%3Bdefault%3Aconsole.log(%22Unknown%20log%20type%3A%20%22%2Ce)%2Cvoid%200%3D%3D%3Dt%3Fconsole.log(%22Message%20to%20log%20was%3A%20%22%2Cr)%3Aconsole.log(%22Message%20to%20log%20was%3A%20%22%2Cr%2Ct)%7DlogData%2B%3Dvoid%200%3D%3D%3Dt%3F%22%5Cn%22%2Br%3A%22%5Cn%22%2Br%2Bt%7Dfunction%20loadScripts()%7Btry%7Bfor(var%20scriptsJS%3D%5B%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjszip%2F3.3.0%2Fjszip.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjszip-utils%2F0.1.0%2Fjszip-utils.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2FFileSaver.js%2F1.3.8%2FFileSaver.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fdom-to-image%2F2.6.0%2Fdom-to-image.min.js%22%5D%2Cindex%3D0%3Bindex%3CscriptsJS.length%3B%2B%2Bindex)%7Bvar%20script%3Ddocument.createElement(%22script%22)%3Bscript.src%3DscriptsJS%5Bindex%5D%2Cscript.type%3D%22text%2Fjavascript%22%2CinjectScript(script.src).then(()%3D%3E%7Blog(%22log%22%2C%22Script%20loaded!%22)%7D).catch(e%3D%3E%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20injectScript%3A%20%22%2Ce)%7D)%7Dfunction%20injectScript(e)%7Breturn%20new%20Promise((r%2Ct)%3D%3E%7Blog(%22log%22%2C%22Loading%20script%3A%20%22%2Ce)%3Bconst%20o%3Ddocument.createElement(%22script%22)%3Bo.src%3De%2Co.addEventListener(%22load%22%2Cr)%2Co.addEventListener(%22error%22%2Ce%3D%3Et(e.error))%2Cdocument.head.appendChild(o)%7D)%7Dvar%20scriptsJQuery%3D%5B%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjquery%2F3.5.1%2Fjquery.min.js%22%2C%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjquery.blockUI%2F2.70%2Fjquery.blockUI.min.js%22%5D%3B(async()%3D%3E%7Bfor(let%20i%3D0%3Bi%3CscriptsJQuery.length%3Bi%2B%2B)%7Bconst%20resp%3Dawait%20fetch(scriptsJQuery%5Bi%5D)%2Ctext%3Dawait%20resp.text()%3Beval(text)%7D%7D)()%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20loadScripts%3A%20%22%2Ce)%7D%7Dfunction%20updateProgress(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20updateProgress%3A%20message%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bdocument.querySelectorAll(%22.blockMsg%22)%5B0%5D.innerText%3De%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20updateProgress%3A%20%22%2Ce)%7D%7Dasync%20function%20doIt()%7Btry%7B!function%20e(r)%7Bwindow.jQuery%26%26window.%24.blockUI%3Fr()%3AsetTimeout(function()%7Be(r)%7D%2C100)%7D(function()%7B!async%20function()%7Btry%7Blog(%22log%22%2C%22Starting%20export%22)%3Bvar%20e%3Dwindow.location.pathname.split(%22%2Fdecks%2F%22).pop().split(%22%2F%22)%5B0%5D%3B0%3D%3De.length%7C%7C0%3D%3Ddocument.getElementsByClassName(%22_15CbF%22).length%3Falert(%22This%20is%20not%20a%20deck%20page!%20You%20need%20to%20go%20to%20the%20Tinycards%20page%20of%20the%20deck%20you%20want%20to%20export!%22)%3A(window.%24.blockUI(%7Bmessage%3A%22Exporting%20deck...%22%7D)%2Cdocument.getElementsByClassName(%22_15CbF%22)%5B1%5D.click()%2CupdateProgress(%22Retrieving%20style%20sheets...%22)%2Cawait%20embedStyleSheets()%2CupdateProgress(%22Retrieving%20fonts...%22)%2Cawait%20embedFonts()%2CupdateProgress(%22Retrieving%20images...%22)%2CproxifyImages()%2CembedImages()%2Cwindow.%24.getJSON(%22https%3A%2F%2Ftinycards.duolingo.com%2Fapi%2F1%2Fdecks%2Fuuid%3FcompactId%3D%22%2Be%2Cfunction(e)%7Bvar%20r%3De.uuid%3BupdateProgress(%22Retrieving%20deck's%20information...%22)%2CgetDeck(r)%7D))%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20startExport%3A%20%22%2Ce)%7D%7D()%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20doIt%3A%20%22%2Ce)%7D%7Dfunction%20getDeck(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getDeck%3A%20deckLongId%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blog(%22log%22%2C%22Getting%20deck%22)%2Cwindow.%24.getJSON(%22https%3A%2F%2Ftinycards.duolingo.com%2Fapi%2F1%2Fdecks%2F%22%2Be%2B%22%3Fattribution%3Dtrue%26expand%3Dtrue%22%2Casync%20function(e)%7Blog(%22log%22%2C%22deckData%3A%20%22%2Ce)%3Bvar%20r%3De.cardCount%2Ct%3Dnull!%3De.coverImageUrl%3Fe.coverImageUrl%3Ae.imageUrl%2Co%3De.description%2Cn%3De.fullname%2Ca%3De.name%2Ci%3De.picture.replace(%22https%22%2CproxyAddress%2B%22https%22)%2Cs%3De.username%2Cl%3De.slug%2B%22_%22%2Be.compactId%2Cd%3D%5B%5B%22Deck%20name%22%2Ca%5D%2C%5B%22Deck%20description%22%2Co%5D%2C%5B%22Creator%20username%22%2Cs%5D%2C%5B%22Creator%20name%22%2Cn%5D%2C%5B%22Number%20of%20cards%22%2Cr%5D%2C%5B%22Deck%20URL%22%2Cwindow.location%5D%5D.map(e%3D%3E'%22'%2Be.join('%22%2C%22')%2B'%22').join(%22%5Cn%22)%3Blog(%22log%22%2C%22deckMainInfo%3A%20%22%2Cd)%3Bvar%20c%3Dnew%20JSZip%3Bc.file(%22deckFullInfo.json%22%2CJSON.stringify(e%2Cnull%2C4))%2Cc.file(%22coverImage.jpg%22%2Ct.startsWith(%22data%3A%22)%3Ft.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(t)%2Ct.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2Cc.file(%22creatorPicture.png%22%2Ci.startsWith(%22data%3A%22)%3Fi.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(i)%2Ci.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2CupdateProgress(%22Retrieving%20cards'%20info...%22)%2Cc%3Dawait%20getDeckCardsInfo(e%2Cd%2Cc)%2CupdateProgress(%22Retrieving%20cards...%22)%2Cc%3Dawait%20everyoneSmile(c)%2CupdateProgress(%22Almost%20done.%20Generating%20the%20zip%20file...%22)%2Cawait%20new%20Promise(e%3D%3EsetTimeout(e%2C1e3))%2Clog(%22log%22%2C%22Generating%20zip%20file%22)%2Cc.file(%22log.txt%22%2ClogData)%2Cc.generateAsync(%7Btype%3A%22blob%22%7D).then(function(e)%7Bwindow.%24.unblockUI()%2CerrorGettingDeckData%3Falert(%22Could%20not%20download%20deck%20data.%20Please%20try%20again.%5CnYou%20can%20also%20check%20for%20errors%20found%20in%20the%20browser's%20console%20(F12)%20or%20in%20the%20log%20file%20included%20in%20the%20zip.%22)%3AerrorsFileDownload%3Falert(%22Some%20files%20could%20not%20be%20downloaded.%20Please%20check%20the%20zip%20file%20contents.%5CnYou%20can%20also%20check%20for%20errors%20found%20in%20the%20browser's%20console%20(F12)%20or%20in%20the%20log%20file%20included%20in%20the%20zip.%22)%3AerrorsFound%26%26alert(%22Some%20errors%20were%20found%20during%20the%20export%20process.%20Please%20check%20the%20browser's%20console%20(F12)%20or%20the%20log%20file%20in%20the%20zip.%22)%2CsaveAs(e%2Cl)%2CsetTimeout(function()%7Bwindow.location.reload()%7D%2C2e3)%7D).catch(e%3D%3E%7BerrorsFound%3D!0%2Cwindow.%24.unblockUI()%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20zip.generateAsync%3A%20%22%2Ce)%7D)%7D).fail(function(e%2Cr%2Ct)%7BerrorGettingDeckData%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20error%20getting%20deck%20data%3A%20%22%2Cr%2B%22%2C%20%22%2Bt)%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeck%3A%20%22%2Ce)%7D%7Dasync%20function%20getDeckCardsInfo(e%2Cr%2Ct)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20deckData%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20deckMainInfo%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dt)throw%20log(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blog(%22log%22%2C%22Getting%20deck%20cards%20info%22)%3Bfor(var%20o%3D%22%22%2Cn%3De.cards%2Ca%3D0%3Ba%3Cn.length%3Ba%2B%2B)%7Bvar%20i%3Dn%5Ba%5D%3Blog(%22log%22%2C%22card%20number%3A%20%22%2Ca)%3Bvar%20s%3D%22%22%2Cl%3D%22%22%2Cd%3D%22%22%2Cc%3D%22%22%2Cg%3Di.sides%3Blog(%22log%22%2C%22sides%20length%3A%20%22%2Cg.length)%3Bfor(var%20u%3D0%3Bu%3Cg.length%3Bu%2B%2B)%7Bvar%20f%3Dg%5Bu%5D%3Blog(%22log%22%2C%22side%3A%20%22%2Cf)%3Bvar%20p%3DNumber(a%2B1)%2Cm%3Dn.length.toString().length%2Ch%3D%22cardsUI%2Fcard_%22%2Bzerofy(p%2Cm)%2B%22_%22%2B(u%3F%22back%22%3A%22front%22)%2B%22.png%22%3Bu%3Fd%3Dh%3As%3Dh%3Bfor(var%20y%3D%22%22%2CR%3D0%3BR%3Cf.concepts.length%3BR%2B%2B)%7Bvar%20v%3Df.concepts%5BR%5D%3Blog(%22log%22%2C%22side%3A%20%22%2Cf)%3Bvar%20w%3Dv.fact%3Blog(%22log%22%2C%22fact%3A%20%22%2Cw)%3Bvar%20b%3DNumber(u%2B1)%2Cx%3Dg.length.toString().length%2CE%3DNumber(R%2B1)%2CS%3Df.concepts.length.toString().length%2Ck%3D%22%22%3B%22IMAGE%22%3D%3Dw.type%3F(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.jpg%22%2Clog(%22log%22%2C%22found%20image%20side%20at%20url%3A%20%22%2Cw.imageUrl)%2Ct.file(%22cards%2F%22%2Bk%2Cw.imageUrl.startsWith(%22data%3A%22)%3Fw.imageUrl.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(w.imageUrl)%2Cw.imageUrl.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D))%3A%22TEXT%22%3D%3Dw.type%3F(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.txt%22%2Clog(%22log%22%2C%22found%20text%20side%3A%20%22%2Cw.text)%2Cy%3Dy.concat(R%3F%22%20%2F%20%22%3A%22%22).concat(w.text)%2Ct.file(%22cards%2F%22%2Bk%2Cw.text)%2Cvoid%200!%3D%3Dw.ttsUrl%26%26(k%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22.mp3%22%2Clog(%22log%22%2C%22found%20tts%3A%20%22%2Cw.ttsUrl)%2Ct.file(%22cards%2F%22%2Bk%2Cw.ttsUrl.startsWith(%22data%3A%22)%3Fw.ttsUrl.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(w.ttsUrl)%2Cw.ttsUrl.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)))%3Alog(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20Unexpected%20concept%20type%3A%20%22%2Bw.type%2Cw)%3Bfor(var%20P%3Dv.noteFacts%2CC%3D0%3BC%3CP.length%3BC%2B%2B)%7Bvar%20F%3DP%5BC%5D%2CO%3DNumber(C%2B1)%2CI%3DP.length.toString().length%2CT%3D%22card_%22%2Bzerofy(p%2Cm)%2B%22_side_%22%2Bzerofy(b%2Cx)%2B%22_concept_%22%2Bzerofy(E%2CS)%2B%22_noteFact_%22%2Bzerofy(O%2CI)%2B%22.txt%22%3Blog(%22log%22%2C%22found%20note%20fact%3A%20%22%2CF)%2Ct.file(%22cards%2F%22%2BT%2CF)%7D%7Du%3Fc%3Dy%3Al%3Dy%7Do%3Do%2B'%22'%2Bs%2B'%22%2C%22'%2Bd%2B'%22%2C%22'%2Bl%2B'%22%2C%22'%2Bc%2B'%22%5Cn'%7Dt.file(%22cardsInfo.csv%22%2Cr%2B'%5Cn%22%22%5Cn%22%22%5Cn%22Front%20Card%20Image%22%2C%22Front%20Card%20Text%22%2C%22Back%20Card%20Image%22%2C%22Back%20Card%20Text%22%5Cn'%2Bo)%3Bvar%20D%3D%22%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3Cmeta%20charset%3D'utf-8'%2F%3E%3Cstyle%3Etable%2C%20th%2C%20td%20%7Bborder%3A%200px%20solid%20gray%3B%20border-collapse%3A%20collapse%3B%7D%20%23cards%20td%20%7Bmax-width%3A%20300px%3B%20min-width%3A%20200px%3B%7D%20%23deckInfo%20%7Bmargin-bottom%3A%2010px%3B%7D%20%23deckInfo%20td%20%7Bpadding%3A0%2020px%200%200%3B%7D%20img%20%7Bbox-shadow%3A%200%208px%2016px%200%20rgba(0%2C0%2C0%2C0.2)%3B%20border-radius%3A%2025px%2025px%2025px%2025px%7D%3C%2Fstyle%3E%3C%2Fhead%3E%3Cbody%3E%3Ch1%3E%22%2Br.split(%22%5Cn%22%2C1)%5B0%5D.split(%22%2C%22)%5B1%5D.replace(%2F(%5E%22)%7C(%22%24)%2Fg%2C%22%22)%2B%22%3C%2Fh1%3E%3Cdiv%3E%3Ctable%20id%3D'deckInfo'%3E%22%2Br.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Ctd%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Ftd%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Ftd%3E%3Ctd%3E%22).concat(%22%3C%2Ftable%3E%3C%2Fdiv%3E%22).replace(%2F(http%5B%5E%3C%5D%2B)(%3F%3D%3C)%2F%2C%22%3Ca%20href%3D'%241'%3E%241%3C%2Fa%3E%22)%2B%22%3Cdiv%3E%3Cp%3E%3Ca%20href%3D'.%2F'%3EBase%20folder%3C%2Fa%3E%3C%2Fp%3E%3C%2Fdiv%3E%5Cn%3Cdiv%3E%3Ctable%20id%3D'cards'%3E%22%2B'%22Front%20Card%20Image%22%2C%22Back%20Card%20Image%22%2C%22Front%20Card%20Text%22%2C%22Back%20Card%20Text%22%5Cn'.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Cth%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Fth%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Fth%3E%3Cth%3E%22)%2Bo.replace(%2F%5E%22%2Fgm%2C%22%3Ctr%3E%3Ctd%3E%22).replace(%2F%22%24%2Fgm%2C%22%3C%2Ftd%3E%3C%2Ftr%3E%22).replace(%2F%22%2C%22%2Fg%2C%22%3C%2Ftd%3E%3Ctd%3E%22).replace(%2F%3Ctd%3EcardsUI%5C%2F%2Fg%2C%22%3Ctd%3E%3Cimg%20src%3D'.%2FcardsUI%2F%22).replace(%2F.png%3C%5C%2Ftd%3E%2Fg%2C%22.png'%2F%3E%3C%2Ftd%3E%22).replace(%2Fsrc%3D%5C'(%5B%5E%5C'%5D%2B)%5C'%2Fg%2Cfunction(e%2Cr)%7Breturn%22alt%3D'%22%2Br.replace(%2F%5C.%5C%2Fcards%5B%5E%5C%2F%5D%2B%5C%2F(%5B%5E%5C.%5D%2B)%5C.png%2Fg%2C%22%241%22).replace(%2F_%2Fg%2C%22%20%22)%2B%22'%20src%3D'%22%2Br%2B%22'%22%7D)%2B%22%3C%2Ftable%3E%3C%2Fdiv%3E%3C%2Fbody%3E%3C%2Fhtml%3E%22%3Breturn%20t.file(%22cardsInfo.html%22%2CD)%2Ct%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getDeckCardsInfo%3A%20%22%2Ce)%7D%7Dfunction%20getBinaryFile(e)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getBinaryFile%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Breturn%20e.startsWith(%22data%3A%22)%3Flog(%22log%22%2C%22Getting%20binary%20file%3A%20data%20url%20received%22)%3Alog(%22log%22%2C%22Getting%20binary%20file%3A%20%22%2Ce)%2Cnew%20Promise(function(r%2Ct)%7BJSZipUtils.getBinaryContent(e%2Cfunction(e%2Co)%7Be%3Ft(e)%3Ar(o)%7D)%7D).catch(function(e)%7Breturn%20errorsFileDownload%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBinaryContent%3A%20%22%2Be)%2C%22ERROR%3A%20could%20not%20download%20this%20file%3A%20%22%2Be%7D)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBinaryFile%3A%20%22%2Ce)%7D%7Dasync%20function%20flipCards()%7Btry%7Blog(%22log%22%2C%22Flipping%20cards%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22.ALWo1%22)%3Bfor(let%20r%20of%20e)r.classList.contains(%22PemDv%22)%3F(r.style.transform%3D%22rotateY(180deg)%22%2Cr.classList.remove(%22PemDv%22))%3A(r.style.transform%3D%22rotateY(0deg)%22%2Cr.classList.add(%22PemDv%22))%2Cr.removeAttribute(%22style%22)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C1e3))%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20flipCards%3A%20%22%2Ce)%7D%7Dfunction%20proxifyImages()%7Btry%7Blog(%22log%22%2C%22Proxifying%20images%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22img%22)%3Bfor(let%20r%20of%20e)r.src.startsWith(proxyAddress)%7C%7Cr.src.startsWith(%22data%3A%22)%7C%7C(r.src%3DproxyAddress%2Br.src)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20flipCards%3A%20%22%2Ce)%7D%7Dfunction%20embedImages()%7Btry%7Bfunction%20e(e%2Cr%2Ct)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20callback%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20o%3Ddocument.createElement(%22CANVAS%22)%2Cn%3Do.getContext(%222d%22)%2Ca%3Dnew%20Image%3Ba.crossOrigin%3D%22Anonymous%22%2Ca.onload%3Dfunction()%7Bo.height%3Da.height%2Co.width%3Da.width%2Cn.drawImage(a%2C0%2C0)%3Bvar%20e%3Do.toDataURL(t%7C%7C%22image%2Fpng%22)%3Br.call(this%2Ce)%2Co%3Dnull%7D%2Ca.src%3De%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertImgToBase64%3A%20%22%2Ce)%7D%7Dlog(%22log%22%2C%22Embedding%20images%22)%3Bvar%20r%3Ddocument.querySelectorAll(%22img%22)%3Bfor(let%20t%20of%20r)e(t.src%2Cfunction(e)%7Bt.src%3De%7D)%2Ct.removeAttribute(%22srcset%22)%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedImages%3A%20%22%2Ce)%7D%7Dasync%20function%20everyoneSmile(e)%7Btry%7Bif(log(%22log%22%2C%22Everyone%20smile%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20everyoneSmile%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Breturn%20e%3Dawait%20cardsSayCheese(e%2C%22front%22)%2Ce%3Dawait%20allTogetherNow(e%2C%22front%22)%2Cawait%20flipCards()%2Ce%3Dawait%20cardsSayCheese(e%2C%22back%22)%2Ce%3Dawait%20allTogetherNow(e%2C%22back%22)%2Cawait%20flipCards()%2Ce%7Dcatch(e)%7Blog(%22error%22%2C%22ERROR%3A%20everyoneSmile%3A%20%22%2Ce)%7D%7Dasync%20function%20convertToPng(e%2Cr%2Ct)%7Btry%7Bif(log(%22log%22%2C%22Converting%20to%20png%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20element%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(r%26%26void%200%3D%3D%3Dt)throw%20log(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20width%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Blet%20o%3De.style.position%2Cn%3De.style.left%3Br%26%26(e.style.position%3D%22absolute%22%2Ce.style.left%3D%22-9999px%22%2Ce.style.width%3Dt%2B%22px%22%2Cdocument.body.appendChild(e))%3Bconst%20a%3Dawait%20domtoimage.toPng(e%2C%7Bstyle%3A%7Bposition%3Ao%2Cleft%3An%7D%7D).catch(function(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20domtoimage%3A%20%22%2Ce)%7D)%3Breturn%20r%26%26document.body.removeChild(e)%2Ca%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20convertToPng%3A%20%22%2Ce)%7D%7Dasync%20function%20cardsSayCheese(e%2Cr)%7Btry%7Bif(log(%22log%22%2C%22Cards%20say%20cheese%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20side%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20t%3Ddocument.querySelectorAll(%22.PemDv%22)%2Co%3Dt.length.toString().length%2Cn%3D0%3Bfor(let%20i%20of%20t)%7BupdateProgress(%22Retrieving%20card's%20%22%2Br%2B%22%20%22%2B(n%2B%3D1)%2B%22%2F%22%2Bt.length%2B%22...%22)%3Bvar%20a%3Dawait%20convertToPng(i)%3Bvoid%200%3D%3D%3Da%3Flog(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20data%20returned%20from%20convertToPng%20is%20undefined%22)%3Ae.file(%22cardsUI%2Fcard_%22%2Bzerofy(n%2Co)%2B%22_%22%2Br%2B%22.png%22%2Ca.startsWith(%22data%3A%22)%3Fa.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(a)%2Ca.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%7Dreturn%20e%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20cardsSayCheese%3A%20%22%2Ce)%7D%7Dfunction%20zerofy(e%2Cr)%7Btry%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20zerofy%3A%20number%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20zerofy%3A%20length%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bfor(var%20t%3D%22%22%2Be%3Bt.length%3Cr%3B)t%3D%220%22%2Bt%3Breturn%20t%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20zerofy%3A%20%22%2Ce)%7D%7Dasync%20function%20allTogetherNow(e%2Cr)%7Btry%7Bif(log(%22log%22%2C%22All%20together%20now%22)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20zip%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bif(void%200%3D%3D%3Dr)throw%20log(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20side%20is%20undefined%22)%2C%22Parameter%20undefined%22%3BupdateProgress(%22Retrieving%20deck's%20%22%2Br%2B%22.%20This%20may%20take%20a%20while%20and%20slow%20down%20your%20browser%20temporarily.%20Please%20wait...%22)%2Cawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bvar%20t%3Ddocument.querySelectorAll(%22.ALWo1%3Anot(.PemDv)%22)%3Bfor(let%20e%20of%20t)e.style.display%3D%22none%22%3Bvar%20o%3Ddocument.querySelector(%22body%22).cloneNode(!0)%2Cn%3Do.querySelector(%22%23export%22)%3Bnull!%3Dn%26%26n.parentNode.removeChild(n)%3Bvar%20a%3Do.querySelectorAll(%22.blockOverlay%2C%20.blockMsg%22)%3Bif(null!%3Da)for(let%20e%20of%20a)null!%3De%26%26e.parentNode.removeChild(e)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bvar%20i%3Dawait%20convertToPng(o%2C!0%2Cdocument.querySelector(%22body%22).clientWidth)%3Bawait%20new%20Promise(e%3D%3EsetTimeout(e%2C100))%3Bfor(let%20e%20of%20t)e.removeAttribute(%22style%22)%3Breturn%20void%200%3D%3D%3Di%3Flog(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20data%20returned%20from%20convertToPng%20is%20undefined%22)%3Ae.file(%22deck%22%2Br.charAt(0).toUpperCase()%2Br.slice(1)%2B%22.png%22%2Ci.startsWith(%22data%3A%22)%3Fi.replace(%2F%5E%5B%5E%2C%5D%2B%2C%2F%2C%22%22)%3AgetBinaryFile(i)%2Ci.startsWith(%22data%3A%22)%3F%7Bbase64%3A!0%7D%3A%7Bbinary%3A!0%7D)%2Ce%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20allTogetherNow%3A%20%22%2Ce)%7D%7Dasync%20function%20getBase64File(e)%7Btry%7Bif(log(%22log%22%2C%22Getting%20a%20base64%20representation%20of%3A%20%22%2Ce)%2Cvoid%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getBase64File%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bconst%20r%3Dawait%20fetch(e)%2Ct%3Dawait%20r.blob()%2Co%3Dnew%20FileReader%3Breturn%20await%20new%20Promise((e%2Cr)%3D%3E%7Bo.onload%3De%2Co.onerror%3Dr%2Co.readAsDataURL(t)%7D)%2Co.result%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20getBase64File%3A%20%22%2Ce)%7D%7Dasync%20function%20embedFonts()%7Btry%7Blog(%22log%22%2C%22Embedding%20fonts%22)%3Bvar%20e%3Ddocument.querySelectorAll(%22style%5Btype%3D'text%2Fcss'%5D%22)%3Bfor(let%20c%20of%20e)%7Bc.textContent%3Dc.textContent.replace(%2Furl%5C(%5C%2F%5C%2F%5B%5E%2C%5D%2B(woff%7Ctruetype%7Csvg)%22%5C)%2C%3F%2Fg%2C%22%22)%2Cc.textContent%3Dc.textContent.replace(%2Fformat%5C(%22woff2%5C%22%5C)%2C%2Fg%2C'format(%22woff2%22)')%2Cc.textContent%3Dc.textContent.replace(%2F%40font-face%2Fg%2C%22%5Cn%40font-face%22)%3Bfor(var%20r%2Ct%3D%2Furl%5C(%5C%2F%5C%2F%5B%5E)%5D%2B%5C)%2Fg%2Co%3D%5B%5D%3Bnull!%3D%3D(r%3Dt.exec(c.textContent))%3B)r%5B0%5D%3Dr%5B0%5D.replace(%2F%5C)%24%2F%2C%22%22).replace(%2F%5Eurl%5C(%2F%2C%22%22)%2Co.push(r%5B0%5D)%3Bfor(var%20n%3D%5B...new%20Set(o)%5D.sort()%2Ca%3D0%3Ba%3Cn.length%3Ba%2B%2B)%7Bvar%20i%3Dn%5Ba%5D%2Cs%3D%22%22%3Bi.startsWith(proxyAddress)%7C%7C(s%3DproxyAddress%2B%22https%3A%22%2Bi)%3Bvar%20l%3Dawait%20getBase64File(s)%2Cd%3Dnew%20RegExp(i%2C%22g%22)%3Bc.textContent%3Dc.textContent.replace(d%2Cl)%7D%7D%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedFonts%3A%20%22%2Ce)%7D%7Dasync%20function%20embedStyleSheets()%7Btry%7Basync%20function%20e(e)%7Bif(void%200%3D%3D%3De)throw%20log(%22error%22%2C%22ERROR%3A%20getExternalCSS%3A%20url%20is%20undefined%22)%2C%22Parameter%20undefined%22%3Bvar%20r%3Dnew%20XMLHttpRequest%3Breturn%20new%20Promise(function(t%2Co)%7Btry%7Br.onreadystatechange%3Dfunction()%7B4%3D%3Dr.readyState%26%26(r.status%3E%3D300%3Fo(%22ERROR%3A%20status%20code%20%3D%20%22%2Br.status)%3At(r.responseText))%7D%2Cr.open(%22get%22%2Ce)%2Cr.send()%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20getExternalCSS%3A%20Promise%3A%20%22%2Ce)%7D%7D)%7Dlog(%22log%22%2C%22Embedding%20style%20sheets%22)%3Bvar%20r%3Ddocument.querySelectorAll(%22LINK%5Bhref*%3D'.css'%5D%22)%3Bfor(let%20o%20of%20r)%7Bvar%20t%3Do.href%3Bt.startsWith(%22moz-extension%22)%7C%7C(t.startsWith(proxyAddress)%7C%7C(t%3DproxyAddress%2Bt)%2Cawait%20e(t).then(function(e)%7Bvoid%200%3D%3D%3De%26%26log(%22error%22%2C%22ERROR%3A%20getExternalCSS%3A%20result%20is%20undefined%22)%3Bvar%20r%3Ddocument.head%7C%7Cdocument.getElementsByTagName(%22head%22)%5B0%5D%2Ct%3Ddocument.createElement(%22style%22)%3Bt.type%3D%22text%2Fcss%22%2Ct.styleSheet%3Ft.styleSheet.cssText%3De%3At.appendChild(document.createTextNode(e))%2Cr.appendChild(t)%7D%2Cfunction(e)%7Blog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20%22%2Ce)%7D)%2Co.remove())%7D%7Dcatch(e)%7BerrorsFound%3D!0%2Clog(%22error%22%2C%22ERROR%3A%20embedStyleSheets%3A%20%22%2Ce)%7D%7DloadScripts()%2CdoIt()%3B%7D)()%3B";
            node.prepend(element);
        }
    }
})();

If you're not familiar with Tampermonkey and you don't want to try it, use the bookmarklet method. If you would like to learn something new, give it a try.

It will create an Export button close to the deck information (look for the Pin button). If it doesn't show right away, refresh the page (Ctrl+F5).

Requirements

To use the deck exporter, you need a modern desktop browser and an Internet connection. We recommend Google Chrome because, in the tests we made, it was able to manage large decks without using too much memory when performing the export. Firefox performed well only when the decks were not large and didn't have too many pictures.

Needed for the deck exporter to run

For the deck exporter to run, the following websites need to be up and running and reachable from your network:

  • Tinycards
    Tinycards is a product from Duolingo. If you like Duolingo, support them with a Duolingo Plus subscription.
  • allOrigins
    Exporting the decks requires using a secondary server for downloading some of the files. This can be done by setting up a local server yourself or using an existing server for that purpose available on the Web. This project uses allOrigins. If you like using the deck exporter without having to set up a local server, support allOrigins.
  • cdnjs
    Where the libraries used are loaded from.

To which flashcard system should I migrate?

There are so many options that it really depends on you. Different systems appeal to different people, so try a few and stay with the one that you like.
On the Tinycards forum many different ones were suggested:

Troubleshooting and Questions

I'm using the Tampermonkey script but I don't see the Export button
It's created close to the deck information (look for the Pin button). If it doesn't show right away, refresh the page (Ctrl+F5).

I press Export but I don't get any zip file
Press F12 to see the browser's console and check for any errors in red.

The Tinycards page is gone. Can I still use this tool to export a Tinycards deck?
This tool only works on the Tinycards deck page that you want to export. If the deck page is no longer accessible the tool won't work.

allOrigins is down or not working any more
Try to find an alternative to it and replace it in the code. You can also set up your own server for dealing with the requests.
More information:

My browser crashed when I was using this tool
You were probably not using Chrome. We recommend Google Chrome because, in the tests we made, it was able to manage large decks without using too much memory when performing the export. Firefox performed well only when the decks were not large and didn't have too many pictures.

Can I download my unfinished decks with this tool?
No. This tool can only download publicly accessible decks.

Who was Cardlos?
Cardlos was the name of the Tinycards mascot. In a parallel dimension he was also known as Tiny.

Acknowledgements

This project would not be possible without Tinycards, allOrigins, cdnjs and the libraries and tools mentioned below.

Libraries used

Used during development

And also