Copy disabled (too large)
Download .txt
Showing preview only (15,277K chars total). Download the full file to get everything.
Repository: 1j01/jspaint
Branch: master
Commit: bc07ca1bce92
Files: 2535
Total size: 14.4 MB
Directory structure:
gitextract_p5h0c0f0/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ ├── run-command-on-all-files.ahk
│ └── settings.json
├── CHANGELOG.md
├── CNAME
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── TODO.md
├── about.html
├── browserconfig.xml
├── cspell.json
├── cypress/
│ ├── cypress-image-snapshot-viewer.js
│ ├── fixtures/
│ │ └── example.json
│ ├── integration/
│ │ ├── tool-tests.spec.js
│ │ └── visual-tests.spec.js
│ ├── plugins/
│ │ └── index.js
│ └── support/
│ ├── commands.js
│ └── index.js
├── cypress.json
├── discord-activity/
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── packages/
│ └── server/
│ ├── environment.d.ts
│ ├── package.json
│ ├── src/
│ │ ├── app.ts
│ │ ├── shared/
│ │ │ └── hello.ts
│ │ └── utils.ts
│ └── tsconfig.json
├── eslint.config.mjs
├── forge.config.js
├── help/
│ ├── coUA.css
│ ├── default.html
│ ├── memcopy.html
│ ├── mspaint.hhc
│ ├── mspaint.hhk
│ ├── nobgcolor.css
│ ├── online_support.htm
│ ├── paint_airbrush.html
│ ├── paint_blackwhite.html
│ ├── paint_brush.html
│ ├── paint_change_color.html
│ ├── paint_change_size.html
│ ├── paint_clear_image.html
│ ├── paint_color_box.html
│ ├── paint_curves.html
│ ├── paint_custom_colors.html
│ ├── paint_cutout_copy_move.html
│ ├── paint_cutout_save.html
│ ├── paint_cutout_select.html
│ ├── paint_enlarge_area.html
│ ├── paint_erase_large.html
│ ├── paint_erase_small.html
│ ├── paint_fill.html
│ ├── paint_flip_picture.html
│ ├── paint_freeform_lines.html
│ ├── paint_grid.html
│ ├── paint_insert_file.html
│ ├── paint_invert.html
│ ├── paint_lines.html
│ ├── paint_not_in_color_box.html
│ ├── paint_ovals.html
│ ├── paint_polygons.html
│ ├── paint_print.html
│ ├── paint_rectangles.html
│ ├── paint_set_default_colors.html
│ ├── paint_skew_picture.html
│ ├── paint_text.html
│ ├── paint_toolbox.html
│ ├── paint_trans_opaque.html
│ ├── paint_undo.html
│ ├── paint_wallpaper.html
│ ├── paint_zoom.html
│ ├── prettify-html.ahk
│ └── vaporwave.js
├── images/
│ ├── 88x31/
│ │ └── custom/
│ │ ├── pipe-strip-88x31-v0.psd
│ │ ├── pipe-strip-88x31-v1.psd
│ │ ├── pipe-strip-88x31-v2.psd
│ │ ├── pipe-strip-88x31-v3.psd
│ │ ├── pipe-strip-88x31-v4.psd
│ │ └── turbo-encabulator-88x31-v0.psd
│ ├── bubblegum/
│ │ ├── bubblegum-recess.psd
│ │ ├── eye-gaze-pause-button.psd
│ │ └── fill-with-color.psd
│ ├── icons/
│ │ └── jspaint.icns
│ └── modern/
│ └── cursors/
│ ├── airbrush-alt.cur
│ ├── airbrush.cur
│ ├── crosshair-large.cur
│ ├── crosshair.cur
│ ├── ew-resize-large.cur
│ ├── ew-resize.cur
│ ├── eye-dropper-large.cur
│ ├── eye-dropper.cur
│ ├── magnifier-large.cur
│ ├── magnifier.cur
│ ├── move-large-alt.cur
│ ├── move-large.cur
│ ├── move.cur
│ ├── nesw-resize-large.cur
│ ├── nesw-resize.cur
│ ├── ns-resize-large.cur
│ ├── ns-resize.cur
│ ├── nwse-resize-large.cur
│ ├── nwse-resize.cur
│ ├── paint-bucket-large.cur
│ ├── paint-bucket.cur
│ ├── pencil-large.cur
│ ├── pencil.cur
│ ├── precise-large.cur
│ ├── precise.cur
│ ├── select-alt.cur
│ ├── select-large-alt.cur
│ ├── select-large.cur
│ ├── select.cur
│ ├── text-large.cur
│ ├── text.cur
│ ├── zoom-in-large.cur
│ ├── zoom-in.cur
│ ├── zoom-out-large.cur
│ └── zoom-out.cur
├── index.html
├── jsconfig.json
├── lib/
│ ├── 98.css/
│ │ ├── 98.custom-build.css
│ │ ├── 98.custom-build.rtl.css
│ │ ├── 98.custom-src.css
│ │ └── modified-build.js
│ ├── FileSaver.js
│ ├── UPNG.js
│ ├── UTIF.js
│ ├── anypalette-0.6.0.js
│ ├── bmp.js
│ ├── discord-embedded-app-sdk-v1.2.0-bundled-with-skypack.js
│ ├── firebase.js
│ ├── font-detective.js
│ ├── gif.js/
│ │ ├── gif.js
│ │ └── gif.worker.js
│ ├── imagetracer_v1.2.5.js
│ ├── os-gui/
│ │ ├── $Window.js
│ │ ├── MenuBar.js
│ │ ├── build/
│ │ │ ├── blue.css
│ │ │ ├── layout.css
│ │ │ ├── layout.rtl.css
│ │ │ ├── peggys-pastels.css
│ │ │ ├── windows-98.css
│ │ │ └── windows-default.css
│ │ ├── os-gui.d.ts
│ │ └── parse-theme.js
│ ├── os-gui.patch
│ ├── pdf.js/
│ │ ├── LICENSE
│ │ ├── build/
│ │ │ ├── pdf.js
│ │ │ ├── pdf.sandbox.js
│ │ │ └── pdf.worker.js
│ │ └── web/
│ │ ├── cmaps/
│ │ │ ├── 78-EUC-H.bcmap
│ │ │ ├── 78-EUC-V.bcmap
│ │ │ ├── 78-H.bcmap
│ │ │ ├── 78-RKSJ-H.bcmap
│ │ │ ├── 78-RKSJ-V.bcmap
│ │ │ ├── 78-V.bcmap
│ │ │ ├── 78ms-RKSJ-H.bcmap
│ │ │ ├── 78ms-RKSJ-V.bcmap
│ │ │ ├── 83pv-RKSJ-H.bcmap
│ │ │ ├── 90ms-RKSJ-H.bcmap
│ │ │ ├── 90ms-RKSJ-V.bcmap
│ │ │ ├── 90msp-RKSJ-H.bcmap
│ │ │ ├── 90msp-RKSJ-V.bcmap
│ │ │ ├── 90pv-RKSJ-H.bcmap
│ │ │ ├── 90pv-RKSJ-V.bcmap
│ │ │ ├── Add-H.bcmap
│ │ │ ├── Add-RKSJ-H.bcmap
│ │ │ ├── Add-RKSJ-V.bcmap
│ │ │ ├── Add-V.bcmap
│ │ │ ├── Adobe-CNS1-0.bcmap
│ │ │ ├── Adobe-CNS1-1.bcmap
│ │ │ ├── Adobe-CNS1-2.bcmap
│ │ │ ├── Adobe-CNS1-3.bcmap
│ │ │ ├── Adobe-CNS1-4.bcmap
│ │ │ ├── Adobe-CNS1-5.bcmap
│ │ │ ├── Adobe-CNS1-6.bcmap
│ │ │ ├── Adobe-CNS1-UCS2.bcmap
│ │ │ ├── Adobe-GB1-0.bcmap
│ │ │ ├── Adobe-GB1-1.bcmap
│ │ │ ├── Adobe-GB1-2.bcmap
│ │ │ ├── Adobe-GB1-3.bcmap
│ │ │ ├── Adobe-GB1-4.bcmap
│ │ │ ├── Adobe-GB1-5.bcmap
│ │ │ ├── Adobe-GB1-UCS2.bcmap
│ │ │ ├── Adobe-Japan1-0.bcmap
│ │ │ ├── Adobe-Japan1-1.bcmap
│ │ │ ├── Adobe-Japan1-2.bcmap
│ │ │ ├── Adobe-Japan1-3.bcmap
│ │ │ ├── Adobe-Japan1-4.bcmap
│ │ │ ├── Adobe-Japan1-5.bcmap
│ │ │ ├── Adobe-Japan1-6.bcmap
│ │ │ ├── Adobe-Japan1-UCS2.bcmap
│ │ │ ├── Adobe-Korea1-0.bcmap
│ │ │ ├── Adobe-Korea1-1.bcmap
│ │ │ ├── Adobe-Korea1-2.bcmap
│ │ │ ├── Adobe-Korea1-UCS2.bcmap
│ │ │ ├── B5-H.bcmap
│ │ │ ├── B5-V.bcmap
│ │ │ ├── B5pc-H.bcmap
│ │ │ ├── B5pc-V.bcmap
│ │ │ ├── CNS-EUC-H.bcmap
│ │ │ ├── CNS-EUC-V.bcmap
│ │ │ ├── CNS1-H.bcmap
│ │ │ ├── CNS1-V.bcmap
│ │ │ ├── CNS2-H.bcmap
│ │ │ ├── CNS2-V.bcmap
│ │ │ ├── ETHK-B5-H.bcmap
│ │ │ ├── ETHK-B5-V.bcmap
│ │ │ ├── ETen-B5-H.bcmap
│ │ │ ├── ETen-B5-V.bcmap
│ │ │ ├── ETenms-B5-H.bcmap
│ │ │ ├── ETenms-B5-V.bcmap
│ │ │ ├── EUC-H.bcmap
│ │ │ ├── EUC-V.bcmap
│ │ │ ├── Ext-H.bcmap
│ │ │ ├── Ext-RKSJ-H.bcmap
│ │ │ ├── Ext-RKSJ-V.bcmap
│ │ │ ├── Ext-V.bcmap
│ │ │ ├── GB-EUC-H.bcmap
│ │ │ ├── GB-EUC-V.bcmap
│ │ │ ├── GB-H.bcmap
│ │ │ ├── GB-V.bcmap
│ │ │ ├── GBK-EUC-H.bcmap
│ │ │ ├── GBK-EUC-V.bcmap
│ │ │ ├── GBK2K-H.bcmap
│ │ │ ├── GBK2K-V.bcmap
│ │ │ ├── GBKp-EUC-H.bcmap
│ │ │ ├── GBKp-EUC-V.bcmap
│ │ │ ├── GBT-EUC-H.bcmap
│ │ │ ├── GBT-EUC-V.bcmap
│ │ │ ├── GBT-H.bcmap
│ │ │ ├── GBT-V.bcmap
│ │ │ ├── GBTpc-EUC-H.bcmap
│ │ │ ├── GBTpc-EUC-V.bcmap
│ │ │ ├── GBpc-EUC-H.bcmap
│ │ │ ├── GBpc-EUC-V.bcmap
│ │ │ ├── H.bcmap
│ │ │ ├── HKdla-B5-H.bcmap
│ │ │ ├── HKdla-B5-V.bcmap
│ │ │ ├── HKdlb-B5-H.bcmap
│ │ │ ├── HKdlb-B5-V.bcmap
│ │ │ ├── HKgccs-B5-H.bcmap
│ │ │ ├── HKgccs-B5-V.bcmap
│ │ │ ├── HKm314-B5-H.bcmap
│ │ │ ├── HKm314-B5-V.bcmap
│ │ │ ├── HKm471-B5-H.bcmap
│ │ │ ├── HKm471-B5-V.bcmap
│ │ │ ├── HKscs-B5-H.bcmap
│ │ │ ├── HKscs-B5-V.bcmap
│ │ │ ├── Hankaku.bcmap
│ │ │ ├── Hiragana.bcmap
│ │ │ ├── KSC-EUC-H.bcmap
│ │ │ ├── KSC-EUC-V.bcmap
│ │ │ ├── KSC-H.bcmap
│ │ │ ├── KSC-Johab-H.bcmap
│ │ │ ├── KSC-Johab-V.bcmap
│ │ │ ├── KSC-V.bcmap
│ │ │ ├── KSCms-UHC-H.bcmap
│ │ │ ├── KSCms-UHC-HW-H.bcmap
│ │ │ ├── KSCms-UHC-HW-V.bcmap
│ │ │ ├── KSCms-UHC-V.bcmap
│ │ │ ├── KSCpc-EUC-H.bcmap
│ │ │ ├── KSCpc-EUC-V.bcmap
│ │ │ ├── Katakana.bcmap
│ │ │ ├── LICENSE
│ │ │ ├── NWP-H.bcmap
│ │ │ ├── NWP-V.bcmap
│ │ │ ├── RKSJ-H.bcmap
│ │ │ ├── RKSJ-V.bcmap
│ │ │ ├── Roman.bcmap
│ │ │ ├── UniCNS-UCS2-H.bcmap
│ │ │ ├── UniCNS-UCS2-V.bcmap
│ │ │ ├── UniCNS-UTF16-H.bcmap
│ │ │ ├── UniCNS-UTF16-V.bcmap
│ │ │ ├── UniCNS-UTF32-H.bcmap
│ │ │ ├── UniCNS-UTF32-V.bcmap
│ │ │ ├── UniCNS-UTF8-H.bcmap
│ │ │ ├── UniCNS-UTF8-V.bcmap
│ │ │ ├── UniGB-UCS2-H.bcmap
│ │ │ ├── UniGB-UCS2-V.bcmap
│ │ │ ├── UniGB-UTF16-H.bcmap
│ │ │ ├── UniGB-UTF16-V.bcmap
│ │ │ ├── UniGB-UTF32-H.bcmap
│ │ │ ├── UniGB-UTF32-V.bcmap
│ │ │ ├── UniGB-UTF8-H.bcmap
│ │ │ ├── UniGB-UTF8-V.bcmap
│ │ │ ├── UniJIS-UCS2-H.bcmap
│ │ │ ├── UniJIS-UCS2-HW-H.bcmap
│ │ │ ├── UniJIS-UCS2-HW-V.bcmap
│ │ │ ├── UniJIS-UCS2-V.bcmap
│ │ │ ├── UniJIS-UTF16-H.bcmap
│ │ │ ├── UniJIS-UTF16-V.bcmap
│ │ │ ├── UniJIS-UTF32-H.bcmap
│ │ │ ├── UniJIS-UTF32-V.bcmap
│ │ │ ├── UniJIS-UTF8-H.bcmap
│ │ │ ├── UniJIS-UTF8-V.bcmap
│ │ │ ├── UniJIS2004-UTF16-H.bcmap
│ │ │ ├── UniJIS2004-UTF16-V.bcmap
│ │ │ ├── UniJIS2004-UTF32-H.bcmap
│ │ │ ├── UniJIS2004-UTF32-V.bcmap
│ │ │ ├── UniJIS2004-UTF8-H.bcmap
│ │ │ ├── UniJIS2004-UTF8-V.bcmap
│ │ │ ├── UniJISPro-UCS2-HW-V.bcmap
│ │ │ ├── UniJISPro-UCS2-V.bcmap
│ │ │ ├── UniJISPro-UTF8-V.bcmap
│ │ │ ├── UniJISX0213-UTF32-H.bcmap
│ │ │ ├── UniJISX0213-UTF32-V.bcmap
│ │ │ ├── UniJISX02132004-UTF32-H.bcmap
│ │ │ ├── UniJISX02132004-UTF32-V.bcmap
│ │ │ ├── UniKS-UCS2-H.bcmap
│ │ │ ├── UniKS-UCS2-V.bcmap
│ │ │ ├── UniKS-UTF16-H.bcmap
│ │ │ ├── UniKS-UTF16-V.bcmap
│ │ │ ├── UniKS-UTF32-H.bcmap
│ │ │ ├── UniKS-UTF32-V.bcmap
│ │ │ ├── UniKS-UTF8-H.bcmap
│ │ │ ├── UniKS-UTF8-V.bcmap
│ │ │ ├── V.bcmap
│ │ │ └── WP-Symbol.bcmap
│ │ ├── debugger.js
│ │ ├── images/
│ │ │ ├── grab.cur
│ │ │ └── grabbing.cur
│ │ ├── locale/
│ │ │ ├── ach/
│ │ │ │ └── viewer.properties
│ │ │ ├── af/
│ │ │ │ └── viewer.properties
│ │ │ ├── an/
│ │ │ │ └── viewer.properties
│ │ │ ├── ar/
│ │ │ │ └── viewer.properties
│ │ │ ├── ast/
│ │ │ │ └── viewer.properties
│ │ │ ├── az/
│ │ │ │ └── viewer.properties
│ │ │ ├── be/
│ │ │ │ └── viewer.properties
│ │ │ ├── bg/
│ │ │ │ └── viewer.properties
│ │ │ ├── bn/
│ │ │ │ └── viewer.properties
│ │ │ ├── bo/
│ │ │ │ └── viewer.properties
│ │ │ ├── br/
│ │ │ │ └── viewer.properties
│ │ │ ├── brx/
│ │ │ │ └── viewer.properties
│ │ │ ├── bs/
│ │ │ │ └── viewer.properties
│ │ │ ├── ca/
│ │ │ │ └── viewer.properties
│ │ │ ├── cak/
│ │ │ │ └── viewer.properties
│ │ │ ├── ckb/
│ │ │ │ └── viewer.properties
│ │ │ ├── cs/
│ │ │ │ └── viewer.properties
│ │ │ ├── cy/
│ │ │ │ └── viewer.properties
│ │ │ ├── da/
│ │ │ │ └── viewer.properties
│ │ │ ├── de/
│ │ │ │ └── viewer.properties
│ │ │ ├── dsb/
│ │ │ │ └── viewer.properties
│ │ │ ├── el/
│ │ │ │ └── viewer.properties
│ │ │ ├── en-CA/
│ │ │ │ └── viewer.properties
│ │ │ ├── en-GB/
│ │ │ │ └── viewer.properties
│ │ │ ├── en-US/
│ │ │ │ └── viewer.properties
│ │ │ ├── eo/
│ │ │ │ └── viewer.properties
│ │ │ ├── es-AR/
│ │ │ │ └── viewer.properties
│ │ │ ├── es-CL/
│ │ │ │ └── viewer.properties
│ │ │ ├── es-ES/
│ │ │ │ └── viewer.properties
│ │ │ ├── es-MX/
│ │ │ │ └── viewer.properties
│ │ │ ├── et/
│ │ │ │ └── viewer.properties
│ │ │ ├── eu/
│ │ │ │ └── viewer.properties
│ │ │ ├── fa/
│ │ │ │ └── viewer.properties
│ │ │ ├── ff/
│ │ │ │ └── viewer.properties
│ │ │ ├── fi/
│ │ │ │ └── viewer.properties
│ │ │ ├── fr/
│ │ │ │ └── viewer.properties
│ │ │ ├── fy-NL/
│ │ │ │ └── viewer.properties
│ │ │ ├── ga-IE/
│ │ │ │ └── viewer.properties
│ │ │ ├── gd/
│ │ │ │ └── viewer.properties
│ │ │ ├── gl/
│ │ │ │ └── viewer.properties
│ │ │ ├── gn/
│ │ │ │ └── viewer.properties
│ │ │ ├── gu-IN/
│ │ │ │ └── viewer.properties
│ │ │ ├── he/
│ │ │ │ └── viewer.properties
│ │ │ ├── hi-IN/
│ │ │ │ └── viewer.properties
│ │ │ ├── hr/
│ │ │ │ └── viewer.properties
│ │ │ ├── hsb/
│ │ │ │ └── viewer.properties
│ │ │ ├── hu/
│ │ │ │ └── viewer.properties
│ │ │ ├── hy-AM/
│ │ │ │ └── viewer.properties
│ │ │ ├── hye/
│ │ │ │ └── viewer.properties
│ │ │ ├── ia/
│ │ │ │ └── viewer.properties
│ │ │ ├── id/
│ │ │ │ └── viewer.properties
│ │ │ ├── is/
│ │ │ │ └── viewer.properties
│ │ │ ├── it/
│ │ │ │ └── viewer.properties
│ │ │ ├── ja/
│ │ │ │ └── viewer.properties
│ │ │ ├── ka/
│ │ │ │ └── viewer.properties
│ │ │ ├── kab/
│ │ │ │ └── viewer.properties
│ │ │ ├── kk/
│ │ │ │ └── viewer.properties
│ │ │ ├── km/
│ │ │ │ └── viewer.properties
│ │ │ ├── kn/
│ │ │ │ └── viewer.properties
│ │ │ ├── ko/
│ │ │ │ └── viewer.properties
│ │ │ ├── lij/
│ │ │ │ └── viewer.properties
│ │ │ ├── lo/
│ │ │ │ └── viewer.properties
│ │ │ ├── locale.properties
│ │ │ ├── lt/
│ │ │ │ └── viewer.properties
│ │ │ ├── ltg/
│ │ │ │ └── viewer.properties
│ │ │ ├── lv/
│ │ │ │ └── viewer.properties
│ │ │ ├── meh/
│ │ │ │ └── viewer.properties
│ │ │ ├── mk/
│ │ │ │ └── viewer.properties
│ │ │ ├── mr/
│ │ │ │ └── viewer.properties
│ │ │ ├── ms/
│ │ │ │ └── viewer.properties
│ │ │ ├── my/
│ │ │ │ └── viewer.properties
│ │ │ ├── nb-NO/
│ │ │ │ └── viewer.properties
│ │ │ ├── ne-NP/
│ │ │ │ └── viewer.properties
│ │ │ ├── nl/
│ │ │ │ └── viewer.properties
│ │ │ ├── nn-NO/
│ │ │ │ └── viewer.properties
│ │ │ ├── oc/
│ │ │ │ └── viewer.properties
│ │ │ ├── pa-IN/
│ │ │ │ └── viewer.properties
│ │ │ ├── pl/
│ │ │ │ └── viewer.properties
│ │ │ ├── pt-BR/
│ │ │ │ └── viewer.properties
│ │ │ ├── pt-PT/
│ │ │ │ └── viewer.properties
│ │ │ ├── rm/
│ │ │ │ └── viewer.properties
│ │ │ ├── ro/
│ │ │ │ └── viewer.properties
│ │ │ ├── ru/
│ │ │ │ └── viewer.properties
│ │ │ ├── scn/
│ │ │ │ └── viewer.properties
│ │ │ ├── si/
│ │ │ │ └── viewer.properties
│ │ │ ├── sk/
│ │ │ │ └── viewer.properties
│ │ │ ├── sl/
│ │ │ │ └── viewer.properties
│ │ │ ├── son/
│ │ │ │ └── viewer.properties
│ │ │ ├── sq/
│ │ │ │ └── viewer.properties
│ │ │ ├── sr/
│ │ │ │ └── viewer.properties
│ │ │ ├── sv-SE/
│ │ │ │ └── viewer.properties
│ │ │ ├── szl/
│ │ │ │ └── viewer.properties
│ │ │ ├── ta/
│ │ │ │ └── viewer.properties
│ │ │ ├── te/
│ │ │ │ └── viewer.properties
│ │ │ ├── th/
│ │ │ │ └── viewer.properties
│ │ │ ├── tl/
│ │ │ │ └── viewer.properties
│ │ │ ├── tr/
│ │ │ │ └── viewer.properties
│ │ │ ├── trs/
│ │ │ │ └── viewer.properties
│ │ │ ├── uk/
│ │ │ │ └── viewer.properties
│ │ │ ├── ur/
│ │ │ │ └── viewer.properties
│ │ │ ├── uz/
│ │ │ │ └── viewer.properties
│ │ │ ├── vi/
│ │ │ │ └── viewer.properties
│ │ │ ├── wo/
│ │ │ │ └── viewer.properties
│ │ │ ├── xh/
│ │ │ │ └── viewer.properties
│ │ │ ├── zh-CN/
│ │ │ │ └── viewer.properties
│ │ │ └── zh-TW/
│ │ │ └── viewer.properties
│ │ ├── viewer.css
│ │ ├── viewer.html
│ │ └── viewer.js
│ └── tracky-mouse/
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .gitrepo
│ ├── .vscode/
│ │ ├── extensions.json
│ │ ├── launch.json
│ │ └── settings.json
│ ├── API.md
│ ├── CHANGELOG.md
│ ├── CLI.md
│ ├── LICENSE.txt
│ ├── README.md
│ ├── core/
│ │ ├── README.md
│ │ ├── facemesh.worker.js
│ │ ├── lib/
│ │ │ ├── clmtrackr.js
│ │ │ ├── facemesh/
│ │ │ │ ├── blazeface/
│ │ │ │ │ └── model.json
│ │ │ │ ├── facemesh/
│ │ │ │ │ └── model.json
│ │ │ │ └── facemesh.js
│ │ │ ├── jsfeat-min.js
│ │ │ ├── no-eval.js
│ │ │ ├── stats.js
│ │ │ └── tf.js
│ │ ├── package.json
│ │ ├── tracky-mouse.css
│ │ └── tracky-mouse.js
│ ├── cspell.json
│ ├── desktop-app/
│ │ ├── forge.config.js
│ │ ├── images/
│ │ │ └── tracky-mouse-logo.icns
│ │ ├── package.json
│ │ └── src/
│ │ ├── electron-app.html
│ │ ├── electron-main/
│ │ │ ├── cli.js
│ │ │ ├── electron-main.js
│ │ │ ├── menus.js
│ │ │ ├── spawner.js
│ │ │ ├── squirrel-update.js
│ │ │ ├── version.js
│ │ │ └── win-powershell.js
│ │ ├── electron-screen-overlay.html
│ │ ├── preload-app-window.js
│ │ ├── preload-screen-overlay.js
│ │ ├── screen-overlay.css
│ │ ├── screen-overlay.js
│ │ └── tracky-mouse-bin.js
│ ├── eslint.config.js
│ ├── images/
│ │ ├── tracky-mouse-logo.blend
│ │ └── tracky-mouse-logo.icns
│ ├── package.json
│ └── website/
│ ├── CNAME
│ ├── demo.js
│ ├── eval-is-evil.html
│ ├── index.html
│ ├── package.json
│ └── tracky-mouse-homepage.css
├── localization/
│ ├── ar/
│ │ ├── Dialog/
│ │ │ └── 0401/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0401/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0401/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── cs/
│ │ ├── Dialog/
│ │ │ └── 0405/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0405/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0405/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── da/
│ │ ├── Dialog/
│ │ │ └── 0406/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0406/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0406/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── de/
│ │ ├── Dialog/
│ │ │ └── 0407/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0407/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0407/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── el/
│ │ ├── Dialog/
│ │ │ └── 0408/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0408/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0408/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── en/
│ │ ├── Dialog/
│ │ │ └── 0409/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0409/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ └── String Table/
│ │ └── 0409/
│ │ ├── 1.rc
│ │ ├── 129.rc
│ │ ├── 130.rc
│ │ ├── 131.rc
│ │ ├── 132.rc
│ │ ├── 135.rc
│ │ ├── 139.rc
│ │ ├── 141.rc
│ │ ├── 144.rc
│ │ ├── 145.rc
│ │ ├── 153.rc
│ │ ├── 2.rc
│ │ ├── 2049.rc
│ │ ├── 2050.rc
│ │ ├── 222.rc
│ │ ├── 2354.rc
│ │ ├── 2355.rc
│ │ ├── 2356.rc
│ │ ├── 2610.rc
│ │ ├── 2628.rc
│ │ ├── 2753.rc
│ │ ├── 2757.rc
│ │ ├── 2758.rc
│ │ ├── 2765.rc
│ │ ├── 2794.rc
│ │ ├── 3.rc
│ │ ├── 3585.rc
│ │ ├── 3601.rc
│ │ ├── 3602.rc
│ │ ├── 3603.rc
│ │ ├── 3605.rc
│ │ ├── 3606.rc
│ │ ├── 3713.rc
│ │ ├── 3714.rc
│ │ ├── 3825.rc
│ │ ├── 3826.rc
│ │ ├── 3841.rc
│ │ ├── 3842.rc
│ │ ├── 3843.rc
│ │ ├── 3845.rc
│ │ ├── 3849.rc
│ │ ├── 3850.rc
│ │ ├── 3857.rc
│ │ ├── 3858.rc
│ │ ├── 3859.rc
│ │ ├── 3865.rc
│ │ ├── 3866.rc
│ │ ├── 3867.rc
│ │ ├── 3868.rc
│ │ ├── 3869.rc
│ │ ├── 39.rc
│ │ ├── 40.rc
│ │ ├── 41.rc
│ │ ├── 430.rc
│ │ ├── 442.rc
│ │ ├── 578.rc
│ │ ├── 626.rc
│ │ ├── 63.rc
│ │ └── 7.rc
│ ├── es/
│ │ ├── Dialog/
│ │ │ └── 0C0A/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0C0A/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0C0A/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── fi/
│ │ ├── Dialog/
│ │ │ └── 040B/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 040B/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 040B/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── fr/
│ │ ├── Dialog/
│ │ │ └── 040C/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 040C/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 040C/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── grab-files-from-vm.sh
│ ├── he/
│ │ ├── Dialog/
│ │ │ └── 040D/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 040D/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 040D/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── hu/
│ │ ├── Dialog/
│ │ │ └── 040E/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 040E/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 040E/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── install-windows-98.sh
│ ├── it/
│ │ ├── Dialog/
│ │ │ └── 0410/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0410/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0410/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── ja/
│ │ ├── Dialog/
│ │ │ └── 0411/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0411/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0411/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── ko/
│ │ ├── Dialog/
│ │ │ └── 0412/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0412/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0412/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── nl/
│ │ ├── Dialog/
│ │ │ └── 0413/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0413/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0413/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── no/
│ │ ├── Dialog/
│ │ │ └── 0414/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0414/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0414/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── parse-rc-file.js
│ ├── pl/
│ │ ├── Dialog/
│ │ │ └── 0415/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0415/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0415/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── preprocess.js
│ ├── pt/
│ │ ├── Dialog/
│ │ │ └── 0816/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0816/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0816/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── pt-br/
│ │ ├── Dialog/
│ │ │ └── 0416/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0416/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0416/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── ru/
│ │ ├── Dialog/
│ │ │ └── 0419/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0419/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0419/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── sk/
│ │ ├── Dialog/
│ │ │ └── 041B/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 041B/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 041B/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── sl/
│ │ ├── Dialog/
│ │ │ └── 0424/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0424/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0424/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── sv/
│ │ ├── Dialog/
│ │ │ └── 041D/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 041D/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 041D/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── tr/
│ │ ├── Dialog/
│ │ │ └── 041F/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 041F/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 041F/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ ├── zh/
│ │ ├── Dialog/
│ │ │ └── 0404/
│ │ │ ├── 105.rc
│ │ │ ├── 108.rc
│ │ │ ├── 112.rc
│ │ │ ├── 113.rc
│ │ │ ├── 132.rc
│ │ │ ├── 30721.rc
│ │ │ ├── 30722.rc
│ │ │ ├── 30723.rc
│ │ │ ├── 37.rc
│ │ │ └── 4001.rc
│ │ ├── Menu/
│ │ │ └── 0404/
│ │ │ ├── 113.rc
│ │ │ ├── 118.rc
│ │ │ ├── 119.rc
│ │ │ ├── 2.rc
│ │ │ ├── 4.rc
│ │ │ └── 5.rc
│ │ ├── String Table/
│ │ │ └── 0404/
│ │ │ ├── 1.rc
│ │ │ ├── 129.rc
│ │ │ ├── 130.rc
│ │ │ ├── 131.rc
│ │ │ ├── 132.rc
│ │ │ ├── 135.rc
│ │ │ ├── 139.rc
│ │ │ ├── 141.rc
│ │ │ ├── 144.rc
│ │ │ ├── 145.rc
│ │ │ ├── 153.rc
│ │ │ ├── 2.rc
│ │ │ ├── 2049.rc
│ │ │ ├── 2050.rc
│ │ │ ├── 222.rc
│ │ │ ├── 2354.rc
│ │ │ ├── 2355.rc
│ │ │ ├── 2356.rc
│ │ │ ├── 2610.rc
│ │ │ ├── 2628.rc
│ │ │ ├── 2753.rc
│ │ │ ├── 2757.rc
│ │ │ ├── 2758.rc
│ │ │ ├── 2765.rc
│ │ │ ├── 2794.rc
│ │ │ ├── 3.rc
│ │ │ ├── 3585.rc
│ │ │ ├── 3601.rc
│ │ │ ├── 3602.rc
│ │ │ ├── 3603.rc
│ │ │ ├── 3605.rc
│ │ │ ├── 3606.rc
│ │ │ ├── 3713.rc
│ │ │ ├── 3714.rc
│ │ │ ├── 3825.rc
│ │ │ ├── 3826.rc
│ │ │ ├── 3841.rc
│ │ │ ├── 3842.rc
│ │ │ ├── 3843.rc
│ │ │ ├── 3845.rc
│ │ │ ├── 3849.rc
│ │ │ ├── 3850.rc
│ │ │ ├── 3857.rc
│ │ │ ├── 3858.rc
│ │ │ ├── 3859.rc
│ │ │ ├── 3865.rc
│ │ │ ├── 3866.rc
│ │ │ ├── 3867.rc
│ │ │ ├── 3868.rc
│ │ │ ├── 3869.rc
│ │ │ ├── 39.rc
│ │ │ ├── 40.rc
│ │ │ ├── 41.rc
│ │ │ ├── 430.rc
│ │ │ ├── 442.rc
│ │ │ ├── 578.rc
│ │ │ ├── 626.rc
│ │ │ ├── 63.rc
│ │ │ └── 7.rc
│ │ └── localizations.js
│ └── zh-simplified/
│ ├── Dialog/
│ │ └── 0804/
│ │ ├── 105.rc
│ │ ├── 108.rc
│ │ ├── 112.rc
│ │ ├── 113.rc
│ │ ├── 132.rc
│ │ ├── 30721.rc
│ │ ├── 30722.rc
│ │ ├── 30723.rc
│ │ ├── 37.rc
│ │ └── 4001.rc
│ ├── Menu/
│ │ └── 0804/
│ │ ├── 113.rc
│ │ ├── 118.rc
│ │ ├── 119.rc
│ │ ├── 2.rc
│ │ ├── 4.rc
│ │ └── 5.rc
│ ├── String Table/
│ │ └── 0804/
│ │ ├── 1.rc
│ │ ├── 129.rc
│ │ ├── 130.rc
│ │ ├── 131.rc
│ │ ├── 132.rc
│ │ ├── 135.rc
│ │ ├── 139.rc
│ │ ├── 141.rc
│ │ ├── 144.rc
│ │ ├── 145.rc
│ │ ├── 153.rc
│ │ ├── 2.rc
│ │ ├── 2049.rc
│ │ ├── 2050.rc
│ │ ├── 222.rc
│ │ ├── 2354.rc
│ │ ├── 2355.rc
│ │ ├── 2356.rc
│ │ ├── 2610.rc
│ │ ├── 2628.rc
│ │ ├── 2753.rc
│ │ ├── 2757.rc
│ │ ├── 2758.rc
│ │ ├── 2765.rc
│ │ ├── 2794.rc
│ │ ├── 3.rc
│ │ ├── 3585.rc
│ │ ├── 3601.rc
│ │ ├── 3602.rc
│ │ ├── 3603.rc
│ │ ├── 3605.rc
│ │ ├── 3606.rc
│ │ ├── 3713.rc
│ │ ├── 3714.rc
│ │ ├── 3825.rc
│ │ ├── 3826.rc
│ │ ├── 3841.rc
│ │ ├── 3842.rc
│ │ ├── 3843.rc
│ │ ├── 3845.rc
│ │ ├── 3849.rc
│ │ ├── 3850.rc
│ │ ├── 3857.rc
│ │ ├── 3858.rc
│ │ ├── 3859.rc
│ │ ├── 3865.rc
│ │ ├── 3866.rc
│ │ ├── 3867.rc
│ │ ├── 3868.rc
│ │ ├── 3869.rc
│ │ ├── 39.rc
│ │ ├── 40.rc
│ │ ├── 41.rc
│ │ ├── 430.rc
│ │ ├── 442.rc
│ │ ├── 578.rc
│ │ ├── 626.rc
│ │ ├── 63.rc
│ │ └── 7.rc
│ └── localizations.js
├── manifest.webmanifest
├── package.json
├── privacy.html
├── prune-globals.js
├── src/
│ ├── $ColorBox.js
│ ├── $Component.js
│ ├── $FontBox.js
│ ├── $ToolBox.js
│ ├── $ToolWindow.js
│ ├── Handles.js
│ ├── OnCanvasHelperLayer.js
│ ├── OnCanvasObject.js
│ ├── OnCanvasSelection.js
│ ├── OnCanvasTextBox.js
│ ├── app-localization.js
│ ├── app-state.js
│ ├── app.js
│ ├── color-data.js
│ ├── copy-inkscape-labels.js
│ ├── discord-activity-client.js
│ ├── edit-colors.js
│ ├── electron-injected.js
│ ├── electron-main.js
│ ├── error-handling-basic.js
│ ├── error-handling-enhanced.js
│ ├── extra-tools.js
│ ├── eye-gaze-mode.js
│ ├── file-format-data.js
│ ├── functions.js
│ ├── globals.d.ts
│ ├── help.js
│ ├── helpers.js
│ ├── image-manipulation.js
│ ├── imgur.js
│ ├── konami.js
│ ├── manage-storage.js
│ ├── menus.js
│ ├── msgbox.js
│ ├── repack-spritesheet.js
│ ├── save-history-as-spritesheet.js
│ ├── sessions.js
│ ├── simulate-random-gestures.js
│ ├── speech-recognition.js
│ ├── storage.js
│ ├── test-news.js
│ ├── theme.js
│ ├── tool-options.js
│ ├── tools.js
│ └── vaporwave-fun.js
├── styles/
│ ├── about.css
│ ├── layout.css
│ ├── layout.rtl.css
│ ├── legal.css
│ ├── normalize.css
│ ├── print.css
│ └── themes/
│ ├── bubblegum.css
│ ├── classic.css
│ ├── dark.css
│ ├── modern-dark.css
│ ├── modern.css
│ ├── occult.css
│ ├── red-wine.css
│ ├── vista-esque-midnight-green.css
│ └── winter.css
├── svg-paint/
│ ├── index.html
│ └── svg-paint.js
├── sync-package.js
└── test-news-newer.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
custom: ["https://www.paypal.me/IsaiahOdhner"]
================================================
FILE: .gitignore
================================================
# cypress-image-snapshot visual diffs
__diff_output__
# cypress-image-snapshot images of the whole cypress UI
*(failed).snap.png
# electron forge output
out/
# npm
node_modules/
*.log
*.log.*
# os crap
Thumbs.db
~*
================================================
FILE: .vscode/extensions.json
================================================
{
"recommendations": [
"streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint"
]
}
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
// To use this configuration, you must run Chrome with a flag:
// google-chrome --remote-debugging-port=9222 http://127.0.0.1:1999
// or for Windows:
// start chrome --remote-debugging-port=9222 http://127.0.0.1:1999
// and Chrome must not be running beforehand, as the flag won't apply otherwise.
// And you need to have the dev server running:
// npm run dev
// If you really don't want to close Chrome, you can use a temporary profile:
// mkdir C:\TempChromeProfile
// echo {"browser": {"has_seen_welcome_page": true, "default_browser_infobar_last_declined": "13354566465257726"}} > C:\TempChromeProfile\Preferences
// start chrome --remote-debugging-port=9222 --user-data-dir="C:\TempChromeProfile" --disable-fre --no-default-browser-check --no-first-run http://127.0.0.1:1999
// rmdir /s /q C:\TempChromeProfile
"type": "chrome",
"request": "attach",
"name": "Attach to Chrome",
"port": 9222,
"urlFilter": "http://127.0.0.1:1999/*",
"webRoot": "${workspaceFolder}"
},
{
// https://www.electronjs.org/docs/latest/tutorial/debugging-vscode
"name": "Electron: Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": [
"."
],
"outputCapture": "std"
}
]
}
================================================
FILE: .vscode/run-command-on-all-files.ahk
================================================
; This script runs on AutoHotkey v2.
;
; I tried the VS Code extension "Command on All Files" first: https://marketplace.visualstudio.com/items?itemName=rioj7.commandOnAllFiles
; but it didn't work with the "cSpell.addIssuesToDictionary" command.
; I think it was too fast, and the spell checker didn't have time to run.
;
; A better solution would be to:
; - Improve the "Command on All Files" extension:
; - add delay options
; - add a dry run mode, which I had to work around by setting it to a near-no-op command
; - just listing the files would be a lot nicer than opening them all one by one
; - unify file matching; you shouldn't have to specify a list of file extensions to include, it should be a glob like the exclusions
; Or:
; - Add a command to the cspell-cli to accept spellings
; Or:
; - Implement an external Node.js script using cspell's API (but that's less helpful than making a PR)
root := A_ScriptDir "\..\*"
ignoreFolders := [
".git",
".history",
"node_modules",
"lib",
"out",
"localization",
]
ignoreExtensions := [
"png",
"gif",
"jpg",
"jpeg",
"svg",
"cur",
"ico",
"icns",
"wav",
]
command := "cSpell.addIssuesToDictionary"
beforeRunInfo := "This script is designed to add all spelling issues to the dictionary.`nTo use it to prune the dictionary of no-longer-needed words, you must empty the dictionary first.`n`nThis script will run the VS Code command '" command "' on all files in the directory '" root "'.`n`n"
delayBeforeCommand := 2000 ; Give enough time for spell checker to run
delayAfterCommand := 2000 ; Give enough time for CSpell to update the dictionary
closeFileAfterCommand := false
appName := "VS Code Automation"
popup := Gui(, appName)
popup.Opt("+AlwaysOnTop +Disabled -SysMenu +Owner") ; +Owner avoids a taskbar button.
popup.Add("Text", , "`nPress Esc to stop the script.`n`n")
statusBar := popup.Add("StatusBar")
windowId := WinExist("ahk_exe Code.exe")
IsIgnoredPath(path) {
SplitPath path, &name, &dir, &ext, &nameNoExt, &drive
for _, ignoreExtension in ignoreExtensions {
if (StrLower(ext) = ignoreExtension) {
return true
}
}
parts := StrSplit(path, "\")
for index, part in parts {
for _, ignoreFolder in ignoreFolders {
if (part = ignoreFolder) {
return true
}
}
}
return false
}
Automate() {
targets := []
; Loop through files (F) recursively (R)
loop files, root, "FR"
{
if (IsIgnoredPath(A_LoopFileFullPath)) {
continue
}
targets.Push(A_LoopFileFullPath)
}
if (targets.Length = 0) {
MsgBox "No files found for pattern: " root
return
}
; Focus VS Code before confirmation to avoid confusion between multiple VS Code windows
try {
WinActivate { Hwnd: windowId }
} catch TargetError as e {
MsgBox "Could not find VS Code window. Please open it and try again.", appName, 0x10
return
}
; Ask for confirmation
if MsgBox(beforeRunInfo "Found " targets.Length " files. Continue?", appName, 4) = "No" {
if MsgBox("Copy file paths to clipboard?", appName, 4) = "Yes" {
A_Clipboard := Join("`n", targets)
}
return
}
RunCommandOnFiles(targets)
}
RunCommandOnFiles(targets) {
popup.Show("NoActivate") ; NoActivate avoids deactivating the currently active window.
for index, target in targets {
statusBar.SetText(index "/" targets.Length)
try {
RunCommandOnFile(target)
} catch TargetError as e {
popup.Destroy()
MsgBox "Lost VS Code window. Please open it and try again.`n`n" index " out of " targets.Length " files were processed.", appName, 0x10
return
}
}
popup.Destroy()
MsgBox "Processed " targets.Length " files."
return
}
SendToVSCode(keys) {
; ControlSend(keys, , { Hwnd: windowId })
WinActivate { Hwnd: windowId }
Send keys
}
RunCommandOnFile(target) {
; Open file in VS Code using Ctrl+P file switcher
SendToVSCode "^p"
Sleep 100
SendToVSCode target
Sleep 100
SendToVSCode "{Enter}"
Sleep delayBeforeCommand
; Run command via F1 command palette
SendToVSCode "{F1}"
Sleep 100
SendToVSCode command
Sleep 100
SendToVSCode "{Enter}"
Sleep delayAfterCommand
; Close the file (optional)
if closeFileAfterCommand {
SendToVSCode "^w"
}
}
Join(sep, items) {
str := ""
for index, item in items {
str .= item . sep
}
return SubStr(str, 1, -StrLen(sep))
}
; Escape hatch
Esc:: {
ExitApp
}
Automate()
ExitApp()
================================================
FILE: .vscode/settings.json
================================================
{
// This hides files from the file tree as well as search results.
"files.exclude": {
"**/node_modules": true,
"**/out": true,
},
// This affects Find In Files (Ctrl+Shift+F) but also Go To File (Ctrl+P) and
// the Quick Search, which I've been using a lot since it was released.
"search.exclude": {
"**/images": true,
"**/lib": true,
"**/out": true,
// The package lock file contains a lot of repetation, and is usually noise in search results.
// You can often search with `npm ls` if you want to check if a package is installed,
// and what depends on what.
"package-lock.json": true,
// Ignore localization data, which is in subfolders, but not helper scripts.
// Any time a search matches a localized string, it matches an overwhelming number of files.
"**/localization/*/**/*": true,
},
"editor.formatOnSave": true,
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"editor.codeActionsOnSave": {
"source.organizeImports": "always",
},
"javascript.preferences.importModuleSpecifierEnding": "js",
"typescript.preferences.importModuleSpecifierEnding": "js",
"html.format.unformattedContentDelimiter": "<!--no_format-->",
"[css]": {
// The CSS in this project uses (the lack of) newlines between rules for grouping, as well as inline comments.
// VS Code's default formatter adds newlines between all rules, and forces comments to the next line, dissociating them.
"editor.formatOnSave": false,
},
"[markdown]": {
// Formatting markdown tables automatically is cool, but doesn't allow padding cells to avoid superflous git diffs.
// Also, VS Code's markdown formatter doesn't handle emoji in tables as well as it could.
"editor.formatOnSave": false,
},
// Note: this doesn't apply to "JSON with comments" files, such as this one. That's [jsonc].
"[json]": {
// npm respects different indent styles, but always adds a newline at the end of package.json/package-lock.json,
// so this avoids ping-ponging changes in git.
// This could be applied to all files for consistency, but it may introduce noise if all files aren't formatted at once.
"files.insertFinalNewline": true,
// Maintaining current indentation for now, but could remove this for consistency.
"editor.detectIndentation": true,
},
// Use local TypeScript version instead of the one bundled with VS Code.
// You may need to run "TypeScript: Select TypeScript Version..." and choose "Use workspace version"
// or that command might just set this setting for you, I'm not sure.
// Go to a TS or JS file for the command to show up in the command palette.
"typescript.tsdk": "node_modules/typescript/lib",
// Prevent accidental editing.
// This can always be overridden with the command "File: Toggle Active Editor Read-only in Session"
"files.readonlyInclude": {
// Electron Forge output
"out/**": true,
// Built/installed app (sometimes I follow error message links into the built app's code, and end up editing it by mistake)
"**/resources/app/**": true,
// Node.js
"node_modules/**": true,
"package-lock.json": true,
// RTLCSS output
"**/*.rtl.css": true,
},
}
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Changed
- `systemHooks.writeBlobToHandle` promise can resolve with `true` to indicate success, in which case **File > Save** will not prompt to save the file again. `false` indicates failure or cancellation, whereas `undefined` can be used if it is unknown whether the file will be saved successfully, as is the case when using the `download` attribute on an anchor element. If saving as a monochrome bitmap, `undefined` will cause the canvas to become monochrome, but it will still prompt to save the file again. This tradeoff is reasonable because the download attribute doesn't support saving over an already saved file anyways
## [1.0.0] - 2022-08-02
### Added
- `systemHooks` API for overriding file dialogs, file saving/loading, and Set as Wallpaper commands
- `systemHooks.showSaveFileDialog = async ({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle }) => { ... };`
- `systemHooks.showOpenFileDialog = async ({ formats }) => { ... };`
- `systemHooks.writeBlobToHandle = async (save_file_handle, blob) => { ... };`
- `systemHooks.readBlobFromHandle = async (file_handle) => { ... };`
- `systemHooks.setWallpaperTiled = (canvas) => { ... };`
- `systemHooks.setWallpaperCentered = (canvas) => { ... };`
- function `undoable({ name, icon }, actionFunction)` to make an action undoable, as far is it modifies the canvas
- function `show_error_message(message, [error])` to show an error message dialog box, optionally with expandable error details
- function `open_from_file(blob, source_file_handle)` to load a file from a blob and file handle pair (kinda quirky API)
- function `set_theme(theme_file_name)` to switch themes
- function `set_language(language_code)` to switch languages, prompting the user to reload the application
- You can use `.main-canvas` selector to access the canvas element.
- URL parameter `#load:<URL>` to load a file from a URL
[Unreleased]: https://github.com/1j01/jspaint/compare/v1.0.0...HEAD
[1.1.0]: https://github.com/1j01/jspaint/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/1j01/jspaint/releases/tag/v1.0.0
================================================
FILE: CNAME
================================================
jspaint.app
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
## Pull Requests
Let me know before you work on something by opening an issue or commenting on an existing one.
Someone may be already working on it, or I may have specific plans or requirements.
I don't want your effort to be wasted!
## Issues
[Bugs and feature requests are tracked on GitHub.](https://github.com/1j01/jspaint/issues)
Before opening an issue for a bug or feature request, search to see if it's already been reported.
You can also [email me](mailto:isaiahodhner@gmail.com) if you prefer.
## Windows 98
Note: JS Paint's GUI is primarily based on Paint from Windows 98.
There's a nice [online emulator](https://copy.sh/v86/?profile=windows98)
that you can play around with and use as a reference.
## Dev Setup
See [**Development Setup**](./README.md#Development-Setup) on the readme.
### Project Structure
- `index.html` and `app.js` are the main entry points for the app.
- `functions.js` has functions that shouldn't own any global state, altho they very much modify global state, and there may be a few stateful global variables defined in there.
- The project uses [jQuery](https://jquery.com/), and a convention of prefixing variables that hold jQuery objects with `$`
- There are also some weird pseudo-classes like `$ColorBox` which extend and return jQuery objects. I don't recommend this pattern for new code.
- Menu code and windowing code lives in the [os-gui](https://github.com/1j01/os-gui) project.
- It can be synced (one-way) by running `npm i os-gui@latest --save-exact && npm run sync-os-gui`
- To develop os-gui in the context of jspaint, you can run `npm link` in a clone of os-gui, then run `npm link os-gui && npm run sync-os-gui` in jspaint after making any changes in os-gui.
- (Maybe I should version this using git-subrepo?)
- Some window behavior specific to jspaint is in `$ToolWindow.js` and `$Component.js`
- `image-manipulation.js` should contain just rendering related code, and ideally no dialogs except maybe some error messages.
- Some image manipulation code is also in `tools.js` and `functions.js`
- CSS is in `styles/`
- Layout-important CSS is kept separate from theme CSS
- Localization data is in `localization/`
- As of writing there's no good way to contribute translations, but [get in touch!](https://github.com/1j01/jspaint/issues/80)
Any good IDE or code editor has a project-wide search (often with <kbd>Ctrl+Shift+F</kbd>). I use this all the time.
I also use the "Intellisense" feature of [VS Code](https://code.visualstudio.com/) to jump to function definitions (an extra convenience over searching for function names).
================================================
FILE: LICENSE.txt
================================================
MIT License
Copyright (c) 2022 Isaiah Odhner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# [ JS Paint](https://jspaint.app)
A pixel-perfect web-based MS Paint remake and more... [Try it out!](https://jspaint.app)
Then join the [Discord server](https://discord.gg/jxQBK3k8tx) to share your art!
JS Paint recreates every tool and menu of MS Paint, and even [little-known features](#did-you-know), to a high degree of fidelity.
It supports themes, additional file types, and accessibility features like a Dwell Clicker and Speech Recognition.

Ah yes, good old Paint. Not the one with the [ribbons][]
or the [new skeuomorphic one][Fresh Paint] with the interface that can take up nearly half the screen.
(And not the even newer [Paint 3D][].)
[ribbons]: https://www.google.com/search?tbm=isch&q=MS+Paint+Windows+7+ribbons "Google Search: MS Paint Windows 7 ribbons"
[Fresh Paint]: https://www.google.com/search?tbm=isch&q=MS+Fresh+Paint "Google Search: MS Fresh Paint"
[Paint 3D]: https://www.microsoft.com/en-us/store/p/paint-3d-preview/9nblggh5fv99
Windows 95, 98, and XP were the golden years of Paint.
You had a tool box and a color box, a foreground color and a background color,
and that was all you needed.
Things were simple.
But we want to undo more than three actions.
We want to edit transparent images.
We can't just keep using the old Paint.
So that's why I'm making JS Paint.
I want to bring good old Paint into the modern era.
#### Current improvements include:
* Open source ([MIT licensed](LICENSE.txt))
* Cross-platform
* Mobile friendly
* Touch support: use two fingers to pan the view, and pinch to zoom
* Click/tap the selected colors area to swap the foreground and background colors
* **View > Fullscreen** to toggle fullscreen mode, nice for small screens
* **Extras > Quick Undo Button** to add a floating undo button for easier access
* (this may be enabled by default in the future for touch devices)
* Web features
* **File > Load From URL...** to open an image from the Web.
* **File > Upload to Imgur** to upload the current image to Imgur.
* **Paste** supports loading from URLs.
* You can create links that will open an image from the Web in JS Paint. For example, this link will start with an isometric grid as a template: <https://jspaint.app/#load:https://i.imgur.com/zJMrWwb.png>
* Rudimentary **multi-user** collaboration support.
Start up a session at
[jspaint.app/#session:multi-user-test](https://jspaint.app/#session:multi-user-test)
and send the link to your friends!
It isn't seamless; actions by other users interrupt what you're doing, and visa versa.
Sessions are not private, and you may lose your work at any time.
If you want better collaboration support, follow the development of [Mopaint](https://github.com/1j01/mopaint).
* **Extras > Themes** to change the look of the app.
* Dark and light variants
* Vector tool icons handcrafted to match the pixel art versions, for both Modern and Classic themes
* Occult theme, in the spirit of Halloween
* Winter theme, with a special color palette including candy cane stripes, and advent calendar style flaps revealing pixel art for each tool
* Bubblegum theme, featuring *Business Pink* color scheme and AI-generated icons
* **Extras > Enlarge UI** to make buttons and menus bigger, for usage with an eye tracker, head tracker, or other course input devices. May also work well for a tablet, but not so much for a phone at the moment.
* **Extras > Dwell Clicker** to click automatically by hovering in one spot, for usage with an eye tracker or head tracker.
* Hovered buttons are highlighted, and the click is performed after a delay.
* Supports dragging windows and drawing on the canvas.
* With just a webcam, you can try it out with [Enable Viacam](https://eviacam.crea-si.com/) (head tracker), [GazePointer](https://sourceforge.net/projects/gazepointer/) (eye tracker), or the built in [<img src="images/tracky-mouse-16x16.png" width="16" height="16"> Tracky Mouse](https://trackymouse.js.org/) head tracker using **Extras > Head Tracker**.
* This feature can be easily added to other web applications, using the [<img src="images/tracky-mouse-16x16.png" width="16" height="16"> Tracky Mouse API](https://www.npmjs.com/package/tracky-mouse).
* **Extras > Speech Recognition** to control the app with your voice.
* Select tools and colors ("fill tool", "orange", etc.)
* Pan the view ("scroll down and to the left", or "go southwest", etc.)
* Explore the menus, or activate any menu item without opening the menus first
* Interact with windows
* Dictate text with the Text tool
<!-- (Broken due to no-longer-free service) * Even tell the application to sketch things (for instance, "draw a house") -->
* Create an animated GIF from the current document history.
Accessible from the Extras menu or with <kbd>Ctrl+Shift+G</kbd>.
It's pretty nifty, you should try it out!
You might want to limit the size of the image though.
* Load and save [many different palette formats](#color-palette-formats) with **Colors > Get Colors** and **Colors > Save Colors**.
(I made a library for this: <img src="images/anypalette-logo-128x128.png" height="16"> [AnyPalette.js](https://github.com/1j01/anypalette.js).)
* You can also drag and drop palette files into the app to load.
Editing Features:
* Use Alt+Mousewheel to zoom in and out
* Edit transparent images! To create a transparent image,
go to **Image > Attributes...** and select Transparent,
then OK, and then **Image > Clear Image** or use the Eraser tool.
Images with *any* translucent pixels will open in Transparent mode.
* You can crop the image by making a selection while holding <kbd>Ctrl</kbd>
* Keyboard shortcuts for rotation: <kbd>Ctrl+.</kbd> and <kbd>Ctrl+,</kbd> (<kbd><</kbd> and <kbd>></kbd>)
* Rotate by any arbitrary angle in **Image > Flip/Rotate**
* In **Image > Stretch/Skew**, you can stretch more than 500% at once
* Zoom to an arbitrary scale in **View > Zoom > Custom...**
* Zoom to fit the canvas within the window with **View > Zoom > Zoom To Window**
* Non-contiguous fill: Replace a color in the entire image by holding <kbd>Shift</kbd> when using the fill tool
Miscellaneous Improvements:
* [Vertical Color Box mode](https://jspaint.app/#vertical-color-box-mode), accessible from **Extras > Vertical Color Box**
* You can use the Text tool at any zoom level (and it previews the exact pixels that will end up on the canvas).
* Spellcheck is available in the textbox if your browser supports it.
* Resize handles are easier to grab than in Windows 10's Paint.
* Omits some Thumbnail view bugs, like the selection showing in the wrong place.
* Unlimited undos/redos (as opposed to a measly 3 in Windows XP,
or a measly 50 in Windows 7)
* Undo history is *nonlinear*, which means if you undo and do something other than redo, the redos aren't discarded. Instead, a new branch is created in the *history tree*. Jump to any point in history with **Edit > History** or <kbd>Ctrl+Shift+Y</kbd>
* Automatically keeps a backup of your image. Only one backup per image tho, which doesn't give you a lot of safety. Remember to save with **File > Save** or <kbd>Ctrl+S</kbd>! Manage backups with **File > Manage Storage**.
<!--
Half-features:
* When you do **Edit > Paste From...** you can select transparent images.
~~You can even paste a transparent animated GIF and then
hold <kbd>Shift</kbd> while dragging the selection to
smear it across the canvas *while it animates*!~~
Update: This was [due to not-to-spec behavior in Chrome.](https://christianheilmann.com/2014/04/16/browser-inconsistencies-animated-gif-and-drawimage/)
I may reimplement this in the future as I really liked this feature.
* You can open SVG files, though only as a bitmap.
(Note: it may open super large, or tiny. There's no option to choose a size when opening.)
-->

#### Limitations:
A few things with the tools aren't done yet.
See [TODO.md](TODO.md#Tools)
Full clipboard support in the web app requires a browser supporting the [Async Clipboard API w/ Images](https://developers.google.com/web/updates/2019/07/image-support-for-async-clipboard), namely Chrome 76+ at the time of writing.
In other browsers you can still copy with <kbd>Ctrl+C</kbd>, cut with <kbd>Ctrl+X</kbd>, and paste with <kbd>Ctrl+V</kbd>,
but data copied from JS Paint can only be pasted into other instances of JS Paint.
External images can be pasted in.
## Supported File Formats
### Image Formats
⚠️ Saving as JPEG will introduce artifacts that cause problems when using the Fill tool or transparent selections.
⚠️ Saving in some formats will reduce the number of colors in the image.
💡 Unlike in MS Paint, you can use **Edit > Undo** to revert color or quality reduction from saving.
This doesn't undo saving the file, but allows you to then save in a different format with higher quality, using **File > Save As**.
💡 Saving as PNG is recommended as it gives small file sizes while retaining full quality.
| File Extension | Name | Read | Write | Read Palette | Write Palette |
|-------------------------------|-------------------------------|:----:|:-----:|:------------:|:-------------:|
| .png | [PNG][] | ✅ | ✅ | 🔜 | |
| .bmp, .dib | [Monochrome Bitmap][BMP] | ✅ | ✅ | 🔜 | ✅ |
| .bmp, .dib | [16 Color Bitmap][BMP] | ✅ | ✅ | 🔜 | ✅ |
| .bmp, .dib | [256 Color Bitmap][BMP] | ✅ | ✅ | 🔜 | ✅ |
| .bmp, .dib | [24-bit Bitmap][BMP] | ✅ | ✅ | N/A | N/A |
| .tif, .tiff, .dng, .cr2, .nef | [TIFF][] (loads first page) | ✅ | ✅ | | |
| .pdf | [PDF][] (loads first page) | ✅ | | | |
| .webp | [WebP][] | 🌐 | 🌐 | | |
| .gif | [GIF][] | 🌐 | 🌐 | | |
| .jpeg, .jpg | [JPEG][] | 🌐 | 🌐 | N/A | N/A |
| .svg | [SVG][] (only default size) | 🌐 | | | |
| .ico | [ICO][] (only default size) | 🌐 | | | |
Capabilities marked with 🌐 are currently left up to the browser to support or not.
If "Write" is marked with 🌐, the format will appear in the file type dropdown but may not work when you try to save.
For opening files, see Wikipedia's [browser image format support table][] for more information.
Capabilities marked with 🔜 may be coming soon, and N/A means not applicable.
"Read Palette" refers to loading the colors into the Colors box automatically (from an [indexed color][] image),
and "Write Palette" refers to writing an [indexed color][] image.
[PNG]: https://en.wikipedia.org/wiki/Portable_Network_Graphics
[BMP]: https://en.wikipedia.org/wiki/BMP_file_format
[TIFF]: https://en.wikipedia.org/wiki/TIFF
[PDF]: https://en.wikipedia.org/wiki/PDF
[WebP]: https://en.wikipedia.org/wiki/WebP
[GIF]: https://en.wikipedia.org/wiki/GIF
[JPEG]: https://en.wikipedia.org/wiki/JPEG
[SVG]: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
[ICO]: https://en.wikipedia.org/wiki/ICO_(file_format)
[indexed color]: https://en.wikipedia.org/wiki/Indexed_color
[browser image format support table]: https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
### Color Palette Formats
With **Colors > Save Colors** and **Colors > Get Colors** you can save and load colors
in many different formats, for compatibility with a wide range of programs.
If you want to add extensive palette support to another application, I've made this functionality available as a library:
<img src="images/anypalette-logo-128x128.png" height="16"> [AnyPalette.js](https://github.com/1j01/anypalette.js)
| File Extension | Name | Programs | Read | Write |
|-------------------|-----------------------------------|-----------------------------------------------------------------------------------|:-------:|:-------:|
| .pal | [RIFF] Palette | [MS Paint] for Windows 95 and Windows NT 4.0 | ✅ | ✅ |
| .gpl | [GIMP][Gimp] Palette | [Gimp], [Inkscape], [Krita], [KolourPaint], [Scribus], [CinePaint], [MyPaint] | ✅ | ✅ |
| .aco | Adobe Color Swatch | Adobe [Photoshop] | ✅ | ✅ |
| .ase | Adobe Swatch Exchange | Adobe [Photoshop], [InDesign], and [Illustrator] | ✅ | ✅ |
| .txt | [Paint.NET] Palette | [Paint.NET] | ✅ | ✅ |
| .act | Adobe Color Table | Adobe [Photoshop] and [Illustrator] | ✅ | ✅ |
| .pal, .psppalette | [Paint Shop Pro] Palette | [Paint Shop Pro] (Jasc Software / Corel) | ✅ | ✅ |
| .hpl | [Homesite] Palette | Allaire [Homesite] / Macromedia [ColdFusion] | ✅ | ✅ |
| .cs | ColorSchemer | ColorSchemer Studio | ✅ | |
| .pal | [StarCraft] Palette | [StarCraft] | ✅ | ✅ |
| .wpe | [StarCraft] Terrain Palette | [StarCraft] | ✅ | ✅ |
| .sketchpalette | [Sketch] Palette | [Sketch] | ✅ | ✅ |
| .spl | [Skencil] Palette | [Skencil] (formerly called Sketch) | ✅ | ✅ |
| .soc | StarOffice Colors | [StarOffice], [OpenOffice], [LibreOffice] | ✅ | ✅ |
| .colors | KolourPaint Color Collection | [KolourPaint] | ✅ | ✅ |
| .colors | Plasma Desktop Color Scheme | [KDE] Plasma Desktop | ✅ | |
| .theme | Windows Theme | [Windows] Desktop | ✅ | |
| .themepack | Windows Theme | [Windows] Desktop | ✅ | |
| .css, .scss, .styl| Cascading StyleSheets | Web browsers / web pages | ✅ | ✅ |
| .html, .svg, .js | any text files with CSS colors | Web browsers / web pages | ✅ | |
[RIFF]: https://en.wikipedia.org/wiki/Resource_Interchange_File_Format
[MS Paint]: https://en.wikipedia.org/wiki/Microsoft_Paint
[Paint.NET]: https://www.getpaint.net/
[Paint Shop Pro]: https://www.paintshoppro.com/en/
[StarCraft]: https://en.wikipedia.org/wiki/StarCraft
[Homesite]: https://en.wikipedia.org/wiki/Macromedia_HomeSite
[ColdFusion]: https://en.wikipedia.org/wiki/Adobe_ColdFusion
[StarOffice]: https://en.wikipedia.org/wiki/StarOffice
[OpenOffice]: https://www.openoffice.org/
[LibreOffice]: https://www.libreoffice.org/
[Sketch]: https://www.sketchapp.com/
[Skencil]: https://skencil.org/
[Photoshop]: https://www.adobe.com/products/photoshop.html
[InDesign]: https://www.adobe.com/products/indesign.html
[Illustrator]: https://www.adobe.com/products/illustrator.html
[Gimp]: https://www.gimp.org/
[Inkscape]: https://inkscape.org/en/
[Krita]: https://www.calligra.org/krita/
[KolourPaint]: http://kolourpaint.org/
[KDE]: https://kde.org/
[Windows]: https://en.wikipedia.org/wiki/Microsoft_Windows
[Scribus]: https://www.scribus.net/
[CinePaint]: http://www.cinepaint.org/
[MyPaint]: http://mypaint.org/
## Did you know?
* There's a black and white mode with *patterns* instead of colors in the palette,
which you can get to from **Image > Attributes...**
* You can drag the color box and tool box around if you grab them by the right place.
You can even drag them out into little windows.
You can dock the windows back to the side by double-clicking on their title bars.
* In addition to the left-click foreground color and the right-click background color,
there's a third color you can access by holding <kbd>Ctrl</kbd> while you draw.
It starts out with no color so you'll need to hold <kbd>Ctrl</kbd> and select a color first.
The fancy thing about this color slot is you can
press and release <kbd>Ctrl</kbd> to switch colors *while drawing*.
* You can apply image transformations like Flip/Rotate, Stretch/Skew or Invert (in the Image menu) either to the whole image or to a selection.
Try scribbling with the Free-Form Select tool and then doing **Image > Invert**
* These Tips and Tricks from [a tutorial for MS Paint](https://www.albinoblacksheep.com/tutorial/mspaint)
also work in JS Paint:
* [x] Brush Scaling (<kbd>+</kbd> & <kbd>-</kbd> on the number pad to adjust brush size)
* [x] "Custom Brushes" (hold <kbd>Shift</kbd> and drag the selection to smear it)
* [x] The 'Stamp' "Tool" (hold <kbd>Shift</kbd> and click the selection to stamp it)
* [x] Image Scaling (<kbd>+</kbd> & <kbd>-</kbd> on the number pad to scale the selection by factors of 2)
* [x] Color Replacement (right mouse button with Eraser to selectively replace the foreground color with the background color)
* [x] The Grid (<kbd>Ctrl+G</kbd> & Zoom to 4x+)
* [x] Quick Undo (Pressing a second mouse button cancels the action you were performing.
I also made it redoable, in case you do it by accident!)
* [ ] Scroll Wheel Bug (Hmm, let's maybe not recreate this?)
## Desktop App
### PWA
JS Paint can be installed as a Progressive Web App (PWA), although it doesn't work offline yet.
Look for the install prompt in the address bar.
PWA features:
- No address bar; middle-ground between web and native
- Cross-platform (macOS, Windows, Linux, Android, iOS)
- Basic file integration:
- File > Open
- File > Save downloads the file after asking for a filename and format
- Drag and drop files onto the window to open them
Missing features:
- <details><summary>Directly saving to files is implemented but not enabled currently.</summary>I was concerned about data loss for two reasons: 1. the change in behavior of File > Save / Ctrl+S from effectively acting as Save As to overwriting files directly, although I made a warning dialog for this, with a don't show again option; 2. there was a bad bug with saved files ending up completely empty (zero bytes), which I don't know if was a bug in my code or in Chrome.</details>
- <details><summary>Offline support is not implemented.</summary>I've taken a few stabs at this, and <a href="https://github.com/1j01/jspaint/pull/144">I'm not the only one</a>, but there are some huge caveats, such as the development server not being able to live-reload without disabling the service worker.</details>
### Electron
I've also built it into a desktop app with [Electron][] and [Electron Forge][].
You can download it from the [releases page][].

Electron app features:
- Native-like experience (runs in a window with no address bar)
- Cross-platform (macOS, Windows, Linux)
- Clipboard support
- Files can be opened in various ways:
- **File > Open**
- Drag and drop onto window
- Drag and drop onto dock icon on macOS
- Drag and drop onto desktop shortcut
- **Right Click > Open With** in file manager (macOS and Linux)
- On Windows, you can manually paste the path to the executable into the Open With dialog, which you can find by right clicking the app in the taskbar, then right clicking the app's name, and selecting Properties. In the Shortcut tab, the Target field is the path to the executable. Once you open the app in this way, the app will show up in the Open With list, and if you select "Always", it will become the default app for that file type.
- Command line: type `jspaint path/to/file.png` in the terminal
- **File > Save** will save directly to the file
- **File > Set As Wallpaper (Tiled)** and **File > Set As Wallpaper (Centered)**
- On macOS, an icon representing the currently open file is shown in the titlebar. You can drag this icon into other applications, for example to include the image you're editing in an email. The icon is dimmed while there are unsaved changes.
<details><summary>Electron app limitations</summary>
- Basics:
- Execution is blocked by default on Mac and Windows
- On macOS you need to Ctrl+click the file and then say Open
- On Windows, you need to say "More info" and then "Run" (or "Run anyway"?)
- I would need to pay a fee for code signing to avoid this. It's basically *security by extortion*.
- There are no automatic updates. Apparently I would need to pay a fee for code signing to get this free service.
- That said, **Help > About Paint** can tell you if JS Paint is out of date, at least in terms of news updates.
- Electron is out of date. It may, for instance, contain image decoding vulnerabilities that have since been fixed. However, I've taken precautions to sandbox the app and restrict write access to a list of files explicitly opened in the app, the list being controlled by the main process, separate from the renderer process which would handle image decoding.
- Only a single editor window can be opened at once.
- The File menu's recent files list is not implemented, nor are [OS-specific jump menus](https://www.electronjs.org/docs/latest/tutorial/recent-documents).
- Minor details:
- A very confusing message is shown if you edit a document before clicking an Open link in the Manage Storage dialog.
- WebGL error messages tell you to refresh without offering a way to reload; also, calling the app a web page feels unpolished
- The File > Open dialog does not have an All Files (\*.\*) option, and the list of file types supported is not exhaustive; for example, AVIF images can be loaded but only by drag and drop
- Drag and drop shows two "Save changes to X?" dialogs on top of each other?
- I'm not sure if all of these are still issues, need to retest them:
- Quit doesn't exit app completely, only closes the window if it's open... intended behavior? shouldn't right click > Quit really quit? https://stackoverflow.com/questions/44316306/how-to-quit-electron-app-on-mac
- Quit doesn't show/focus window when save changes prompt is shown on maybe mac/linux
- Ctrl+C doesn't exit on mac/linux https://github.com/electron/electron/issues/5273
- this is because of `editor_window.on("close")` calling `preventDefault` and may be a feature but needs to show/focus the window
- https://stackoverflow.com/questions/75362687/electron-js-processes-do-not-exit-on-app-quit
- Opening an SVG file also isn't working via command line argument (dragging onto the shortcut in File Explorer) even though dragging and dropping into the window works.
- Seems to load load SVG as a palette... Is this what I was running into?
</details>
[Electron]: https://electronjs.org/
[Electron Forge]: https://electronforge.io/
[releases page]: https://github.com/1j01/jspaint/releases/
## Development Setup
[Clone the repo.](https://help.github.com/articles/cloning-a-repository/)
Install [Node.js][] if you don't have it, then open up a command prompt / terminal in the project directory.
### Quality Assurance
Run `npm run lint` to check for spelling errors, type errors, code style issues, and other problems.
Run `npm run format` to automatically fix formatting issues, or `npx eslint --fix` to fix all auto-fixable issues.
The formatting rules are configured for compatibility with VS Code's built-in formatter.
Run `npm test` to run browser-based tests with Cypress. (It's slow to start up and run tests, unfortunately.)
Run `npm run accept` to accept any visual changes.
This unfortunately re-runs all the tests, rather than accepting results of the previous test, so you could end up with different results than the previous test.
If you use [GitHub Desktop](https://desktop.github.com/), you can view diffs of images, in four different modes.
To open the Cypress UI, first run `npm run test:start-server`, then concurrently `npm run cy:open`
### Web App (https://jspaint.app)
After you've installed dependencies with `npm i`,
use `npm run dev` to start a live-reloading server.
Make sure any layout-important styles go in `layout.css`.
When updating `layout.css`, a right-to-left version of the stylesheet is generated, using [RTLCSS](https://rtlcss.com/).
You should test the RTL layout by changing the language to Arabic or Hebrew.
Go to **Extras > Language > العربية** or **עברית**.
See [Control Directives](https://rtlcss.com/learn/usage-guide/control-directives/) for how to control the RTL layout.
There is a VS Code launch task for attaching to Chrome for debugging.
See `.vscode/launch.json` for usage instructions.
### Desktop App (Electron)
- Install dependencies with `npm i`
- Start the electron app with `npm run electron:start`
[electron-debug][] is included, so you can use <kbd>F5</kbd>/<kbd>Ctrl+R</kbd> to reload and <kbd>F12</kbd>/<kbd>Ctrl+Shift+I</kbd> to open the devtools.
You can build for production with `npm run electron:make`
There is a VS Code launch task for debugging the Electron main process.
For the renderer process, you can use the embedded Chrome DevTools.
[Live Server]: https://github.com/1j01/live-server
[Node.js]: https://nodejs.org/
[electron-debug]: https://github.com/sindresorhus/electron-debug
## Deployment
JS Paint can be deployed using a regular web server.
Nothing needs to be compiled.
### CORS proxy
Optionally, you can set up a [CORS Anywhere](https://github.com/Rob--W/cors-anywhere) server, for loading images from the web, if you paste a URL into JS Paint, or use the `#load:<URL>` feature with images that are not on the same domain.
By default it will use a [CORS Anywhere instance](https://jspaint-cors-proxy.herokuapp.com) set up to work with [jspaint.app](https://jspaint.app).
It is hosted for free on [Heroku](https://www.heroku.com/),
and you can set up your own instance and configure it to work with your own domain.
You'll have to find and replace `https://jspaint-cors-proxy.herokuapp.com` with your own instance URL.
### Multiplayer Support
Multiplayer support currently relies on Firebase,
which is not open source software.
You could create a [Firebase Realtime Database](https://firebase.google.com/docs/database/web/start) instance and edit JS Paint's `sessions.js` to point to it,
replacing the `config` passed to `initializeApp` with the config from the Firebase Console when you set up a Web App.
But the multiplayer mode is very shoddy so far.
It should be replaced with something open source, more secure, more efficient, and more robust.
## Embed in your website
### Simple
Add this to your HTML:
```html
<iframe src="https://jspaint.app" width="100%" height="100%"></iframe>
```
#### Start with an image
You can have it load an image from a URL by adding `#load:<URL>` to the URL.
```html
<iframe src="https://jspaint.app#load:https://jspaint.app/favicon.ico" width="100%" height="100%"></iframe>
```
### Advanced
If you want to control JS Paint, how it saves/loads files, or access the canvas directly,
there is an unstable API.
First you need to [clone the repo](https://help.github.com/articles/cloning-a-repository/),
so you can point an `iframe` to your local copy.
The local copy of JS Paint has to be hosted on the same web server as the containing page, or more specifically, it has to share the [same origin](https://en.wikipedia.org/wiki/Same-origin_policy).
Having a local copy also means things won't break any time the API changes.
If JS Paint is cloned to a folder called `jspaint`, which lives in the same folder as the page you want to embed it in, you can use this:
```html
<iframe src="jspaint/index.html" id="jspaint-iframe" width="100%" height="100%"></iframe>
```
If it lives somewhere else, you may need to add `../` to the start of the path, to go up a level. For example, `src="../../apps/jspaint/index.html"`.
You can also use an absolute URL, like `src="https://example.com/cool-apps/jspaint/index.html"`.
#### Changing how files are saved/loaded
You can override the file saving and opening dialogs
with JS Paint's `systemHooks` API.
```html
<script>
var iframe = document.getElementById("jspaint-iframe");
var jspaint = iframe.contentWindow;
// Wait for systemHooks object to exist (the iframe needs to load)
waitUntil(()=> jspaint.systemHooks, 500, ()=> {
// Hook in
jspaint.systemHooks.showSaveFileDialog = async ({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle }) => { ... };
jspaint.systemHooks.showOpenFileDialog = async ({ formats }) => { ... };
jspaint.systemHooks.writeBlobToHandle = async (save_file_handle, blob) => { ... };
jspaint.systemHooks.readBlobFromHandle = async (file_handle) => { ... };
});
// General function to wait for a condition to be met, checking at regular intervals
function waitUntil(test, interval, callback) {
if (test()) {
callback();
} else {
setTimeout(waitUntil, interval, test, interval, callback);
}
}
</script>
```
A [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) represents the contents of a file in memory.
A file handle is anything that can identify a file.
You get to own this concept, and define how to identify files.
It could be anything from an index into an array, to a Dropbox file ID, to an IPFS URL, to a file path.
It can be any type, or maybe it needs to be a string, I forget.
Once you have a concept of a file handle, you can implement file pickers using the system hooks, and functions to read and write files.
| Command | Hooks Used |
| ------- | ---------- |
| **File > Save As** | [`systemHooks.showSaveFileDialog`][], then when a file is picked, [`systemHooks.writeBlobToHandle`][] |
| **File > Open** | [`systemHooks.showOpenFileDialog`][], then when a file is picked, [`systemHooks.readBlobFromHandle`][] |
| **File > Save** | [`systemHooks.writeBlobToHandle`][] (or same as **File > Save As** if there's no file open yet) |
| **Edit > Copy To** | [`systemHooks.showSaveFileDialog`][], then when a file is picked, [`systemHooks.writeBlobToHandle`][] |
| **Edit > Paste From** | [`systemHooks.showOpenFileDialog`][], then when a file is picked, [`systemHooks.readBlobFromHandle`][] |
| **File > Set As Wallpaper (Tiled)** | [`systemHooks.setWallpaperTiled`][] if defined, else [`systemHooks.setWallpaperCentered`][] if defined, else same as **File > Save As** |
| **File > Set As Wallpaper (Centered)** | [`systemHooks.setWallpaperCentered`][] if defined, else same as **File > Save As** |
| **Extras > Render History As GIF** | Same as **File > Save As** |
| **Colors > Save Colors** | Same as **File > Save As** |
| **Colors > Get Colors** | Same as **File > Open** |
#### Loading a file initially
To start the app with a file loaded for editing,
wait for the app to load, then call [`systemHooks.readBlobFromHandle`][] with a file handle, and tell the app to load that file blob.
```js
const file_handle = "initial-file-to-load";
systemHooks.readBlobFromHandle(file_handle).then(file => {
if (file) {
contentWindow.open_from_file(file, file_handle);
}
}, (error) => {
// Note: in some cases, this handler may not be called, and instead an error message is shown by readBlobFromHandle directly.
contentWindow.show_error_message(`Failed to open file ${file_handle}`, error);
});
```
This is clumsy, and in the future there may be a query string parameter to load an initial file by its handle.
(Note to self: it will need to wait for your system hooks to be registered, somehow.)
There's already a query string parameter to load from a URL:
```html
<iframe src="https://jspaint.app?load:SOME_URL_HERE"></iframe>
```
But this won't set up the file handle for saving.
#### Integrating Set as Wallpaper
You can define two functions to set the wallpaper, which will be used by **File > Set As Wallpaper (Tiled)** and **File > Set As Wallpaper (Centered)**.
- [`systemHooks.setWallpaperTiled`][]` = (canvas) => { ... };`
- [`systemHooks.setWallpaperCentered`][]` = (canvas) => { ... };`
If you define only [`systemHooks.setWallpaperCentered`][], JS Paint will attempt to guess your screen's dimensions and tile the image, applying it by calling your [`systemHooks.setWallpaperCentered`][] function.
If you don't specify [`systemHooks.setWallpaperCentered`][], JS Paint will default to saving a file (`<original file name> wallpaper.png`) using [`systemHooks.showSaveFileDialog`][] and [`systemHooks.writeBlobToHandle`][].
Here's a full example supporting a persistent custom wallpaper as a background on the containing page:
```js
const wallpaper = document.querySelector("body"); // or some other element
jspaint.systemHooks.setWallpaperCentered = (canvas) => {
canvas.toBlob((blob) => {
setDesktopWallpaper(blob, "no-repeat", true);
});
};
jspaint.systemHooks.setWallpaperTiled = (canvas) => {
canvas.toBlob((blob) => {
setDesktopWallpaper(blob, "repeat", true);
});
};
function setDesktopWallpaper(file, repeat, saveToLocalStorage) {
const blob_url = URL.createObjectURL(file);
wallpaper.style.backgroundImage = `url(${blob_url})`;
wallpaper.style.backgroundRepeat = repeat;
wallpaper.style.backgroundPosition = "center";
wallpaper.style.backgroundSize = "auto";
if (saveToLocalStorage) {
const fileReader = new FileReader();
fileReader.onload = () => {
localStorage.setItem("wallpaper-data-url", fileReader.result);
localStorage.setItem("wallpaper-repeat", repeat);
};
fileReader.onerror = () => {
console.error("Error reading file (for setting wallpaper)", file);
};
fileReader.readAsDataURL(file);
}
}
// Initialize the wallpaper from localStorage, if it exists
try {
const wallpaper_data_url = localStorage.getItem("wallpaper-data-url");
const wallpaper_repeat = localStorage.getItem("wallpaper-repeat");
if (wallpaper_data_url) {
fetch(wallpaper_data_url).then(response => response.blob()).then(file => {
setDesktopWallpaper(file, wallpaper_repeat, false);
});
}
} catch (error) {
console.error(error);
}
```
It's a little bit recursive, sorry; it could probably be done simpler.
Like by just using data URLs. (Actually, I think I wanted to use blob URLs just so that it doesn't bloat the DOM inspector with a super long URL. Which is really a devtools UX bug. Maybe they've improved this?)
#### Specifying the canvas size
You can load a file that has the desired dimensions.
There's no special API for this at the moment.
See [Loading a file initially](#loading-a-file-initially).
#### Specifying the theme
You could change the theme programmatically:
```js
var iframe = document.getElementById("jspaint-iframe");
var jspaint = iframe.contentWindow;
jspaint.set_theme("modern.css");
```
but this will break the user preference.
The **Extras > Themes** menu will still work, but the preference won't persist when reloading the page.
In the future there may be a query string parameter to specify the default theme. You could also fork jspaint to change the default theme.
#### Specifying the language
Similar to the theme, you can try to change the language programmatically:
```js
var iframe = document.getElementById("jspaint-iframe");
var jspaint = iframe.contentWindow;
jspaint.set_language("ar");
```
but this will actually **ask the user to reload the application** to change languages.
The **Extras > Language** menu will still work, but the user will be bothered to change the language every time they reload the page.
In the future there may be a query string parameter to specify the default language. You could also fork jspaint to change the default language.
#### Adding custom menus
Not supported yet.
You could fork jspaint and add your own menus.
#### Accessing the canvas directly
With access to the canvas, you can implement a live preview of your drawing, for example updating a texture in a game engine in realtime.
```js
var iframe = document.getElementById("jspaint-iframe");
// contentDocument here refers to the webpage loaded in the iframe, not the image document loaded in jspaint.
// We're just reaching inside the iframe to get the canvas.
var canvas = iframe.contentDocument.querySelector(".main-canvas");
```
It's recommended **not** to use this for loading a document, as it won't change the document title, or reset undo/redo history, among other things.
Instead use [`open_from_file`][].
#### Performing custom actions
If you want to make buttons or other UI to do things to the document, you should (probably) make it undoable.
It's very easy, just wrap your action in a call to [`undoable`][].
```js
var iframe = document.getElementById("jspaint-iframe");
var jspaint = iframe.contentWindow;
var icon = new Image();
icon.src = "some-folder/some-image-15x11-pixels.png";
jspaint.undoable({
name: "Seam Carve",
icon: icon, // optional
}, function() {
// do something to the canvas
});
```
#### <a href="#systemHooks.showSaveFileDialog" id="systemHooks.showSaveFileDialog">async function `systemHooks.showSaveFileDialog({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle })`</a>
[`systemHooks.showSaveFileDialog`]: #systemHooks.showSaveFileDialog
Define this function to override the default save dialog.
This is used both for saving images, as well as palette files, and animations.
Arguments:
- `formats`: an array of objects representing types of files, with the following properties:
- `formatID`: a string that uniquely identifies the format (may be the same as `mimeType`)
- `mimeType` (optional): the file format's designated [media type](https://en.wikipedia.org/wiki/Media_type), e.g. `"image/png"` (palette formats do not have this property)
- `name`: the file format's name, e.g. `"WebP"`
- `nameWithExtensions`: the file format's name followed by a list of extensions, e.g. `"TIFF (*.tif;*.tiff)"`
- `extensions`: an array of file extensions, excluding the dot, with the preferred extension first, e.g. `["bmp", "dib"]`
- `defaultFileName` (optional): a suggested file name, e.g. `"Untitled.png"` or the name of an open document.
- `defaultPath` (optional): a file handle for a document that was opened, so you can save to the same folder easily. Misnomer: this may not be a path, it depends on how you define file handles.
- `defaultFileFormatID` (optional): the `formatID` of a file format to select by default.
- `async function getBlob(formatID)`: a function you call to get a file in one of the supported formats. It takes a `formatID` and returns a `Promise` that resolves with a `Blob` representing the file contents to save.
- `function savedCallbackUnreliable({ newFileName, newFileFormatID, newFileHandle, newBlob })` (optional): a function you call when the user has saved the file. The `newBlob` should come from `getBlob(newFileFormatID)`.
- `dialogTitle` (optional): a title for the save dialog.
Note the inversion of control here:
JS Paint calls your `systemHooks.showSaveFileDialog` function, and then you call JS Paint's `getBlob` function.
Once `getBlob` resolves, you can call the `savedCallbackUnreliable` function which is defined by JS Paint.
(Hopefully I can clarify this in the future.)
Also note that this function is responsible for saving the file, not just picking a save location.
You may reuse your `systemHooks.writeBlobToHandle` function if it's helpful.
#### <a href="#systemHooks.showOpenFileDialog" id="systemHooks.showOpenFileDialog">async function `systemHooks.showOpenFileDialog({ formats })`</a>
[`systemHooks.showOpenFileDialog`]: #systemHooks.showOpenFileDialog
Define this function to override the default open dialog.
This is used for opening images and palettes.
Arguments:
- `formats`: same as `systemHooks.showSaveFileDialog`
Note that this function is responsible for loading the contents of the file, not just picking a file.
You may reuse your `systemHooks.readBlobFromHandle` function if it's helpful.
#### <a href="#systemHooks.writeBlobToHandle" id="systemHooks.writeBlobToHandle">async function `systemHooks.writeBlobToHandle(fileHandle, blob)`</a>
[`systemHooks.writeBlobToHandle`]: #systemHooks.writeBlobToHandle
Define this function to tell JS Paint how to save a file.
Arguments:
- `fileHandle`: a file handle, as defined by your system, representing the file to write to.
- `blob`: a `Blob` representing the file contents to save.
Returns:
- `Promise` that resolves with `true` if the file was definitely saved successfully, `false` if an error occurred or the user canceled, or `undefined` if it is not known whether the file was saved successfully, as is the case with file downloading with `<a href="..." download="...">`. The promise should not reject; errors should be handled by showing an error message and returning `false`.
#### <a href="#systemHooks.readBlobFromHandle" id="systemHooks.readBlobFromHandle">async function `systemHooks.readBlobFromHandle(fileHandle)`</a>
[`systemHooks.readBlobFromHandle`]: #systemHooks.readBlobFromHandle
Define this function to tell JS Paint how to load a file.
Arguments:
- `fileHandle`: a file handle, as defined by your system, representing the file to read from.
#### <a href="#systemHooks.setWallpaperTiled" id="systemHooks.setWallpaperTiled">function `systemHooks.setWallpaperTiled(canvas)`</a>
[`systemHooks.setWallpaperTiled`]: #systemHooks.setWallpaperTiled
Define this function to tell JS Paint how to set the wallpaper. See [Integrating Set as Wallpaper](#integrating-set-as-wallpaper) for an example.
Arguments:
- `canvas`: a `HTMLCanvasElement` with the image to set as the wallpaper.
#### <a href="#systemHooks.setWallpaperCentered" id="systemHooks.setWallpaperCentered">function `systemHooks.setWallpaperCentered(canvas)`</a>
[`systemHooks.setWallpaperCentered`]: #systemHooks.setWallpaperCentered
Define this function to tell JS Paint how to set the wallpaper. See [Integrating Set as Wallpaper](#integrating-set-as-wallpaper) for an example.
Arguments:
- `canvas`: a `HTMLCanvasElement` with the image to set as the wallpaper.
#### <a href="#undoable" id="undoable">function `undoable({ name, icon }, actionFunction)`</a>
[`undoable`]: #undoable
Use this to make an action undoable.
This function takes a snapshot of the canvas, and some other state, and then calls the `actionFunction` function.
It creates an entry in the history so it can be undone.
Arguments:
- `name`: a name for the action, e.g. `"Brush"` or `"Rotate Image 270°"`
- `icon` (optional): an `Image` to display in the History window. It is recommended to be 15x11 pixels.
- `actionFunction`: a function that takes no arguments, and modifies the canvas.
#### <a href="#show_error_message" id="show_error_message">function `show_error_message(message, [error])`</a>
[`show_error_message`]: #show_error_message
Use this to show an error message dialog box, optionally with expandable error details.
Arguments:
- `message`: plain text to show in the dialog box.
- `error` (optional): an `Error` object to show in the dialog box, collapsed by default in a "Details" expandable section.
#### <a href="#open_from_file" id="open_from_file">function `open_from_file(blob, source_file_handle)`</a>
[`open_from_file`]: #open_from_file
Use this to load a file into the app.
Arguments:
- `blob`: a `Blob` object representing the file to load.
- `source_file_handle`: a *corresponding* file handle for the file, as defined by your system.
Sorry for the quirky API.
The API is new, and parts of it have not been designed at all. This was just a hack that I came to depend on, reaching into the internals of JS Paint to load a file.
I decided to document it as the first version of the API, since I'll want a changelog when upgrading my usage of it anyways.
#### <a href="#set_theme" id="set_theme">function `set_theme(theme_file_name)`</a>
[`set_theme`]: #set_theme
Use this to change the look of the application.
Arguments:
- `theme_file_name`: the name of the theme file to load, one of:
- `"classic.css"`: the Windows98 theme.
- `"dark.css"`: the Dark theme.
- `"modern.css"`: the Modern theme.
- `"winter.css"`: the festive Winter theme.
- `"occult.css"`: a Satanic theme.
#### <a href="#set_language" id="set_language">function `set_language(language_code)`</a>
[`set_language`]: #set_language
You can kind of use this to change the language of the application. But actually it will show a prompt to the user to change the language, because the application needs to reload to apply the change.
And if that dialog isn't in the right language, well, they'll probably be confused.
Arguments:
- `language_code`: the language code to use, e.g. `"en"` for English, `"zh"` for Traditional Chinese, `"zh-simplified"` for Simplified Chinese, etc.
#### Changelog
The API will change a lot, but changes will be documented in the [Changelog](CHANGELOG.md).
Not just a history of changes, but a migration/upgrading guide. <!-- These are some Ctrl+F keywords. -->
For general project news, click **Extras > Project News** in the app.
## License
JS Paint is free and open source software, licensed under the permissive [MIT license](https://opensource.org/licenses/MIT).
[](https://opensource.org/licenses/MIT)
[](https://github.com/1j01/jspaint/stargazers)
[](https://github.com/1j01/jspaint/network/members)
================================================
FILE: TODO.md
================================================
#  JS Paint Todo
### Help
* Link-esque things
* Popups (I'd probably make the text within the popups selectable)
* Related topics (I'd probably make this a heading with links instead of the weird context menu thing)
* Add topics
* In "Tips and Tricks" (which is just a lame section)
* Transparency
* Multi-user / collaboration / "To share the document On-Line" or whatever
* Index
* Search
* Keyboard support
* Interactive tutorials?
* Possibly hosted by Clippy, with [ClippyJS](https://www.smore.com/clippy-js)
* Links the cat has a good "GetArtsy" animation, which would be good to use especially if talking about stamping and smearing selections
* Highlight elements on the page
* Be sure to cover undo/redo, and file saving
### Visual
* Fill bucket and airbrush cursors are supposed to invert the background in parts. This is not possible with `.png` files. Microsoft Edge also apparently requires `.cur` files for custom cursors. I already have `.cur` files in the repo for the modern theme (unused), and extracted (outside the repo) for the classic theme. I just need to copy them, rename them semantically, use them, and do some testing to see if format fallbacks work as expected.
### Extended editing
* Optional fill tolerance (slider that you enable from a settings menu?)
* Transparency
* Color opacity slider
* Toggle between blend and copy (overwrite) modes
* Maybe equivalize any rgba(X, X, X, 0) in fill algorithm?
There'd still be the possibility of 1/255th opacity pixels,
but if you're creating colors from the combination of a color picker and an opacity slider,
you might naturally introduce differing zero-opacity color values a lot.
* Documents with multiple sub-images
* Component to switch between sub-images
* Handle undo/redo for sub-images
* Animated GIFs
* Transparency ([jnordberg/gif.js issue #5](https://github.com/jnordberg/gif.js/issues/5))
* Animated Transparent APNGs
* APNG Library: [UPNG.js](https://github.com/photopea/UPNG.js/) (already used for loading/saving PNGs)
* Multi-size Icons
* Windows ICO ([jBinary can read](https://jdataview.github.io/jBinary.Repo/demo/#ico) and presumably write ICO files)
* Mac ICNS
* Layered images
* Photoshop PSD ([via psd.js](https://github.com/samccone/psd.js)
* OpenRaster ORA ([via ora.js](https://github.com/zsgalusz/ora.js))
* Paged Images
* PDF (via [pdf.js](https://github.com/mozilla/pdf.js)) (single page already supported)
* DjVu (via [djvu.js](https://djvu.js.org/))
* TIFF (via [utif.js](https://github.com/photopea/UTIF.js/)) (single page/frame already supported)
* Online (multi-user) and local (single-user) sessions
* See [sessions.js](src/sessions.js)
* Issues
* There's no conflict resolution; user edits revert other user edits
* It's not eventually consistent
* Cursors from other users that go outside the parent can cause the page to be scrollable
* Symmetry, tesselation, painting texture on 3D models, and even an infinite canvas, all could be done with a shared system
* For symmetry and tesselation, [geometry can be generated](), and then it can work the same as painting on a 3D model
* An infinite canvas engine would generate simple square geometry, but would require support for multiple editable textures (also useful for 3D models)
* And of course layers and animations and multi-size icons need a similar system (multiple sub-images)
* For 3D model painting, it's important to note there's a few different possible approaches.
1. UV-dynamic, like [Chameleon](https://www-ui.is.s.u-tokyo.ac.jp/~takeo/chameleon/chameleon.htm) & [Chameleon.js](https://tomtung.github.io/chameleon.js/) (can adapt texture resolution as you paint)
2. UV-static
1. Ray tracing the pointer to find texture coordinates (gives texture coordinate space scaled result by default)
2. Screen-space drawing (gives screen space scaled result by default); I saw a good medium post or two about this
* Also, some approaches might not extend to tesselation and symmetry. ["Very important, this means that we assume our uv has no overlapping triangles. So no \[tileable\] textures."](https://shahriyarshahrabi.medium.com/mesh-texture-painting-in-unity-using-shaders-8eb7fc31221c)
* Existing 3D texturing systems:
* Closed source project: https://discourse.threejs.org/t/a-fully-fledged-texture-painter-for-the-web/15678/16
* Open source project with adaptive UVs: https://tomtung.github.io/chameleon.js/
* Open source project with adaptive and static UV modes, for both painting and sculpting: https://github.com/stephomi/sculptgl (check Dynamic Topology > Activated)
* Save text and record transformations so the image can be saved as
SVG (or HTML?) with invisible selectable transformed text elements?
* Every time you move a selection, duplicate the text and create a clip-path for both parts?
* Make only one of them audible for screen-readers
### Device support
* Prevent text selection in buttons and history entries
* Enlarge menus on touch devices
* Enlarge window titlebar close buttons on touch devices
* Magnifier: on touchscreens, wait until pointerup to zoom
* To detect touchscreen usage, could keep track of whether the last pointermove had any buttons pressed... or use `pointerType`, right?
* Alternative way to access "Color Eraser" feature without a secondary mouse button?
* Alternative access to functionality that would normally require a keyboard (with a numpad!)
* Numpad +/-: Increase/Decrease brush size, Double/Halve selection size, ...
* Shift toggles a handful of things (could have one toggle button renamed contextually?):
* Proportional Resize
* Smear / Trail Selection
* Snap to 8 directions
* An isometric mode would also be good
* Ctrl+Select: "Crop To Selection" menu option
* Don't drag toolbars out into windows with touch, it's too easy to do accidentally
### Tools
* Select and Free-Form Select
* Passive: create no undoables until you do something like move or invert the selection
* You should be able to make a selection, then change the secondary color, then drag the selection cutting it out with the color you selected
* Select and deselect with no actions in between should create no undoables
* Proportionally resize selection while holding Shift
* (or maybe by default? I feel like it should be the default, tbh.)
* Text
* If it would go over the edge of the canvas, reject the input (at least, that's what mspaint does)
* Add padding left to text area when font has glyphs that extend left, like italic 'f' in Times New Roman
* mspaint has access to font metrics
* jspaint could render text to see when it would overflow
* To do it efficiently,
* Take all glyphs in the text
* (And maybe a set of common letters like the alphabet)
* Split with a library to handle Unicode (emojis etc.)
* Uniquify
* Place them *all on top of each other*, positioned absolutely, leaving room to the left of them to detect pixels
* Scan the pixels at the left to find the maximum extent left
* Could store, per font, what glyphs have been tested and what's the maximum extent detected, in order to not have to rerender these
* "What glyphs have been tested" should be specific to font size and attributes, since an italic 'f' may extend more than a normal 'f' for instance
* Store position of FontBox
* Shape Styles
* Shapes: respond to Ctrl (It's complicated)
* Patterns (black and white mode, winter theme)
* Check to make sure patterns are aligned properly for all the tools
* There's supposed to be a mapping between color values and pattern fills, used by the text tool and for the palette when switching between modes (colors should be kept between going to black and white mode and back)
### Desktop App (Electron)
Electron boilerplate stuff:
* Remember window position/state
* Set up autoupdating
* Keep window hidden until loaded (`show: false`, [`ready-to-show`](https://electronjs.org/docs/api/browser-window#event-ready-to-show))
Security:
* Context isolation
* Disable multiplayer?? should be fine
Functionality:
* Subwindows as separate windows
* Document recovery without having to know about File > Manage Storage - pop up contextually with a dialog when you need it
* Show link URLs when you hover over them, in the status bar (because we have a status bar! haha) (there's this API: [event: update-target-url](https://github.com/electron/electron/blob/master/docs/api/web-contents.md#event-update-target-url), which gave me the idea, or it could be implemented with mouse events)
* Recent files (could also be implemented for 98.js.org in the future)
* macOS:
* `win.setSheetOffset` with the menu bar height
* Windows: maybe handle `session-end` event and ask to save?
* Detect if file changes on disk, ask if you want to reload it?
### Also
* Anything marked `@TODO` or `@FIXME` in the source code
* See [Issues on GitHub](https://github.com/1j01/jspaint/issues)
* CSS
* DRY, especially button styles, with [os-gui](https://github.com/1j01/os-gui)
* Clearer `z-index` handling, maybe with CSS variables?
* JS
* Organize things into files better; "functions.js" is like ONE step above saying "code.js"
* `$ToolWindow` has a `$Button` facility; `$DialogWindow` overrides it with essentially a better one; now there's `showMessageBox` too! and `$ToolWindow` is a wrapper for OS-GUI's `$Window`, and should be removed at some point; btw, should `show_error_message` functionality be folded into `showMessageBox`?
* Make code clearer / improve code quality
* https://codeclimate.com/github/1j01/jspaint
* Images
* Use a shared sprite sheet per theme (and optimize it I guess)
================================================
FILE: about.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JS Paint — MS Paint online</title>
<!-- <meta http-equiv="Content-Security-Policy" content="
default-src 'self';
img-src 'self' data: blob: http: https:;
"> -->
<link href="styles/normalize.css" rel="stylesheet" type="text/css">
<!-- `styles/layout.css` includes `overflow: hidden` on the body and html elements, designed for the app,
which completely prevents scrolling, at least in Internet Explorer.
Don't think we want `styles/layout.css`, but OS-GUI's `layout.css` is used for window elements. -->
<!-- <link href="styles/layout.css" class="flippable-layout-stylesheet" rel="stylesheet" type="text/css"> -->
<!-- <link href="styles/print.css" rel="stylesheet" type="text/css" media="print"> -->
<link href="lib/os-gui/build/layout.css" class="flippable-layout-stylesheet" rel="stylesheet" type="text/css">
<link href="lib/98.css/98.custom-build.css" class="flippable-layout-stylesheet not-for-modern" rel="stylesheet"
type="text/css">
<link rel="apple-touch-icon" href="images/icons/apple-icon-180x180.png">
<!-- Chrome will pick the largest image for some reason, instead of the most appropriate one. -->
<!-- <link rel="icon" type="image/png" sizes="192x192" href="images/icons/192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="images/icons/32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="images/icons/96x96.png"> -->
<!-- <link rel="icon" type="image/png" sizes="16x16" href="images/icons/16x16.png"> -->
<link rel="shortcut icon" href="favicon.ico">
<link rel="mask-icon" href="images/icons/safari-pinned-tab.svg" color="red">
<link rel="manifest" href="manifest.webmanifest">
<meta name="msapplication-TileColor" content="#008080">
<meta name="msapplication-TileImage" content="images/icons/ms-icon-144x144.png">
<meta name="theme-color" content="#000080">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Classic MS Paint in the browser, with extra features">
<meta property="og:image:width" content="279">
<meta property="og:image:height" content="279">
<meta property="og:description" content="Classic MS Paint in the browser, with extra features.">
<meta property="og:title" content="JS Paint">
<meta property="og:url" content="https://jspaint.app">
<meta property="og:image" content="https://jspaint.app/images/icons/og-image-279x279.jpg">
<meta name="twitter:title" content="JS Paint">
<meta name="twitter:description" content="Classic MS Paint in the browser, with extra features">
<meta name="twitter:image" content="https://jspaint.app/images/meta/twitter-card-plz-no-crop.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@isaiahodhner">
<meta name="twitter:creator" content="@isaiahodhner">
<link rel="stylesheet" href="styles/themes/classic.css">
<link rel="stylesheet" href="styles/about.css">
</head>
<body>
<section id="main-section">
<h1 style="text-align: center;">
<a href="https://jspaint.app" target="_blank">
<img src="images/icons/jspaint.svg" width="192" height="192" alt="">
<br>
<span id="jspaint-project-name">JS Paint</span>
</a>
</h1>
<p style="text-align: center;">JS Paint is a pixel-perfect remake of Microsoft Paint that runs in the browser.
</p>
<p>
<a href="https://github.com/1j01/jspaint/blob/master/LICENSE.txt" target="_blank"><img
src="images/about/free.gif" width="88" height="39" alt="Free" style="vertical-align: middle"></a>
Open source under the permissive
<a href="https://github.com/1j01/jspaint/blob/master/LICENSE.txt" target="_blank">MIT License</a>.
</p>
<p>
<a href="https://github.com/1j01/jspaint/issues" target="_blank"><img src="images/about/foco.gif" width="40"
height="40" alt="Ideas" style="vertical-align: middle"></a>
Request features and report bugs <a href="https://github.com/1j01/jspaint/issues" target="_blank">on
GitHub</a>
or <a href="mailto:isaiahodhner@gmail.com?subject=JS%20Paint" target="_blank">by email</a>.
</p>
<b>THIS SITE IS...</b>
<img src="images/about/conpaint.gif" width="350" height="50" alt="Under Construction"
style="vertical-align: middle; max-width: 100%; height: auto;">
<img src=" images/about/red_paint_bucket_brush_md_clr_24887PURPLE.gif" width="87" height="100"
alt="Paint bucket" style="float: right">
<!-- <iframe src="index.html" title="JS Paint app" id="jspaint-iframe"></iframe> -->
<div class="window os-window focused" id="os-window-jspaint"
style="width: 267px; height: 392px; touch-action: none; position: relative; z-index: 9; display: flex;">
<div class="window-titlebar" style="touch-action: none;"><img src="images/icons/16x16.png" width="16"
height="16" draggable="false" style="width: 16px; height: 16px;" alt="">
<div class="window-title-area"><span class="window-title">untitled - Paint</span></div><button
class="window-minimize-button window-action-minimize window-button"
aria-label="Minimize window"><span class="window-button-icon"></span></button><button
class="window-maximize-button window-action-maximize window-button"
aria-label="Maximize or restore window"><span class="window-button-icon"></span></button><button
class="window-close-button window-action-close window-button" aria-label="Close window"><span
class="window-button-icon"></span></button>
</div>
<div class="window-content" tabindex="-1" style="outline: none; display: flex; flex-direction: column;">
<!-- <iframe id="jspaint-iframe" src="index.html" -->
<iframe id="jspaint-iframe" src="/"
style="min-width: 0px; min-height: 0px; flex: 1 1 1px; border: 0px;"></iframe>
</div>
<!-- <div class="handle"
style="position: absolute; top: -2px; right: -2px; width: 4px; height: 4px; touch-action: none; cursor: ne-resize;">
</div>
<div class="handle"
style="position: absolute; top: -2px; left: calc(2px); width: calc(100% - 8px + 4px); height: 4px; touch-action: none; cursor: n-resize;">
</div>
<div class="handle"
style="position: absolute; top: -2px; left: -2px; width: 4px; height: 4px; touch-action: none; cursor: nw-resize;">
</div>
<div class="handle"
style="position: absolute; top: calc(2px); left: -2px; width: 4px; height: calc(100% - 8px + 4px); touch-action: none; cursor: w-resize;">
</div>
<div class="handle"
style="position: absolute; bottom: -2px; left: -2px; width: 4px; height: 4px; touch-action: none; cursor: sw-resize;">
</div>
<div class="handle"
style="position: absolute; bottom: -2px; left: calc(2px); width: calc(100% - 8px + 4px); height: 4px; touch-action: none; cursor: s-resize;">
</div>
<div class="handle"
style="position: absolute; bottom: -2px; right: -2px; width: 4px; height: 4px; touch-action: none; cursor: se-resize;">
</div>
<div class="handle"
style="position: absolute; top: calc(2px); right: -2px; width: 4px; height: calc(100% - 8px + 4px); touch-action: none; cursor: e-resize;">
</div> -->
</div>
<div id="try-me"
style="position: absolute; margin-left: min(300px, 100vw - 80px); margin-top: -200px; z-index: 10; color: purple; font-weight: bold;">
<img src="images/about/izquierda.gif" width="49" height="23" alt="hand pointing left"
style="vertical-align: middle">
Try me!
<!-- <span style="color: red">T</span><span style="color: orange">r</span><span style="color: yellow">y</span> <span
style="color: green">m</span><span style="color: blue">e</span><span style="color: purple">!</span> -->
</div>
<p>
<a href="https://github.com/1j01/jspaint#readme" target="_blank"><img src="images/about/moreinfo_paint.gif"
width="100" height="60" alt="More info" style="vertical-align: middle"></a>
Read about the project and extra features on <a href="https://github.com/1j01/jspaint#readme"
target="_blank">the readme</a>.
</p>
<p>
<a href="https://www.paypal.me/IsaiahOdhner" target="_blank"><img src="images/about/money4.gif" width="32"
height="32" alt="$" style="vertical-align: middle"></a>
Support the project at <a href="https://www.paypal.me/IsaiahOdhner"
target="_blank">paypal.me/IsaiahOdhner</a>.
</p>
</section>
<section id="windows-98-section">
<h2>Windows 98 online</h2>
<p>
<a href="https://98.js.org" target="_blank">
<img src="images/about/windows-button.gif" width="40" height="40" alt="Windows logo button">
<img src="images/about/flagani.gif" style="float: right" width="138" height="251"
alt="Windows 98 flag pole animation">
</a>
JS Paint is also included in a <b>web-based version of Windows 98</b>,
along with Notepad, Minesweeper, Sound Recorder, Calculator, and Winamp.
</p>
<br>
<!--
Fancy multi-layered image link with a wooden window frame that zooms in on hover.
-->
<div id="enter-98-wrapper">
<a href="https://98.js.org" target="_blank" id="enter-98-link">
<img src="images/about/98.js.org.png" width="360" height="287"
alt="Windows 98 desktop recreation with Minesweeper, Paint, and other programs"
style="position: absolute; left: 0; top: 0">
<img src="images/about/gatinha.gif" width="126" height="141"
alt="White cat putting paws up and looking around" style="position: absolute; bottom: 0">
<img src="images/about/WindowCLR_WRK.gif" width="360" height="287" alt="windows swung open outwards"
id="wooden-window-frame" style="position: absolute; left: 0; top: 0">
<img src="images/about/ENTERsolar.gif" width="128" height="45" alt="ENTER / 由此進入"
style="position: absolute; left: 50%; top: 80%; transform: translate(-50%, -50%); mix-blend-mode: lighten">
</a>
</div>
<br>
<br>
</section>
<section id="desktop-app-section">
<img src="images/about/cordborder.gif" width="620" height="23" alt=""
style="margin: 0 auto; display: block; width: 100%; height: 23px; position: relative; top: -20px">
<h2 class="bg">Desktop Version <img src="images/about/news.gif" alt="(New!)"></h2>
<img src="images/about/atomo010.gif" width="50" height="50" alt="built with Electron"
style="position: absolute; right: 5%">
<div style="position: absolute; left: 2%">
<img src="images/about/atomo010.gif" width="50" height="50" alt="" style="position: relative; top: 50px">
</div>
<div style="position: absolute; right: 10%">
<img src="images/about/atomo010.gif" width="50" height="50" alt=""
style="position: relative; top: min(390px, 60vw)">
</div>
<img src="images/meta/electron-app-screenshot-mac.png" width="592" height="548"
alt="screenshot of JS Paint Electron app running on macOS"
style="max-width: 100%; height: auto; margin: 0 auto; display: block">
<p class="bg">
For a more native experience, you can install the JS Paint desktop app.
It works on Windows, macOS, and Linux.
</p>
<div class="bg">
<p>
<strong>Features:</strong>
</p>
<ul>
<li>Runs offline</li>
<li>Clipboard support</li>
<li>Open and save files like a native app</li>
<!-- <li>Save directly to the open file instead of downloading a copy</li>
<li>File associations (on macOS and Linux)</li>
<li>Drag and drop to open files (drop onto desktop icon, dock icon, or window)</li> -->
<!-- <li>Command line interface: <code>jspaint "My Picture.bmp"</code></li> -->
<!-- <li>macOS titlebar integration
(<img src="images/about/electron-app-titlebar-icon-mac.png" width="16" height="16"
alt="image document">
icon next to file name shows saved state and
can be dragged into other apps to insert or open the image)</li> -->
<li>Set wallpaper from File menu</li>
</ul>
</div>
<br>
<h3>
<img src="images/about/mn_download.gif" width="168" height="28" alt="Download">
<!-- <img src="images/about/links.gif" width="100" height="60" alt="Links"> -->
<img src="images/about/here.gif" width="101" height="45" alt="Here" style="position: relative; top: 7px">
<img src="images/about/grey-tabby.gif" width="51" height="116" alt="Grey tabby cat"
style="position: relative; top: 27px">
</h3>
<div id="compound-download-button">
<div id="compound-download-button-main-links" style="width: fit-content">
<!-- Using class instead of id because element is cloned on Linux. -->
<a href="https://github.com/1j01/jspaint/releases/" target="_blank" class="main-download-link">
<img src="images/about/download5.gif" width="100" height="40" alt="Download">
</a>
</div>
<!-- <a href="https://github.com/1j01/jspaint/issues/2" target="_blank">
<img src="images/about/conpaint.gif" width="350" height="50" alt="Under Construction" style="max-width: 100%; height: auto;">
</a> -->
<details id="more-download-options-expandable">
<summary id="more-download-options-toggle" title="More download options"></summary>
<div id="more-download-options-dropdown">
<ul>
<li>
<a id="download-link-windows"
href="https://github.com/1j01/jspaint/releases/download/v1.0.0-beta.1/jspaint-1.0.0-Windows-x64-Setup.exe"><span
class="os-icon"><img src="images/about/windowslogo.gif" width="34" height="30"
alt="Windows logo"></span>Download for Windows (x64)
</a>
</li>
<li>
<a id="download-link-mac"
href="https://github.com/1j01/jspaint/releases/download/v1.0.0-beta.1/jspaint-1.0.0-Mac-x64.zip"><span
class="os-icon"><img src="images/about/maclogo.gif" width="34" height="29"
alt="Macintosh logo"></span>Download for Mac (x64)
</a>
</li>
<li>
<a id="download-link-linux-deb"
href="https://github.com/1j01/jspaint/releases/download/v1.0.0-beta.1/jspaint-1.0.0-Linux-x64.deb"><span
class="os-icon"><img src="images/about/linuxlogo.gif" width="30" height="35"
alt="Linux mascot Tux the penguin"></span>Download <span class="big">.deb</span>
(x64)
for Ubuntu, Debian, Mint, Kali, etc.
</a>
</li>
<li>
<a id="download-link-linux-rpm"
href="https://github.com/1j01/jspaint/releases/download/v1.0.0-beta.1/jspaint-1.0.0-Linux-x64.rpm"><span
class="os-icon"><img src="images/about/linuxlogo.gif" width="30" height="35"
alt="Linux mascot Tux the penguin"></span>Download <span class="big">.rpm</span>
(x64)
for Fedora, RHEL, CentOS, OpenSUSE, etc.
</a>
</li>
<li>
<!-- icon options: ✱, 📚, 🕓, 🔍, ↩️, github logo -->
<a id="download-link-view-all-releases"
href="https://github.com/1j01/jspaint/releases/"><span class="os-icon">🕓</span>View all
releases
</a>
</li>
</ul>
</div>
</details>
</div>
<script>
const downloadLinkWindows = document.querySelector("#download-link-windows");
const downloadLinkMac = document.querySelector("#download-link-mac");
const downloadLinkLinuxDeb = document.querySelector("#download-link-linux-deb");
const downloadLinkLinuxRpm = document.querySelector("#download-link-linux-rpm");
const downloadLinkViewAllReleases = document.querySelector("#download-link-view-all-releases");
const mainDownloadLink = document.querySelector(".main-download-link");
/**
* @returns {"Windows" | "Mac" | "Linux" | "Android" | "iOS" | "Unknown"}
*/
function detectOS() {
const userAgent = window.navigator.userAgent,
platform = window.navigator?.userAgentData?.platform ?? window.navigator.platform;
if (/^Mac|Darwin/i.test(platform)) {
return "Mac";
} else if (/iPhone|iPod|iPad/i.test(platform)) {
return "iOS";
} else if (/^Win/i.test(platform)) {
return "Windows";
} else if (/Android/i.test(userAgent)) {
return "Android";
} else if (/Linux/i.test(platform)) {
return "Linux";
}
return "Unknown";
}
function updateDownloadLink() {
const os = detectOS();
const specificLink = {
"Windows": downloadLinkWindows,
"Mac": downloadLinkMac,
"iOS": downloadLinkMac,
"Linux": [downloadLinkLinuxDeb, downloadLinkLinuxRpm],
}[os] ?? downloadLinkViewAllReleases;
const downloadImageHTML = mainDownloadLink.innerHTML + "<br>";
if (specificLink instanceof Array) {
const mainDownloadLink2 = mainDownloadLink.cloneNode(true);
mainDownloadLink.parentNode.insertBefore(mainDownloadLink2, mainDownloadLink.nextSibling);
mainDownloadLink.href = specificLink[0].href;
mainDownloadLink.innerHTML = specificLink[0].innerHTML.replace("Download", downloadImageHTML);
mainDownloadLink2.href = specificLink[1].href;
mainDownloadLink2.innerHTML = specificLink[1].innerHTML.replace("Download", downloadImageHTML);
mainDownloadLink.querySelector(".big").style.fontSize = "1.5em";
mainDownloadLink2.querySelector(".big").style.fontSize = "1.5em";
} else if (specificLink) {
mainDownloadLink.href = specificLink.href;
mainDownloadLink.innerHTML = specificLink.innerHTML.replace("Download", downloadImageHTML);
}
}
updateDownloadLink();
// Close the dropdown when clicking outside of it
document.addEventListener("click", function (event) {
const details = document.querySelector("#more-download-options-expandable");
if (!details.contains(event.target)) {
details.removeAttribute("open");
}
});
</script>
<div style="position: absolute; right: 3%">
<img src="images/about/atomo010.gif" width="50" height="50" alt="" style="position: relative; bottom: 50px">
</div>
<img src="images/about/cordborder.gif" width="620" height="23" alt=""
style="margin: 0 auto; display: block; width: 100%; height: 23px; position: relative; top: 20px">
</section>
<section id="pwa-section">
<h2>Progressive Web App</h2>
<img src="images/meta/mobipaint.png" width="308" height="193" alt="JS Paint on a phone" style="float: right;">
<p>
Alternatively, you can install JS Paint as a PWA (Progressive Web App),
but this does not <b>yet</b> support offline use
(as it doesn't include a Service Worker).
It's more like a bookmark (for now), except it runs in a special window.
</p>
<p>
The user interface for installing PWAs differs by browser and operating system.
</p>
<p>
<q>On most desktop browsers, the install prompt is in the URL bar.
On mobile, the install prompt is generally found in the menu of browser options.</q>
See <a
href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Installing#installing_pwas"
target="_blank">
Installing PWAs</a> for visual guidance.
</p>
<button id="install-pwa" hidden style="padding: 10px 30px; margin-bottom: 1em;">
<img src="images/about/monitor.png" width="16" height="16" alt="" style="vertical-align: middle;">
Install JS Paint
</button>
<!-- prevent floated image mobipaint.png overlapping next section -->
<div style="clear: both;"></div>
</section>
<section id="textual-paint-section">
<!--
@TODO: test screen reader accessibility
Notes about this heading:
- FIGlet font used: "small"
- Separate elements for each word allows word wrapping on narrow screens
- Not using `<pre>` element because it's not allowed in a heading, and visa versa.
- VS Code knows not to format `<pre>` elements but not arbitrary elements with `white-space: pre;`,
so I had to define "html.format.unformattedContentDelimiter" in .vscode/settings.json
-->
<!--no_format-->
<h2 style="font-size: 1em">
<abbr title="Textual Paint" style="text-decoration: none">
<span style="display: inline-block; white-space: pre; margin: 0;">
_____ _ _
|_ _|____ _| |_ _ _ __ _| |
| |/ -_) \ / _| || / _` | |
|_|\___/_\_\\__|\_,_\__,_|_|</span><span style="display: inline-block; white-space: pre; margin: 0;">
___ _ _
| _ \__ _(_)_ _| |_
| _/ _` | | ' \ _|
|_| \__,_|_|_||_\__|</span>
</abbr>
</h2>
<!--no_format-->
<br>
<p>
I also made a <em>separate</em> elaborate MS Paint clone that runs in the terminal,
and edits ANSI art in addition to bitmaps.
</p>
<p>
You can install it with:
<code>pip install textual-paint</code>
</p>
<p>
And then run with simply:
<code>textual-paint</code>
</p>
<p>
Requires Python 3.10 or later, and a terminal emulator with Unicode and true color support.
</p>
<ul>
<li>
<span class="os-icon"><img src="images/about/windowslogo.gif" width="34" height="30"
alt="Windows logo"></span>
Runs well in <i>Windows Terminal</i>, but not in the older <i>Windows Console</i>.
</li>
<li>
<span class="os-icon"><img src="images/about/maclogo.gif" width="34" height="29"
alt="Macintosh logo"></span>
Runs well in <i>iTerm2</i>, but not the built in macOS <i>Terminal.app</i>.
</li>
<li>
<span class="os-icon"><img src="images/about/linuxlogo.gif" width="30" height="35"
alt="Linux mascot Tux the penguin"></span>
Runs well in <i>GNOME Terminal</i>, and most Linux terminal emulators, but not the <i>Linux console</i>.
</li>
</ul>
<!-- <img src="images/about/dos-samp.gif" width="391" height="136" alt="MS DOS prompt"> -->
<!-- TODO: PNG screenshot of GNOME terminal, which has the best rendering (SVG uses browser's rendering and displays artifacts); and include it in the repo -->
<img src="https://raw.githubusercontent.com/1j01/textual-paint/v0.1.0/screenshot.svg" width="1238" height="1026"
alt="screenshot of Textual Paint showing the About Paint dialog" style="max-width: 100%; height: auto;">
<img src="images/about/Computer-04-june.gif" width="134" height="133" alt="Computer typing on its own keyboard"
style="float: left">
<p>
<a href="https://github.com/1j01/textual-paint" target="_blank">Textual Paint</a>
was built using the <a href="https://textual.textualize.io/" target="_blank">Textual</a>
framework, which was very fun to work with!
</p>
<p>
I may have more Paint projects planned, the mad man that I am. 🎨
</p>
<p>
<i style="color: gray">What's more retro than a terminal-based Paint program, I wonder?</i>
</p>
</section>
<section id="other-projects-section">
<!-- `clear: both` just in case the floated GIF intrudes too much, for instance if font sizes or margins were changed or paragraphs moved or removed. -->
<h2 style="clear: both">Other Projects</h2>
<p style="float: right;">
<a href="https://isaiahodhner.io/" target="_blank">
<img src="images/about/home.gif" width="40" height="40" alt="Home button"
style="vertical-align: middle">
Check out my home page for more projects!
</a>
</p>
<p>
<a href="https://isaiahodhner.io/" target="_blank"
style="color: rgb(160, 42, 52); font-weight: bold; font-style: italic;">
<img src="images/about/artcreated.gif" width="165" height="136" alt="Created by">
<br>
<span style="display: block; text-align: center; width: 165px;">
Isaiah Odhner
</span>
</a>
</p>
<div id="junkbot-area">
<a href="https://1j01.github.io/janitorial-android/#junkbot" target="_blank">
<img src="images/about/junkbot-collecting-bin.gif" width="105" height="126"
alt="LEGO Junkbot minifig eating a recycling bin" id="junkbot-img"></a>
<span id="feeding-text" hidden>Please don't feed Junkbot.</span>
</div>
<a href="https://1j01.github.io/guitar/" target="_blank">
<img src=" images/about/guitar.gif" width="60" height="100" alt="Guitar" style="float: right;">
</a>
<a href="https://1j01.github.io/true-random-movie/" target="_blank">
<img src="images/about/filmreel.gif" width="116" height="50" alt="film reel" style="float: right;">
</a>
<a href="https://1j01.github.io/dat-boi/" target="_blank">
<img src="images/about/dat-boi-transparent-small.gif" width="96" height="120" alt="Dat Boi"
style="float: right;">
</a>
<a href="https://1j01.github.io/chess-mashup/" target="_blank">
<img src="images/about/CHESS_CUBE.gif" width="100" height="90" alt="Dat Boi" style="float: right;">
</a>
<!-- extends background when floated elements wrap -->
<div style="clear: both;"></div>
</section>
<section id="buttons-section">
<h3>Here are some buttons I made</h3>
<p>
Feel free to copy these to your site!
Some of them are rubbish, but a few of them I'm quite happy with.
</p>
<p>
Right click on the image and select "Save image as..." to download it,
then copy and paste the HTML code below it into your site,
and update the <code>src</code> attribute to point to where you're hosting the image.
</p>
<a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31.png" width="88" height="31" alt="JS Paint">
</a>
<a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-history.gif" width="88" height="31" alt="JS Paint">
</a>
<!-- <a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-basic-88x31-v1.png" width="88" height="31" alt="JS Paint">
</a> -->
<!-- <a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-v1.png" width="88" height="31" alt="JS Paint">
</a> -->
<a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-bubbly.png" width="88" height="31" alt="JS Paint">
</a>
<!-- <a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-bubbly-inverse.png" width="88" height="31"
alt="JS Paint">
</a> -->
<!-- <a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-custom-font.png" width="88" height="31" alt="JS Paint">
</a> -->
<!-- <a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-gray-border.png" width="88" height="31" alt="JS Paint">
</a> -->
<a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-v2-history.gif" width="88" height="31" alt="JS Paint">
</a>
<a href="https://jspaint.app">
<img src="images/88x31/custom/jspaint-button-88x31-v2.png" width="88" height="31" alt="JS Paint">
</a>
<!-- <img src="images/88x31/custom/made-with-jspaint-88x31-v1.png" width="88" height="31" alt="Made with JS Paint"> -->
<a href="https://jspaint.app/about">
<img src="images/88x31/custom/made-with-jspaint-88x31-v2.png" width="88" height="31"
alt="Made with JS Paint">
</a>
<!-- <a href="https://jspaint.app/about">
<img src="images/88x31/custom/made-with-jspaint-88x31-v3.png" width="88" height="31"
alt="Made with JS Paint">
</a> -->
<!-- <img src="images/88x31/custom/made-with-jspaint-88x31-v4.png" width="88" height="31" alt="Made with JS Paint"> -->
<!-- <img src="images/88x31/custom/made-with-jspaint-88x31-v5-history.gif" width="88" height="31" alt="Made with JS Paint"> -->
<a href="https://jspaint.app/about">
<img src="images/88x31/custom/made-with-jspaint-88x31-v5.png" width="88" height="31"
alt="Made with JS Paint">
</a>
<a href="https://98.js.org">
<img src="images/88x31/custom/98.js.org-88x31.png" width="88" height="31" alt="98.JS">
</a>
<!-- <img src="images/88x31/custom/take-this-88x31-v1.png" width="88" height="31" alt="It's dangerous to go alone. Take this, Now!"> -->
<!-- <img src="images/88x31/custom/take-this-88x31-v2.png" width="88" height="31" alt="It's dangerous to go alone. Take this, Now!"> -->
<!-- <img src="images/88x31/custom/take-this-88x31-v2-frame-2.png" width="88" height="31" alt="It's dangerous to go alone. Take this, Now!"> -->
<!-- <img src="images/88x31/custom/take-this-88x31-v2-history.gif" width="88" height="31" alt="It's dangerous to go alone. Take this, Now!"> -->
<img src="images/88x31/custom/take-this-88x31-v2.gif" width="88" height="31"
alt="It's dangerous to go alone. Take this, Now! (Legend of Zelda parody)">
<!-- <img src="images/88x31/custom/turbo-encabulator-88x31-v0.psd" width="88" height="31" alt="It's dangerous to go alone. Take this, Now!"> -->
<a href="https://youtu.be/lVZ8Ko-nss4">
<img src=" images/88x31/custom/turbo-encabulator-88x31-v1.png" width="88" height="31"
alt="Powered by turbo encabulator">
</a>
<!-- <img src="images/88x31/custom/vs-code-88x31-v0.1.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v0.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v1.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v1-history.gif" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v2-stupid-garbage.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v3-no-border.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v4-overlapping-border.png" width="88" height="31" alt="Built with VS Code"> -->
<!-- <img src="images/88x31/custom/vs-code-88x31-v5-history.gif" width="88" height="31" alt="Built with VS Code"> -->
<a href="https://code.visualstudio.com/">
<img src="images/88x31/custom/vs-code-88x31-v5-within-border.png" width="88" height="31"
alt="Built with VS Code">
</a>
<!-- <img src="images/88x31/custom/vs-code-88x31-v6-shadow.png" width="88" height="31" alt="Built with VS Code"> -->
<a href="https://code.visualstudio.com/">
<img src="images/88x31/custom/vs-code-88x31-v7-animated.gif" width="88" height="31"
alt="Built with VS Code">
</a>
<!-- <img src="images/88x31/custom/windows-7.png" width="88" height="31" alt="Windows 7 was Microsoft's last decent operating system"> -->
<!-- <img src="images/88x31/custom/windows-7-template-88x31.png" width="88" height="31" alt="Windows 7"> -->
<img src="images/88x31/custom/windows-7-vs-11.png" width="88" height="31"
alt="Windows 7 is still better than Windows 11">
<!-- <img src="images/88x31/custom/creative-constraints-88x31.png" width="88" height="31" alt="Creative constraints"> -->
<!-- <img src="images/88x31/custom/creative-constraints-88x31-v2.png" width="88" height="31"
alt="Creative constraints"> -->
<!-- <img src="images/88x31/custom/creative-constraints-88x31-v3.png" width="88" height="31"
alt="Creative constraints"> -->
<!-- <img src="images/88x31/custom/creative-constraints-88x31-v4.png" width="88" height="31"
alt="Creative constraints"> -->
<!-- <img src="images/88x31/custom/creative-constraints-88x31-v5.png" width="88" height="31"
alt="Creative constraints"> -->
<!-- <img src="images/88x31/custom/creative-constraints-88x31-v6.png" width="88" height="31"
alt="Creative constraints"> -->
<a href="https://jspaint.app/about">
<img src="images/88x31/custom/creative-constraints-88x31-v7-history.gif" width="88" height="31"
alt="Creative constraints (doodle progress animation)">
</a>
<a href="https://jspaint.app/about">
<img src="images/88x31/custom/creative-constraints-88x31-v7.png" width="88" height="31"
alt="Creative constraints">
</a>
<!-- <img src="images/88x31/custom/electron-sucks-88x31-v0.png" width="88" height="31" alt="I hate Electron!"> -->
<img src="images/88x31/custom/electron-sucks-88x31-v1.png" width="88" height="31" alt="I hate Electron!">
<!-- <img src="images/88x31/custom/how-now-brown-cow-88x31-v1.png" width="88" height="31" alt="How Now! (brown cow)"> -->
<img src="images/88x31/custom/how-now-brown-cow-88x31-v2.png" width="88" height="31" alt="How Now! (brown cow)">
<!-- <img src="images/88x31/custom/junkbot-play-88x31-frame-1.png" width="88" height="31" alt="Play LEGO Junkbot">
<img src="images/88x31/custom/junkbot-play-88x31-frame-2.png" width="88" height="31" alt="Play LEGO Junkbot">
<img src="images/88x31/custom/junkbot-play-88x31-frame-3.png" width="88" height="31" alt="Play LEGO Junkbot">
<img src="images/88x31/custom/junkbot-play-88x31-frame-4.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<!-- <img src="images/88x31/custom/junkbot-88x31-v0.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v1.png" width="88" height="31" alt="Play LEGO Junkbot">
</a>
<!-- <img src="images/88x31/custom/junkbot-88x31-v2.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<!-- <img src="images/88x31/custom/junkbot-88x31-v3.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<!-- <a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v4.png" width="88" height="31" alt="Play LEGO Junkbot">
</a> -->
<a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v5.png" width="88" height="31" alt="Play LEGO Junkbot">
</a>
<!-- <img src="images/88x31/custom/junkbot-88x31-v6.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v7.png" width="88" height="31" alt="Play LEGO Junkbot">
</a>
<!-- <img src="images/88x31/custom/junkbot-88x31-v8.png" width="88" height="31" alt="Play LEGO Junkbot"> -->
<!-- <a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v9-history.gif" width="88" height="31"
alt="LEGO Junkbot button graphic progress animation">
</a> -->
<a href="https://github.com/1j01/janitorial-android/?tab=readme-ov-file#readme">
<img src="images/88x31/custom/junkbot-88x31-v9.png" width="88" height="31" alt="Play LEGO Junkbot">
</a>
<!-- <img src="images/88x31/custom/pipe-strip-88x31-v0.psd" width="88" height="31" alt="The Pipe Strip">
<img src="images/88x31/custom/pipe-strip-88x31-v1.png" width="88" height="31" alt="The Pipe Strip">
<img src="images/88x31/custom/pipe-strip-88x31-v1.psd" width="88" height="31" alt="The Pipe Strip">
<img src="images/88x31/custom/pipe-strip-88x31-v2.png" width="88" height="31" alt="The Pipe Strip">
<img src="images/88x31/custom/pipe-strip-88x31-v2.psd" width="88" height="31" alt="The Pipe Strip"> -->
<!-- <img src="images/88x31/custom/pipe-strip-88x31-v3.png" width="88" height="31" alt="The Pipe Strip"> -->
<!-- <img src="images/88x31/custom/pipe-strip-88x31-v3.psd" width="88" height="31" alt="The Pipe Strip"> -->
<a href="https://pypi.org/project/pipe-strip/">
<img src="images/88x31/custom/pipe-strip-88x31-v4.png" width="88" height="31"
alt="Panel 1. Jon is sitting on the sofa reading the newspaper, and he searches the table beside him with his hand. Panel 2. Jon, no longer relaxing with his leg kicked up turns to face the viewer, and thinks to himself, "Now where could my pipe be?" Panel 3. Garfield, Jon's orange tabby cat, is smoking Jon's pipe. Jon is shocked and shouts from off-screen "Garfield!!"">
</a>
<!-- <img src="images/88x31/custom/pipe-strip-88x31-v4.psd" width="88" height="31" alt="The Pipe Strip"> -->
<a href="https://www.youtube.com/watch?v=k1BneeJTDcU">
<img src="images/88x31/custom/a-little-bit-of-everything.gif" width="88" height="31"
alt="A little bit of everything, Now!">
</a>
<a href="https://ublockorigin.com/">
<img src="images/88x31/custom/ublock-origin-88x31-v2.png" width="88" height="31"
alt="Get uBlock Origin now!">
</a>
<a href="https://ublockorigin.com/">
<img src="images/88x31/custom/ublock-origin-88x31.gif" width="88" height="31" alt="Get uBlock Origin now!">
</a>
<h3>Here are some buttons I collected</h3>
<p>
I don't know where most of these came from, and I've repurposed some of them.
</p>
<img src="images/88x31/collected/mspaint.gif" width="88" height="31" alt="Long live MS Paint!">
<img src="images/88x31/collected/mousemade.gif" width="88" height="31" alt="Made with Mouse">
<a href="https://98.js.org/">
<img src="images/88x31/collected/mswin98_89.gif" width="88" height="31"
alt="Made with Microsoft Windows 98. Get!">
</a>
<a
href="https://www.eff.org/deeplinks/2021/03/google-testing-its-controversial-new-ad-targeting-tech-millions-browsers-heres"><img
src="images/88x31/collected/abc.gif" title="Please use any browser but Chrome">
</a>
<a href="https://rainy.gay/other/buttons">
<img src="images/88x31/collected/antinft.gif" width="88" height="31" alt="This is an anti-NFT site.">
</a>
<img src="images/88x31/collected/nofuckingthanks.gif" width="88" height="31" alt="NFT - No Fucking Thanks">
<a href="https://www.getpaint.net/">
<img src="images/88x31/collected/paintnet.gif" width="88" height="31" alt="Get Paint.NET">
</a>
<img src="images/88x31/collected/goodieblink.png" width="88" height="31" alt="graphic design is my passion">
<img src="images/88x31/collected/google_stand.gif" width="88" height="31"
alt="Fight for open web standards. Fight for online privacy. Fight against monopolistic practices. Stand up to Google!">
<img src="images/88x31/collected/imissxp.gif" width="88" height="31" alt="I miss Windows XP">
<a href="https://archive.org/">
<img src="images/88x31/collected/internetarchive.gif" width="88" height="31" alt="Internet Archive">
</a>
<img src="images/88x31/collected/is_it_slow_say_so.gif" width="88" height="31" alt="Is it slow? Say so!">
<img src="images/88x31/collected/new-tab.gif" width="88" height="31"
alt="Please do not force this img to be lonely">
<img src="images/88x31/collected/nneighborhoodsmall.gif" width="88" height="31" alt="Network neighborhood">
<a href="https://code.visualstudio.com/">
<img src="images/88x31/collected/vscbutton.gif" width="88" height="31" alt="Visual Studio Code">
</a>
<a href="https://youtu.be/JcJSW7Rprio">
<img src="images/88x31/collected/webdisk.gif" width="88" height="31" alt="WebDisk, Now">
</a>
<a href="https://jspaint.app">
<img src="images/88x31/collected/yay_its_a_button.gif" width="88" height="31" alt="I use MS Paint">
</a>
<a href="https://98.js.org">
<img src="images/88x31/collected/98plusani.gif" width="88" height="31" alt="98 Plus!">
</a>
<a href="https://flashpointarchive.org/">
<img src="images/88x31/collected/adobe_getflashp.gif" width="88" height="31"
alt="Get Flashpoint web game archive">
</a>
<img src="images/88x31/collected/anibanner.gif" width="88" height="31" alt="Up all night">
<img src="images/88x31/collected/bookmark_this_page.gif" width="88" height="31" alt="Bookmark this page">
<img src="images/88x31/collected/cssdif.gif" width="88" height="31" alt="CSS is difficult">
<img src="images/88x31/collected/dark-mode.gif" width="88" height="31" alt="Made for dark mode">
<a href="https://duckduckgo.com/">
<img src="images/88x31/collected/ddg.gif" width="88" height="31" alt="DuckDuckGo">
</a>
<a href="https://neocities.org/">
<img src="images/88x31/collected/delete-twitter.gif" width="88" height="31"
alt="Delete Twitter. Make a Neocities.">
</a>
<img src="images/88x31/collected/desp-anim.gif" width="88" height="31" alt="Despacito, Now!">
<img src="images/88x31/collected/diff-now.gif" width="88" height="31"
alt="Something completely different, Now!">
<a href="https://webamp.org/">
<img src="images/88x31/collected/winamp.gif" width="88" height="31" alt="Winamp">
</a>
<a onclick="{
const bubbles = document.createElement('img');
bubbles.src = 'images/about/bubbles.webp';
bubbles.width = 732;
bubbles.height = 544;
bubbles.style.pointerEvents = 'none';
bubbles.style.position = 'fixed';
bubbles.style.left = event.clientX - bubbles.width / 2 + 'px';
bubbles.style.top = event.clientY - bubbles.height + 'px';
document.body.appendChild(bubbles);
setTimeout(() => bubbles.remove(), 5000);
bubbles.addEventListener('transitionend', () => bubbles.remove());
bubbles.style.transition = 'transform 5s, opacity 5s';
setTimeout(() => {
bubbles.style.transform = 'translate(-50%, -50%) scale(2)';
bubbles.style.opacity = 0;
});
}" style="cursor: pointer;">
<img src="images/88x31/collected/digby88.gif" width="88" height="31" alt="bubbles">
</a>
<a onclick="{
if (window.eSheep) {
addSheep();
} else {
const scriptURL = 'https://adrianotiger.github.io/web-esheep/dist/esheep.min.js';
const script = document.createElement('script');
script.src = scriptURL;
script.onload = addSheep;
script.onerror = () => {
alert('Failed to load eSheep!');
};
document.head.appendChild(script);
// Make eSheep land on more surfaces
// It only lands on div and hr elements:
// https://github.com/Adrianotiger/web-esheep/blob/641210d262e484cab5441c6b5c8fe2c9c28bed58/src/esheep.js#L65
// which have a top border:
// https://github.com/Adrianotiger/web-esheep/blob/641210d262e484cab5441c6b5c8fe2c9c28bed58/src/esheep.js#L601
// and isn't configurable, as of writing.
for (const section of document.querySelectorAll('section, footer')) {
const hr = document.createElement('hr');
hr.style.border = '0';
hr.style.borderTop = '1px solid transparent';
hr.style.margin = '0';
hr.style.marginTop = '-1px';
section.parentNode.insertBefore(hr, section);
hr.classList.add('eSheep-landing-surface');
}
}
function addSheep() {
const sheep = new eSheep();
sheep.Start();
// Not part of public API, and doesn't work, possibly because it's not loaded yet.
//sheep._setPosition?.(event.clientX, event.clientY);
// Give some visual feedback that the sheep is being added.
event.target.style.transform = 'scale(1.5)';
setTimeout(() => event.target.style.transform = '', 100);
}
}" style="cursor: pointer;">
<img src="images/88x31/collected/esheep.gif" width="88" height="31" alt="eSheep, Now!">
</a>
<a href="https://ezgif.com/">
<img src="images/88x31/collected/ezgif_now.gif" width="88" height="31" alt="EZGIF.COM, Now!">
</a>
<a href="https://imgur.com/gallery/KXr07TX">
<img src="images/88x31/collected/folder2.gif" width="88" height="31" alt="A folder with several tabs">
</a>
<a href="https://isaiahodhner.io/games">
<img src="images/88x31/collected/games.gif" width="88" height="31" alt="Games">
</a>
<a href="https://pages.github.com/">
<img src="images/88x31/collected/gh-pages-bo.gif" width="88" height="31"
alt="Powered by Microsoft GitHub Pages">
</a>
<a href="https://github.com/1j01">
<img src="images/88x31/collected/github-check.gif" width="88" height="31" alt="Check out my GitHub!">
</a>
</section>
<script>
// Ideally this would be baked into the HTML, but this is nice and automatic.
for (const button of document.querySelectorAll("#buttons-section img")) {
const subject = button.closest("a") ?? button;
const wrapper = document.createElement("div");
wrapper.style.display = "inline-block";
wrapper.style.margin = "0 10px 10px 0";
const textarea = document.createElement("textarea");
const html = subject.outerHTML;
// Normalize indentation for the snippet.
// The last indentation in the HTML will be for the closing tag, if applicable,
// which should not end up indented, and works for a search string to replace.
// The first indentation, by contrast, will include one more indent level,
// and so isn't suitable as a search string.
const lastIndentation = html.match(/^\s*/gm).pop() ?? "";
textarea.value = html
.replace(new RegExp("^" + lastIndentation, "gm"), "");
textarea.style.width = "88px";
textarea.style.height = "31px";
//textarea.style.resize = "none";
textarea.style.display = "block";
wrapper.appendChild(textarea);
// Order matters here, because `appendChild` moves the element.
subject.parentNode.insertBefore(wrapper, subject);
wrapper.insertBefore(subject, textarea);
}
// Resize textareas back to normal when clicking outside of them.
// This isn't necessarily great for usability (it may be surprising),
// but it's kind of fun and restores the even grid, which is nice for aesthetics.
// It shouldn't hamper usability too much, since you can still expand multiple at once if you wish.
function restoreTextareaSizes() {
for (const textarea of document.querySelectorAll("#buttons-section textarea")) {
if (getComputedStyle(textarea).width !== "88px" || getComputedStyle(textarea).height !== "31px") {
textarea.style.transition = "width 0.5s, height 0.5s";
textarea.style.width = "88px";
textarea.style.height = "31px";
textarea.addEventListener("transitionend", function () {
textarea.style.transition = "";
}, { once: true });
// In case resize handle is grabbed during transition,
// interrupt the resize animation, to prevent a sluggish feeling
// from the transition being constantly restarted.
// (Test this by increasing the transition duration significantly!)
textarea.addEventListener("transitioncancel", function () {
textarea.style.transition = "";
}, { once: true });
}
}
}
document.addEventListener("click", function (event) {
if (!event.target.closest("#buttons-section textarea")) {
restoreTextareaSizes();
}
});
</script>
<script>
var maxButton = document.querySelector(".window-maximize-button");
var closeButton = document.querySelector(".window-close-button");
var minimizeButton = document.querySelector(".window-minimize-button");
var windowElements = document.querySelectorAll(".window, #try-me");
maxButton.addEventListener("click", function () {
var iframe = document.querySelector("#jspaint-iframe");
// `iframe.src` doesn't contain the document ID added by the app page.
// Accessing the iframe's `location.href` allows a more seamless transition,
// although undos are lost.
// TODO: Save undo history as part of the session.
// TODO: Make sure the session is saved before navigating away.
// if (iframe.contentWindow.undos.length) {
// if (!confirm("Maximizing will clear your undo history. Continue?")) {
// return;
// }
// }
location.href = iframe.contentWindow.location.href;
});
function hideDemo() {
for (var i = 0; i < windowElements.length; i++) {
windowElements[i].style.display = "none";
}
}
closeButton.addEventListener("click", hideDemo);
minimizeButton.addEventListener("click", hideDemo);
// Junkbot "feeding" interaction
var junkbotArea = document.querySelector("#junkbot-area");
var junkbotImg = document.querySelector("#junkbot-img");
var cursorHasBin = true;
junkbotArea.style.cursor = "url(images/about/junkbot-bin.png) 16 16, auto";
junkbotImg.src = "images/about/junkbot.gif";
junkbotImg.addEventListener("mouseenter", function (event) {
// console.log("mouseenter, cursorHasBin =", cursorHasBin);
if (!cursorHasBin) {
return;
}
junkbotImg.src = "images/about/junkbot-collecting-bin.gif";
junkbotArea.style.cursor = "";
cursorHasBin = false;
// TODO: make non-looping version of GIF and increase timeout
// or do this differently, because setTimeout isn't reliable!
// It's not firing in Firefox sometimes (while loading the page?)
// and may not fire if the tab is in the background (is switched away from).
// console.log("setting timeout");
setTimeout(function () {
// console.log("timeout");
junkbotImg.src = "images/about/junkbot.gif";
junkbotArea.style.cursor = "url(images/about/junkbot-bin.png) 16 16, auto";
cursorHasBin = true;
}, 1000);
});
document.querySelector("#feeding-text").removeAttribute("hidden");
</script>
<!-- split script to keep above ES5-only -->
<script>
// PWA install button
// https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/How_to/Trigger_install_prompt
const installButton = document.querySelector("#install-pwa");
let installPrompt = null;
window.addEventListener("beforeinstallprompt", (event) => {
event.preventDefault();
installPrompt = event;
installButton.removeAttribute("hidden");
});
installButton.addEventListener("click", async () => {
if (!installPrompt) {
return;
}
const result = await installPrompt.prompt();
console.log(`Install prompt was: ${result.outcome}`);
disableInAppInstallPrompt();
});
function disableInAppInstallPrompt() {
installPrompt = null;
installButton.setAttribute("hidden", "");
}
window.addEventListener("appinstalled", () => {
disableInAppInstallPrompt();
});
</script>
</body>
</html>
================================================
FILE: browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="images/icons/ms-icon-70x70.png"/><square150x150logo src="images/icons/ms-icon-150x150.png"/><square310x310logo src="images/icons/ms-icon-310x310.png"/><TileColor>#008080</TileColor></tile></msapplication></browserconfig>
================================================
FILE: cspell.json
================================================
{
"ignorePaths": [
".history", // VS Code "Local History" extension
"node_modules",
"lib",
"out", // Electron Forge output
"*.png",
"*.gif",
"*.jpg",
"*.jpeg",
"*.svg",
"*.cur",
"*.ico",
"*.icns",
"*.wav",
"*.psd",
"*.mp4",
"localization"
],
"words": [
"abcdefghijklmnopqrstuvwxyzabcdef",
"Adlm",
"airb",
"airbrushbrush",
"Allaire",
"anypalette",
"apng",
"appinstalled",
"argparse",
"atombgwht",
"autoupdating",
"beforeinstallprompt",
"bepis",
"Bgau",
"bigfix",
"blackwhite",
"Bopo",
"Bresenham",
"Bresenham's",
"browserconfig",
"checkmarks",
"clipart",
"Clippy",
"clmtrackr",
"cloudflared",
"clsid",
"cmaps",
"colorbar",
"colorbox",
"colorstr",
"colyseus",
"contenteditable",
"Corel",
"ctype",
"Darude",
"datetime",
"dectree",
"desaturated",
"Despacito",
"discoverability",
"divs",
"djvu",
"documentedly",
"duplicately",
"ellipticals",
"encabulator",
"endonym",
"endregion",
"equivalize",
"ertical",
"espree",
"esque",
"Excelsi",
"eyedrop",
"EZGIF",
"farbling",
"fieldsets",
"firebaseapp",
"firebaseio",
"firstrun",
"flagani",
"fliph",
"flippable",
"flipv",
"floodfill",
"floodfilling",
"fontbox",
"frowny",
"fullscreen",
"ghostwhite",
"Glag",
"gons",
"greyscale",
"gridlines",
"hackily",
"haha",
"Hanb",
"hcanvas",
"hctx",
"hideothers",
"hilight",
"HKEY",
"homescreen",
"hotspot",
"hslrgb",
"hsrgb",
"humbnail",
"Icci",
"ICNS",
"iconify",
"IFDs",
"iframes",
"IIFE",
"Imgur",
"Inkscape",
"IPFS",
"isaiahodhner",
"isded",
"Jasc",
"jfif",
"jnordberg",
"JSGF",
"jspaint",
"jsperf",
"Junkbot",
"keyshortcuts",
"Khoj",
"Kolour",
"Konami",
"Krita",
"labelledby",
"lerp",
"libgconf",
"libtess",
"Linb",
"linebreak",
"liveweb",
"llpaper",
"localdomain",
"localforage",
"lookpath",
"lors",
"Lospec",
"lrgb",
"ltres",
"Luciferi",
"Macromedia",
"mediump",
"menuitemcheckbox",
"menuitemradio",
"mimg",
"minifig",
"mobipaint",
"Mopaint",
"Mousewheel",
"msapplication",
"msgbox",
"MSPaint",
"multilines",
"multitools",
"multitouch",
"multiuser",
"murl",
"Naptha",
"nargs",
"Nbat",
"Neocities",
"nesw",
"nevermind",
"Nkoo",
"nocheck",
"nomine",
"nonblock",
"nonwords",
"nostri",
"numberofcolors",
"numpad",
"occluder",
"octree",
"Odhner",
"oleobject",
"onestep",
"Optikey",
"orizontal",
"OSGUI",
"ovaloid",
"ovaloids",
"oviforms",
"paintbucket",
"pako",
"palettized",
"pearlescent",
"Peggys",
"Phlp",
"Photoshop",
"pipx",
"pixeling",
"PLTE",
"pointermove",
"pointerup",
"proch",
"proclabel",
"pseudorandomly",
"psppalette",
"qtres",
"redoable",
"Rege",
"relh",
"reltopics",
"repurposable",
"resizer",
"retarget",
"retargeted",
"retrofuturist",
"retrofuturistic",
"RGBA",
"RGBAs",
"rightclick",
"rotologo",
"roundrect",
"roundrects",
"rrect",
"RTLCSS",
"sandboxing",
"Satana",
"Satanas",
"Scribus",
"scrollbars",
"Shft",
"Skencil",
"sketchpalette",
"skeuomorphic",
"skypack",
"smslant",
"sorthweast",
"SoundCloud",
"spacebar",
"spirobrush",
"spraycan",
"spraypaint",
"spraypainting",
"spritesheet",
"styl",
"stylable",
"subh",
"subrepo",
"subwindows",
"tesselator",
"tessy",
"textareas",
"textbox",
"textboxes",
"themeable",
"themepack",
"throwie",
"tileable",
"timespan",
"titlebar",
"togglable",
"topich",
"tracedata",
"Tracky",
"Tvcy",
"typecheck",
"typechecked",
"typestyles",
"undecagons",
"undoable",
"undoables",
"undock",
"undocked",
"undos",
"unfocusing",
"uniquify",
"unmaximize",
"unminimize",
"unpackaged",
"unpremultiplied",
"unwantedly",
"UPNG",
"ustom",
"UTIF",
"vaporwave",
"verts",
"Viacam",
"viewports",
"VSNs",
"Wayback",
"Webamp",
"webglcontextlost",
"webglcontextrestored",
"webp",
"wicg",
"Winamp",
"WINTRAP",
"woah",
"Wolfie",
"xfconf",
"xtras",
"zoomable",
"zoomer",
"עברית",
"العربية",
"𖦹ᯅ𖦹"
]
}
================================================
FILE: cypress/cypress-image-snapshot-viewer.js
================================================
// ==UserScript==
// @name Cypress Image Snapshot Viewer
// @namespace https://github.com/1j01/
// @version 0.1
// @description Show diffs of screenshots within the Cypress Dashboard. Works with images from cypress-image-snapshot. To use, press D in the gallery, and then move the mouse over and out of the image.
// @author Isaiah Odhner
// @match https://dashboard.cypress.io/*
// @grant none
// @noframes
// ==/UserScript==
(function () {
"use strict";
let cleanUp = null;
function showDiffView(originalImg) {
if (cleanUp) { cleanUp(); }
var screenshotWidth = originalImg.naturalWidth / 3;
var screenshotHeight = originalImg.naturalHeight;
originalImg.style.opacity = "0";
var img = document.createElement("img");
img.src = originalImg.src;
img.style.position = "absolute";
img.style.left = "0";
img.style.pointerEvents = "all";
img.draggable = false;
img.addEventListener("mouseenter", () => {
img.style.left = `${-2 * screenshotWidth}px`;
});
img.addEventListener("mouseleave", () => {
img.style.left = "0";
});
var container = document.createElement("div");
container.style.width = `${screenshotWidth}px`;
container.style.height = `${screenshotHeight}px`;
container.style.position = "relative";
container.style.overflow = "hidden";
container.style.margin = "auto";
var outerContainer = document.createElement("div");
outerContainer.style.position = "fixed";
outerContainer.style.display = "flex";
outerContainer.style.left = "0";
outerContainer.style.right = "0";
outerContainer.style.top = "0";
outerContainer.style.bottom = "0";
outerContainer.style.zIndex = "100000";
outerContainer.style.pointerEvents = "none";
outerContainer.appendChild(container);
container.appendChild(img);
document.body.appendChild(outerContainer);
cleanUp = () => {
originalImg.style.opacity = "";
container.style.transformOrigin = "center center";
container.style.transition = "opacity 0.2s ease, transform 0.2s ease";
container.style.opacity = 0;
container.style.transform = "scale(0.9)";
setTimeout(() => {
outerContainer.remove();
}, 500);
cleanUp = null;
};
}
addEventListener("keydown", (e) => {
if (e.key === "d") {
if (cleanUp) {
cleanUp();
} else {
var originalImg = document.elementFromPoint(innerWidth / 2, innerHeight / 2);
if (!originalImg || !originalImg.matches("img")) {
console.warn("Didn't find an image in the middle of the page. Found", originalImg);
return;
}
showDiffView(originalImg);
}
} else if (e.key === "Escape") {
if (cleanUp) { cleanUp(); }
}
});
// mousedown is TAKEN - with stopPropagation, presumably
// (useCapture doesn't help)
addEventListener("pointerdown", (_event) => {
if (cleanUp) { cleanUp(); }
});
})();
================================================
FILE: cypress/fixtures/example.json
================================================
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
================================================
FILE: cypress/integration/tool-tests.spec.js
================================================
/// <reference types="Cypress" />
context("tool tests", () => {
// @TODO: make rounded tools render consistently across platforms
const roundedToolsCompareOptions = {
failureThreshold: 13,
failureThresholdType: "pixel",
};
before(() => {
cy.visit("/");
cy.setResolution([800, 500]);
cy.window().should("have.property", "api_for_cypress_tests"); // wait for app to be loaded
});
beforeEach(() => {
// eslint-disable-next-line require-await
cy.window().then({ timeout: 60000 }, async (win) => {
win.api_for_cypress_tests.reset_for_next_test();
});
});
const simulateGesture = (win, { start, end, shift, /*shiftToggleChance = 0.01,*/ secondary, /*secondaryToggleChance,*/ target }) => {
target = target || win.$(".main-canvas")[0];
let startWithinRect = target.getBoundingClientRect();
let canvasAreaRect = win.$(".canvas-area")[0].getBoundingClientRect();
let startMinX = Math.max(startWithinRect.left, canvasAreaRect.left);
let startMaxX = Math.min(startWithinRect.right, canvasAreaRect.right);
let startMinY = Math.max(startWithinRect.top, canvasAreaRect.top);
let startMaxY = Math.min(startWithinRect.bottom, canvasAreaRect.bottom);
let startPointX = startMinX + start.x * (startMaxX - startMinX);
let startPointY = startMinY + start.y * (startMaxY - startMinY);
let endPointX = startMinX + end.x * (startMaxX - startMinX);
let endPointY = startMinY + end.y * (startMaxY - startMinY);
const $cursor = win.$(`<img src="images/cursors/default.png" class="user-cursor"/>`);
$cursor.css({
position: "absolute",
left: 0,
top: 0,
opacity: 0,
zIndex: 5, // @#: z-index
pointerEvents: "none",
transition: "opacity 0.5s",
});
$cursor.appendTo(".jspaint");
let triggerMouseEvent = (type, point) => {
const clientX = point.x;
const clientY = point.y;
// const el_over = win.document.elementFromPoint(clientX, clientY);
const do_nothing = false;//!type.match(/move/) && (!el_over || !el_over.closest(".canvas-area"));
$cursor.css({
display: "block",
position: "absolute",
left: clientX,
top: clientY,
opacity: do_nothing ? 0.5 : 1,
});
if (do_nothing) {
return;
}
let event = new win.$.Event(type, {
view: window,
bubbles: true,
cancelable: true,
clientX,
clientY,
screenX: clientX,
screenY: clientY,
offsetX: point.x,
offsetY: point.y,
button: secondary ? 2 : 0,
buttons: secondary ? 2 : 1,
shiftKey: shift,
});
win.$(target).trigger(event);
};
let t = 0;
const stepsInGesture = 3;
let pointForTime = (t) => {
return {
x: startPointX + (endPointX - startPointX) * t,
y: startPointY + (endPointY - startPointY) * Math.pow(t, 0.3),
};
};
return new Promise((resolve) => {
triggerMouseEvent("pointerenter", pointForTime(t)); // so dynamic cursors follow the simulation cursor
triggerMouseEvent("pointerdown", pointForTime(t));
let move = () => {
t += 1 / stepsInGesture;
// if (seededRandom() < shiftToggleChance) {
// shift = !shift;
// }
// if (seededRandom() < secondaryToggleChance) {
// secondary = !secondary;
// }
if (t > 1) {
triggerMouseEvent("pointerup", pointForTime(t));
$cursor.remove();
resolve();
} else {
triggerMouseEvent("pointermove", pointForTime(t));
/*gestureTimeoutID =*/ setTimeout(move, 10);
}
};
triggerMouseEvent("pointerleave", pointForTime(t));
move();
});
};
// const gesture = (points) => {
// const options = { secondary: false, shift: false };
// // @TODO: while loop
// trigger("pointerenter", points[0].x, points[0].y, options);
// trigger("pointerdown", points[0].x, points[0].y, options);
// let i = 0;
// for (; i < points.length; i++) {
// trigger("pointermove", points[i].x, points[i].y, options);
// }
// i--;
// trigger("pointerup", points[i].x, points[i].y, options);
// };
// it("brush tool", () => {
// cy.get(".tool[title='Brush']").click();
// // gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]);
// cy.get(".swatch:nth-child(21)").rightclick();
// cy.window().then({ timeout: 8000 }, async (win) => {
// for (let secondary = 0; secondary <= 1; secondary++) {
// for (let b = 0; b < 12; b++) {
// win.$(`.chooser > :nth-child(${b + 1})`).click();
// const start = { x: 0.05 + b * 0.05, y: 0.1 + 0.1 * secondary };
// const end = { x: start.x + 0.04, y: start.y + 0.04 };
// await simulateGesture(win, { shift: false, secondary: !!secondary, start, end });
// }
// }
// });
// cy.matchImageSnapshot();
// });
// @TODO: test transparent document mode
it("eraser tool", () => {
cy.get(".tool[title='Eraser/Color Eraser']").click();
// gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]);
cy.window().then({ timeout: 60000 }, async (win) => {
const { selected_colors } = win.api_for_cypress_tests;
for (let row = 0; row < 4; row++) {
const secondary = !!(row % 2);
const increaseSize = row >= 2;
let $options = win.$(".chooser > *");
for (let o = 0; o < $options.length; o++) {
$options[o].click();
if (increaseSize) {
for (let i = 0; i < 5; i++) {
win.$("body").trigger(new win.$.Event("keydown", { code: "NumpadAdd" }));
}
}
selected_colors.background = "#f0f";
const start = { x: 0.05 + o * 0.05, y: 0.1 + 0.1 * row };
const end = { x: start.x + 0.04, y: start.y + 0.04 };
await simulateGesture(win, { shift: false, secondary: false, start, end });
if (secondary) {
selected_colors.background = "#ff0";
selected_colors.foreground = "#f0f";
const start = { x: 0.04 + o * 0.05, y: 0.11 + 0.1 * row };
const end = { x: start.x + 0.03, y: start.y + 0.02 };
await simulateGesture(win, { shift: false, secondary: true, start, end });
}
}
}
});
cy.get(".main-canvas").matchImageSnapshot();
});
["Brush", "Pencil", "Rectangle", "Rounded Rectangle", "Ellipse", "Line"].forEach((toolName) => {
it(`${toolName.toLowerCase()} tool`, () => {
cy.get(`.tool[title='${toolName}']`).click();
// gesture([{ x: 50, y: 50 }, { x: 100, y: 100 }]);
cy.get(".swatch:nth-child(22)").rightclick();
cy.window().then({ timeout: 60000 }, async (win) => {
for (let row = 0; row < 4; row++) {
const secondary = !!(row % 2);
const increaseSize = row >= 2;
let $options = win.$(".chooser > *");
// Pencil has no options
if ($options.length === 0) {
$options = win.$("<dummy>");
}
for (let o = 0; o < $options.length; o++) {
$options[o].click();
if (increaseSize && (o === 0 || toolName === "Brush" || toolName === "Line")) {
for (let i = 0; i < 5; i++) {
win.$("body").trigger(new win.$.Event("keydown", { code: "NumpadAdd" }));
}
}
const start = { x: 0.05 + o * 0.05, y: 0.1 + 0.1 * row };
const end = { x: start.x + 0.04, y: start.y + 0.04 };
await simulateGesture(win, { shift: false, secondary: !!secondary, start, end });
}
}
});
cy.get(".main-canvas").matchImageSnapshot(toolName.match(/Rounded Rectangle|Ellipse/) ? roundedToolsCompareOptions : undefined);
});
});
});
================================================
FILE: cypress/integration/visual-tests.spec.js
================================================
/// <reference types="Cypress" />
context("visual tests", () => {
// These tests are not really cross-platform or even cross-computer,
// since they depend on pixel-exact text and SVG rendering, as well as browser-specific built-in styles and layout.
// Unfortunately, increasing the threshold to a point where the tests pass on all systems would introduce RIDICULOUS false negatives,
// like changing the entire icon set wasn't even detected as a change, in Eye Gaze Mode (now Enlarge UI mode), where the icons are HUGE!
// And again unfortunately, decreasing the threshold to the point where it detects most changes that matter,
// it produces RIDICULOUS false positives, like the window title bar gradient and all text being said to be different,
// even on the same machine! In short, the image comparison is unusable.
// I suspect it treats a difference between 254 and 255 (white and white) the same as a difference between 0 and 255 (black and white),
// and if it just summed the differences instead of counting the number of pixels that differ, it would be much more useful,
// although still not cross-device due to font rendering differences etc.
// For now, I've removed the thresholds so it will always detect changes;
// that way I can at least use it to view the diffs, occasionally, if not automatically check for changes.
const withTextCompareOptions = {
// failureThreshold: 0.05, // masks HUGE differences
// failureThresholdType: "percent" // not actually percent - fraction
failureThreshold: 0,
failureThresholdType: "pixel",
};
const withMuchTextCompareOptions = {
// failureThreshold: 0.08, // masks HUGE differences
// failureThresholdType: "percent" // not actually percent - fraction
failureThreshold: 0,
failureThresholdType: "pixel",
};
const toolboxCompareOptions = {
// failureThreshold: 40,
// failureThresholdType: "pixel"
failureThreshold: 0,
failureThresholdType: "pixel",
};
const escapeRegExp = (string) =>
string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
// Menus need pointer events currently.
// These "click*" functions are used to interact with menus, and don't trigger click events.
const clickElementWithExactText = (selector, text) => {
cy.contains(selector, new RegExp(`^${escapeRegExp(text)}$`))
// .click();
.trigger("pointerdown", { which: 1 })
.trigger("pointerup", { force: true });
};
const closeMenus = () => {
cy.get(".status-text").click({ force: true }); // force because a menu may be covering the status bar / part of it
};
const clickMenuButton = (label) => {
clickElementWithExactText(".menu-button", label);
};
const clickMenuItem = (label) => {
clickElementWithExactText(".menu-item-label", label);
};
const selectTheme = (themeName) => {
clickMenuButton("Extras");
clickMenuItem("Themes");
clickMenuItem(themeName);
closeMenus();
cy.wait(1000); // give a bit of time for theme to load
};
// `intercept` requires Cypress 6+
// cypress-image-snapshot@4.0.1 has a peer dependency on cypress@"^4.5.0",
// although I believe it works with v9, and only really has problems on v10.
// That said, this didn't work! So. No point in upgrading just yet.
// I'll upgrade when I'm ready to replace the visual testing framework.
// const waitForRequest = (urlPattern, callback) => {
// // intercept without changing or stubbing response
// cy.intercept(urlPattern).as("urlPattern");
// cy.wait("@urlPattern").then(callback);
// };
const waitForImage = (selector) => {
// should automatically retries
// checking visibility first ensures we're testing at least one image, theoretically
cy.get(selector).should("be.visible");
cy.get(selector).should(($imgs) => {
for (const img of $imgs) {
expect(img.naturalWidth).to.be.greaterThan(0);
expect(img.naturalHeight).to.be.greaterThan(0);
}
});
};
before(() => {
// Hides the news indicator, which shouldn't affect the visual tests.
// If by the year 3000 AI doesn't automatically find and fix stupid code like this, humanity will have already been doomed.
cy.clock(32503698000000);
cy.visit("/");
cy.setResolution([760, 490]);
cy.window().should("have.property", "api_for_cypress_tests"); // wait for app to be loaded
// Needed, given `cy.clock` is used, for `requestAnimationFrame` in `update_$swatch`,
// so the color palette is rendered correctly.
cy.tick(100);
});
it("main screenshot", () => {
cy.matchImageSnapshot(withTextCompareOptions);
});
it("brush selected", () => {
cy.get('.tool[title="Brush"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("select selected", () => {
cy.get('.tool[title="Select"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("magnifier selected", () => {
cy.get('.tool[title="Magnifier"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("airbrush selected", () => {
cy.get('.tool[title="Airbrush"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("eraser selected", () => {
cy.get('.tool[title="Eraser/Color Eraser"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("line selected", () => {
cy.get('.tool[title="Line"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
it("rectangle selected", () => {
cy.get('.tool[title="Rectangle"]').click();
cy.get(".tools-component").matchImageSnapshot(toolboxCompareOptions);
});
beforeEach(() => {
if (Cypress.$(".window:visible")[0]) {
cy.get(".window:visible .window-close-button").click();
cy.get(".window").should("not.be.visible");
}
});
it("image attributes window", () => {
cy.get("body").type("{ctrl}e");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("modern dark theme -- image attributes window", () => {
selectTheme("Modern Dark");
cy.get("body").type("{ctrl}e");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("modern dark theme -- custom zoom window", () => {
clickMenuButton("View");
clickMenuItem("Zoom");
clickMenuItem("Custom...");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("bubblegum theme - custom zoom window", () => {
// selectTheme("Bubblegum"); // not released yet
cy.window().then((win) => {
win.api_for_cypress_tests.set_theme("bubblegum.css");
});
clickMenuButton("View");
clickMenuItem("Zoom");
clickMenuItem("Custom...");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("custom zoom window", () => {
selectTheme("Classic Light");
clickMenuButton("View");
clickMenuItem("Zoom");
clickMenuItem("Custom...");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("flip and rotate window", () => {
clickMenuButton("Image");
clickMenuItem("Flip/Rotate");
cy.get(".window:visible").matchImageSnapshot(withMuchTextCompareOptions);
});
it("stretch and skew window", () => {
clickMenuButton("Image");
clickMenuItem("Stretch/Skew");
waitForImage(".window:visible img");
cy.get(".window:visible").matchImageSnapshot(withTextCompareOptions);
});
it("help window", () => {
clickMenuButton("Help");
clickMenuItem("Help Topics");
cy.get(".window:visible .folder", { timeout: 10000 }); // wait for sidebar contents to load
// @TODO: wait for iframe to load
cy.get(".window:visible").matchImageSnapshot(Object.assign({}, withTextCompareOptions, { blackout: ["iframe"] }));
});
it("about window", () => {
clickMenuButton("Help");
clickMenuItem("About Paint");
waitForImage("#about-paint-icon");
cy.get(".window:visible").matchImageSnapshot(Object.assign({}, withMuchTextCompareOptions, { blackout: ["#maybe-outdated-line", "#jspaint-version"] }));
});
const toggleEyeGazeMode = () => {
// Eye Gaze Mode has been split into several features.
clickMenuButton("Extras");
clickMenuItem("Vertical Color Box");
closeMenus();
clickMenuButton("Extras");
clickMenuItem("Quick Undo Button");
closeMenus();
clickMenuButton("Extras");
clickMenuItem("Dwell Clicker");
closeMenus();
clickMenuButton("Extras");
clickMenuItem("Enlarge UI");
closeMenus();
};
it("eye gaze mode", () => {
cy.get('.tool[title="Select"]').click();
toggleEyeGazeMode();
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
cy.wait(100);
cy.get(".floating-undo-button").should("exist");
cy.matchImageSnapshot(withTextCompareOptions);
});
it("bubblegum theme -- eye gaze mode", () => {
cy.get(".floating-undo-button").should("exist");
// selectTheme("Bubblegum"); // not released yet
cy.window().then((win) => {
win.api_for_cypress_tests.set_theme("bubblegum.css");
});
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
it("modern light theme -- eye gaze mode", () => {
cy.get(".floating-undo-button").should("exist");
selectTheme("Modern Light");
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
it("exit eye gaze mode", () => {
// this acts as teardown for the eye gaze mode tests
toggleEyeGazeMode();
cy.get(".floating-undo-button").should("not.exist");
});
it("modern light theme -- main screenshot", () => {
cy.wait(100);
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
closeMenus();
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
const test_edit_colors_dialog = (expand = true) => {
clickMenuButton("Colors");
clickMenuItem("Edit Colors...");
cy.wait(100);
if (expand) {
cy.contains("button", "Define Custom Colors >>").click();
}
cy.get(".window:visible").matchImageSnapshot(Object.assign({}, withTextCompareOptions));
};
it("modern light theme -- edit colors dialog (expanded)", () => {
test_edit_colors_dialog(true);
});
it("bubblegum theme -- main screenshot", () => {
// selectTheme("Bubblegum"); // not released yet
cy.window().then((win) => {
win.api_for_cypress_tests.set_theme("bubblegum.css");
});
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
it("bubblegum theme -- about window", () => {
clickMenuButton("Help");
clickMenuItem("About Paint");
// waitForImage("#about-paint-icon"); // it's actually replaced with a background image in this theme
// waitForRequest("/images/bubblegum/bubblegum-paint-128x128.png", () => { // not working
// waitForRequest("**/bubblegum-paint-*.png", () => { // not working
cy.wait(1000); // wait and hope it's loaded
cy.get(".window:visible").matchImageSnapshot(Object.assign({}, withMuchTextCompareOptions, { blackout: ["#maybe-outdated-line", "#jspaint-version"] }));
// });
});
it("winter theme -- main screenshot", () => {
selectTheme("Winter");
// clickMenuButton("View");
// cy.get("body").trigger("pointermove", { clientX: 200, clientY: 150 });
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
it("winter theme -- edit colors dialog (expanded)", () => {
test_edit_colors_dialog(true);
});
it("winter theme -- vertical color box", () => {
cy.wait(500);
clickMenuButton("Extras");
clickMenuItem("Vertical Color Box");
cy.wait(500);
closeMenus();
cy.wait(100);
cy.matchImageSnapshot(withTextCompareOptions);
});
it("vertical color box", () => {
selectTheme("Classic Light");
cy.matchImageSnapshot(withTextCompareOptions);
});
it("edit colors dialog", () => {
test_edit_colors_dialog(false);
});
it("modern light theme -- vertical color box", () => {
selectTheme("Modern Light");
cy.matchImageSnapshot(withTextCompareOptions);
});
it("about window during pride month", () => {
// TODO: DRY with other about window tests and the app loading in the `before` hook,
// maybe enable test isolation even though it's slower to load the app every time
// June 19, 3000
cy.clock(32518299600000);
cy.visit("/");
cy.setResolution([760, 490]);
cy.window().should("have.property", "api_for_cypress_tests"); // wait for app to be loaded
// Needed, given `cy.clock` is used, for `requestAnimationFrame` in `update_$swatch`,
// so the color palette is rendered correctly.
// (Doesn't apply to this test.)
cy.tick(100);
clickMenuButton("Help");
clickMenuItem("About Paint");
waitForImage("#about-paint-icon");
cy.get(".window:visible").matchImageSnapshot(Object.assign({}, withMuchTextCompareOptions, { blackout: ["#maybe-outdated-line", "#jspaint-version"] }));
});
});
================================================
FILE: cypress/plugins/index.js
================================================
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const {
addMatchImageSnapshotPlugin,
} = require("cypress-image-snapshot/plugin");
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
addMatchImageSnapshotPlugin(on, config);
};
================================================
FILE: cypress/support/commands.js
================================================
import { addMatchImageSnapshotCommand } from "cypress-image-snapshot/command";
addMatchImageSnapshotCommand({
failureThreshold: 0,
failureThresholdType: "pixel",
customDiffConfig: { threshold: 0 },
capture: "viewport",
});
Cypress.Commands.add("setResolution", (size) => {
if (Cypress._.isArray(size)) {
cy.viewport(size[0], size[1]);
} else {
cy.viewport(size);
}
});
================================================
FILE: cypress/support/index.js
================================================
// ***********************************************************
// This support/index.js is processed and
// loaded automatically before your test files.
//
// https://on.cypress.io/configuration
import "./commands";
================================================
FILE: cypress.json
================================================
{
"projectId": "6im7v7",
"baseUrl": "http://localhost:11822",
"video": false
}
================================================
FILE: discord-activity/.gitignore
================================================
node_modules
*.pem
*.log
.DS_Store
build
dist
.env
================================================
FILE: discord-activity/README.md
================================================
# Discord Embedded App Starter
This repo is a minimal starter-project. Getting an embedded app running in Discord can be complex. The goal of this example is to get you up-and-running as quickly as possible, while making it easy to swap in pieces to fit your embedded app's client and server needs.
## Client architecture
The client (aka front-end) is using vanilla JS.
### Server architecture
The server (aka back-end) is using Express with typescript.
## Setting up your Discord Application
Before we write any code, lets follow the instructions [here](https://discord.com/developers/docs/activities/building-an-activity#step-1-creating-a-new-app) to make sure your Discord application is set up correctly.
## Setting up your environment variables
In this directory (`/examples/discord-activity-starter`) we need to create a `.env` file with the OAuth2 variables, as described [here](https://discord.com/developers/docs/activities/building-an-activity#find-your-oauth2-credentials).
```env
VITE_CLIENT_ID=123456789012345678
CLIENT_SECRET=abcdefghijklmnopqrstuvwxyzabcdef
```
### Adding a new environment variable
In order to add new environment variables, you will need to do the following:
1. Add the environment key and value to `.env`
2. Add the key to [/examples/discord-activity-starter/packages/client/src/vite-env.d.ts](/examples/discord-activity-starter/packages/client/src/vite-env.d.ts)
3. Add the key to [/examples/discord-activity-starter/packages/server/environment.d.ts](/examples/discord-activity-starter/packages/server/environment.d.ts)
This will ensure that you have type safety when consuming your environment variables
## Running your app locally
As described [here](https://discord.com/developers/docs/activities/building-an-activity#step-4-running-your-app-locally-in-discord), we encourage using a tunnel solution such as [cloudflared](https://github.com/cloudflare/cloudflared#installing-cloudflared) for local development.
To run your app locally, run the following from this directory (/examples/discord-activity-starter)
```
pnpm install # only need to run this the first time
pnpm dev
pnpm tunnel # from another terminal
```
Be sure to complete all the steps listed [here](https://discord.com/developers/docs/activities/building-an-activity) to ensure your development setup is working as expected.
================================================
FILE: discord-activity/package.json
================================================
{
"name": "discord-activity-starter",
"private": true,
"version": "0.1.0",
"description": "A minimal starter project using embedded-app-sdk",
"main": "index.js",
"scripts": {
"dev": "pnpm run --filter \"./packages/**\" --parallel dev",
"tunnel": "cloudflared tunnel --url http://localhost:3000"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.19.2"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.12.7",
"nodemon": "^3.1.0",
"npm-run-all2": "^6.0.0",
"rimraf": "^5.0.0",
"ts-node": "^10.9.1",
"typescript": "~5.4.0"
}
}
================================================
FILE: discord-activity/packages/server/environment.d.ts
================================================
declare global {
namespace NodeJS {
interface ProcessEnv {
VITE_CLIENT_ID: string;
CLIENT_SECRET: string;
NODE_ENV: "development" | "production";
PORT?: string;
PWD: string;
}
}
}
export { };
================================================
FILE: discord-activity/packages/server/package.json
================================================
{
"name": "server",
"version": "0.1.0",
"description": "The app server",
"main": "index.js",
"scripts": {
"start": "npm-run-all build start:prod",
"start:prod": "node ./dist/app.js",
"dev": "nodemon --watch src -e ts,ejs --exec $npm_execpath start",
"build": "npm-run-all build:clean build:tsc",
"build:clean": "rimraf dist",
"build:tsc": "tsc",
"debug:start": "npm-run-all build debug:start:prod",
"debug:start:prod": "node --nolazy --inspect-brk=9229 ./dist/app.js"
},
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.2",
"dotenv": "^16.0.1",
"express-ws": "^5.0.2",
"nodemon": "^3.1.0"
},
"devDependencies": {
"@types/express-ws": "^3.0.4",
"npm-run-all2": "^6.0.0"
}
}
================================================
FILE: discord-activity/packages/server/src/app.ts
================================================
import bodyParser from "body-parser";
import dotenv from "dotenv";
import express, { Application, Request, Response } from "express";
// import enableWs from "express-ws";
import fs from "fs";
import path from "path";
import { fetchAndRetry } from "./utils";
dotenv.config({ path: "../../.env" });
const app: Application = express();
const port: number = Number(process.env.PORT) || 1999;
// enableWs(app);
app.use(express.json());
const clientSourcePath = path.join(__dirname, "../../../..");
const clientId = process.env.VITE_CLIENT_ID;
const clientIdNeedle = "$$$$$CLIENT_ID$$$$$"; // same length as the client ID, just in case
const urlPathForPatching = "/src/discord-activity-client.js";
const fsPathForPatching = path.join(clientSourcePath, urlPathForPatching);
// Ensure the file exists and prepare it for serving
// const patchedFileContent = fs.readFileSync(fsPathForPatching, "utf8").replace(clientIdNeedle, clientId);
// // Serve the patched file
// app.get(urlPathForPatching, (req, res) => {
// res.setHeader("Content-Type", "text/javascript");
// res.send(patchedFileContent);
// });
if (!fs.existsSync(fsPathForPatching)) {
throw new Error(`Could not find file at ${fsPathForPatching}`);
}
// Serve the patched file without caching it, for development purposes
app.get(urlPathForPatching, (req, res) => {
fs.readFile(fsPathForPatching, "utf8", (err, data) => {
if (err) {
res.status(500).send(err);
return;
}
res.setHeader("Content-Type", "text/javascript");
res.send(data.replace(clientIdNeedle, clientId));
});
});
// if (process.env.NODE_ENV === "production") {
// const clientBuildPath = path.join(__dirname, "../../client/dist");
// app.use(express.static(clientBuildPath));
// }
// I'm hacking this to work without Vite, without a build step, and without a client folder / monorepo structure.
// This will include odds and ends like .git and .env files by default, so we need to exclude them with an extra route,
// as .env is a security risk and .git and .history are potentially sensitive as well.
app.use((req, res, next) => {
// Must be case-insensitive for Windows FS!
// There are quite possibly ways to bypass this, with URL encoding or similar...
// TODO: use a clean allowed set of files.
if (req.path.match(/\.(git|history|env)/i)) {
res.status(403).send("Forbidden");
return;
}
next();
});
app.use(express.static(clientSourcePath));
// Fetch token from developer portal and return to the embedded app
app.post("/api/token", async (req: Request, res: Response) => {
const response = await fetchAndRetry(`https://discord.com/api/oauth2/token`, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
client_id: process.env.VITE_CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
grant_type: "authorization_code",
code: req.body.code,
}),
});
const { access_token } = (await response.json()) as {
access_token: string;
};
res.send({ access_token });
});
// Simple multiplayer image editing
const rooms: { [key: string]: string } = {};
// app.post("/api/rooms", (req: Request, res: Response) => {
// const roomId = uuid(); // or the room id might be the Discord Activity instance ID
// rooms[roomId] = "";
// res.send({ roomId });
// });
app.get("/api/rooms/:roomId/data", (req: Request, res: Response) => {
const { roomId } = req.params;
res.send(rooms[roomId]);
});
app.put("/api/rooms/:roomId/data", bodyParser.text({ type: "*/*" }), (req: Request, res: Response) => {
const { roomId } = req.params;
const image = req.body;
rooms[roomId] = image;
res.send({ success: true });
});
// app.ws("/api/sessions/:session_id", (ws, req) => {
// console.log("WebSocket support is enabled")
// @ts-ignore
// app.ws("/api/session", (ws, req) => {
// console.log("WebSocket was opened")
// ws.on("message", (msg: string) => {
// console.log("Received message", msg)
// ws.send(msg)
// })
// ws.on("close", () => {
// console.log("WebSocket was closed")
// })
// })
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`App is listening on port ${port} !`);
});
================================================
FILE: discord-activity/packages/server/src/shared/hello.ts
================================================
export function hello() {
console.log("hello from the server's shared folder");
}
================================================
FILE: discord-activity/packages/server/src/utils.ts
================================================
export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* This function extends fetch to allow retrying
* If the request returns a 429 error code, it will wait and retry after "retry_after" seconds
*/
export async function fetchAndRetry(
input: RequestInfo,
init?: RequestInit | undefined,
nRetries: number = 3,
): Promise<Response> {
try {
// Make the request
const response = await fetch(input, init);
// If there's a 429 error code, retry after retry_after seconds
// https://discord.com/developers/docs/topics/rate-limits#rate-limits
if (response.status === 429 && nRetries > 0) {
const retryAfter = Number(response.headers.get("retry_after"));
if (Number.isNaN(retryAfter)) {
return response;
}
await sleep(retryAfter * 1000);
return await fetchAndRetry(input, init, nRetries - 1);
} else {
return response;
}
} catch (ex) {
if (nRetries <= 0) {
throw ex;
}
// If the request failed, wait one second before trying again
// This could probably be fancier with exponential backoff
await sleep(1000);
return await fetchAndRetry(input, init, nRetries - 1);
}
}
================================================
FILE: discord-activity/packages/server/tsconfig.json
================================================
{
"compilerOptions": {
"outDir": "dist",
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*.ts",
"./environment.d.ts"
],
"exclude": [
"node_modules"
]
}
================================================
FILE: eslint.config.mjs
================================================
import js from "@eslint/js";
import stylistic from "@stylistic/eslint-plugin";
import globals from "globals";
/** @type {import("@types/eslint").Linter.FlatConfig[]} */
export default [
{
// "if an ignores key is used without any other keys in the configuration object, then the patterns act as global ignores"
"ignores": [
"**/node_modules/",
"**/.git/",
"**/.history/",
"**/.idea/",
"**/.vscode/",
"**/lib/", // vendored dependencies
"**/out/", // Electron build
"**/build/", // maybe nothing
"**/dist/", // maybe nothing
"**/localization/*/*.js", // generated files (note that there is some non-generated JS directly in `localization/`, hence not using `**/localization/**/*.js`)
],
},
js.configs.recommended,
{
"linterOptions": {
"reportUnusedDisableDirectives": "warn",
},
"languageOptions": {
"ecmaVersion": 2022,
"sourceType": "module",
"globals": {
...globals.browser,
...globals.es2022,
// libraries
"$": "readonly",
"jQuery": "readonly",
"libtess": "readonly",
"firebase": "readonly",
"GIF": "readonly",
"saveAs": "readonly",
"YT": "readonly",
"FontDetective": "readonly",
"AnyPalette": "readonly",
"ImageTracer": "readonly",
// os-gui's MenuBar.js
// "MenuBar": "readonly",
// "MENU_DIVIDER": "readonly",
// os-gui's $Window.js
// "$Window": "readonly",
// "$FormWindow": "readonly",
// os-gui's parse-theme.js has more
},
},
"plugins": {
"@stylistic": stylistic,
},
"rules": {
"no-undef": "warn",
"no-unused-vars": ["warn", {
"args": "all",
"argsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_",
// "varsIgnorePattern": "^_",
}],
// "eqeqeq": "error",
// "class-methods-use-this": "error",
"no-alert": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-invalid-this": "error",
"no-new-func": "error",
"no-eval": "error",
"no-new-wrappers": "error",
"no-proto": "error",
"no-return-assign": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-throw-literal": "error",
"no-unmodified-loop-condition": "error",
"no-unused-expressions": "error", // Tip: `a && a();` can become `a?.();` https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
"no-useless-concat": "error",
"prefer-promise-reject-errors": "error",
"radix": "error",
"require-await": "error",
// "vars-on-top": "error",
"no-label-var": "error",
// "no-shadow": "error",
// "no-use-before-define": "error",
// To target specific variables to rename or otherwise address:
"no-restricted-globals": ["error", "event", "canvas", "ctx", "colors", "i", "j", "k", "x", "y", "z", "width", "height", "w", "h"],
// Stylistic:
"@stylistic/array-bracket-newline": ["error", "consistent"],
"@stylistic/array-bracket-spacing": ["error", "never"],
// "@stylistic/array-element-newline": ["error", "consistent"], // lot of big arrays with sometimes meaningful line breaks; could exclude certain files though
"@stylistic/arrow-parens": ["error", "always"],
"@stylistic/arrow-spacing": ["error", { "before": true, "after": true }],
"@stylistic/block-spacing": ["error", "always"],
"@stylistic/brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"@stylistic/comma-dangle": ["error", {
"arrays": "always-multiline", // ensure commas to avoid confusing git diffs
"objects": "always-multiline", // ensure commas to avoid confusing git diffs
"imports": "never", // always a single line anyways
"exports": "never", // matches VS Code's default JS/TS formatter
"functions": "only-multiline", // commas sometimes avoid confusing git diffs, sometimes are confusing themselves
}],
"@stylistic/comma-spacing": ["error", { "before": false, "after": true }],
"@stylistic/comma-style": ["error", "last"],
"@stylistic/computed-property-spacing": ["error", "never"],
"@stylistic/dot-location": ["error", "property"],
"@stylistic/eol-last": ["error", "always"],
// "@stylistic/function-call-argument-newline": ["error", "consistent"], // several places with meaningful line breaks grouping arguments
"@stylistic/function-call-spacing": ["error", "never"],
// "@stylistic/function-paren-newline": ["error", "multiline-arguments"], // several places with meaningful line breaks grouping arguments
"@stylistic/generator-star-spacing": ["error", "after"],
// "@stylistic/implicit-arrow-linebreak": ["error", "beside"], // could encourage parens for clarity, but ESLint won't mention that's the reason, so probably not a good idea
// The indent settings are mostly defaults copied from https://github.com/eslint-stylistic/eslint-stylistic/blob/c11f1d6f26c13b29fd44c95c908922cb79a0ac82/packages/eslint-plugin/configs/customize.ts#L115-L154
"@stylistic/indent": ["error", "tab", {
ArrayExpression: 1,
CallExpression: { arguments: 1 },
flatTernaryExpressions: false,
FunctionDeclaration: { body: 1, parameters: 1 },
FunctionExpression: { body: 1, parameters: 1 },
ignoreComments: true, // modified from default
ignoredNodes: [
"TemplateLiteral *",
"JSXElement",
"JSXElement > *",
"JSXAttribute",
"JSXIdentifier",
"JSXNamespacedName",
"JSXMemberExpression",
"JSXSpreadAttribute",
"JSXExpressionContainer",
"JSXOpeningElement",
"JSXClosingElement",
"JSXFragment",
"JSXOpeningFragment",
"JSXClosingFragment",
"JSXText",
"JSXEmptyExpression",
"JSXSpreadChild",
"TSUnionType",
"TSIntersectionType",
"TSTypeParameterInstantiation",
"FunctionExpression > .params[decorators.length > 0]",
"FunctionExpression > .params > :matches(Decorator, :not(:first-child))",
"ClassBody.body > PropertyDefinition[decorators.length > 0] > .key",
],
ImportDeclaration: 1,
MemberExpression: 1,
ObjectExpression: 1,
offsetTernaryExpressions: false,
outerIIFEBody: 1,
SwitchCase: 1,
VariableDeclarator: 1,
}],
"@stylistic/indent-binary-ops": ["error", "tab"],
// "@stylistic/jsx-child-element-spacing": "off",
// "@stylistic/jsx-closing-bracket-location": "off",
// "@stylistic/jsx-closing-tag-location": "off",
// "@stylistic/jsx-curly-brace-presence": "off",
// "@stylistic/jsx-curly-newline": "off",
// "@stylistic/jsx-curly-spacing": "off",
// "@stylistic/jsx-equals-spacing": "off",
// "@stylistic/jsx-first-prop-new-line": "off",
// "@stylistic/jsx-function-call-newline": "off",
// "@stylistic/jsx-indent": "off",
// "@stylistic/jsx-indent-props": "off",
// "@stylistic/jsx-max-props-per-line": "off",
// "@stylistic/jsx-newline": "off",
// "@stylistic/jsx-one-expression-per-line": "off",
// "@stylistic/jsx-pascal-case": "off",
// "@stylistic/jsx-props-no-multi-spaces": "off",
// "@stylistic/jsx-quotes": "off",
// "@stylistic/jsx-self-closing-comp": "off",
// "@stylistic/jsx-sort-props": "off",
// "@stylistic/jsx-tag-spacing": "off",
// "@stylistic/jsx-wrap-multilines": "off",
"@stylistic/key-spacing": ["error", { "beforeColon": false, "afterColon": true }],
"@stylistic/keyword-spacing": ["error", { "before": true, "after": true }],
// "@stylistic/line-comment-position": "off",
// "@stylistic/linebreak-style": "off",
// "@stylistic/lines-around-comment": ["error", ""], // TODO maybe (so many options...)
"@stylistic/lines-between-class-members": ["error", "never"],
// "@stylistic/max-len": ["error", ""], // TODO maybe along with changing export {} to individual exports
"@stylistic/max-statements-per-line": ["error", { "max": 4 }], // TODO: maybe decrease this
// TODO: lint .d.ts files, and ideally JSDoc comments
// "@stylistic/member-delimiter-style": ["error", { "multiline": { "delimiter": "semi", "requireLast": true }, "singleline": { "delimiter": "semi", "requireLast": true } }],
// "@stylistic/multiline-comment-style": ["error", "separate-lines"], // I use block comments sometimes for disabled code; also this is detecting a few JSDoc comments even though it says it won't without "checkJSDoc" set to true.
// "@stylistic/multiline-ternary": ["error", "always-multiline"], // might want to change the ternary style in the future...
"@stylistic/new-parens": ["error", "always"],
"@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 5 }], // TODO: maybe decrease this
// "@stylistic/no-confusing-arrow": ["error", { "allowParens": true }], // don't really like the changes this implies in the couple of places it flags
// "@stylistic/no-extra-parens": ["error", "all"], // if there are extra parens, it's probably for clarity (TODO: look at the granular options), also, this doesn't seem to detect cases it should for function calls?
"@stylistic/no-extra-semi": "error",
"@stylistic/no-floating-decimal": "error",
// "@stylistic/no-mixed-operators": ["error", ...], // TODO: investigate options
"@stylistic/no-mixed-spaces-and-tabs": "error",
"@stylistic/no-multi-spaces": "error",
"@stylistic/no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }],
// "@stylistic/no-tabs": "off", // I use tabs for indentation, in disabled code, and in template literals
"@stylistic/no-trailing-spaces": "error",
"@stylistic/no-whitespace-before-property": "error",
"@stylistic/nonblock-statement-body-position": ["error", "beside"], // TODO: maybe drop curly braces from single line conditionals
// "@stylistic/object-curly-newline": ["error", ""], // TODO: investigate options
"@stylistic/object-curly-spacing": ["error", "always"],
"@stylistic/object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }],
// "@stylistic/one-var-declaration-per-line": ["error", "always"], // TODO maybe? there is a risk of `let a, b = 0;` leaving `a` as undefined, but sometimes it just looks better, for related variables...
"@stylistic/operator-linebreak": ["error", "after"], // not sure about ternary operator tbh
// "@stylistic/padded-blocks": "off", // it depends, especially on how much stuff is in the block
// "@stylistic/padding-line-between-statements": ["error", ""], // TODO: investigate options, looks very complex
// "@stylistic/quote-props": ["error", "consistent"], // I prefer it inconsistent if it's just for a few CSS custom properties when setting several CSS properties at once, especially since it's not going to be consistent with object property shorthand e.g. { "--requires-quotes": requiresQuotes, "quotedForConsistency": true, inconsistent }
"@stylistic/quotes": ["error", "double", { "avoidEscape": true, "allowTemplateLiterals": true }], // Note: allowTemplateLiterals allows template literals without any substitutions, and removing "allowTemplateLiterals" doesn't allow them for avoiding escaping
"@stylistic/rest-spread-spacing": ["error", "never"],
"@stylistic/semi": ["error", "always"],
"@stylistic/semi-spacing": ["error", { "before": false, "after": true }],
"@stylistic/semi-style": ["error", "last"],
"@stylistic/space-before-blocks": ["error", "always"],
"@stylistic/space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always",
}],
"@stylistic/space-in-parens": ["error", "never"],
"@stylistic/space-infix-ops": "error",
"@stylistic/space-unary-ops": ["error", {
"words": true,
"nonwords": false,
}],
// "@stylistic/spaced-comment": ["error", "always"], // TODO: investigate
"@stylistic/switch-colon-spacing": ["error", { "after": true, "before": false }],
"@stylistic/template-curly-spacing": ["error", "never"],
"@stylistic/template-tag-spacing": ["error", "never"],
// "@stylistic/type-annotation-spacing": ["error", ""], // TODO: lint TS
// "@stylistic/type-generic-spacing": ["error", ""], // TODO: lint TS
// "@stylistic/type-named-tuple-spacing": ["error", ""], // TODO: lint TS
"@stylistic/wrap-iife": ["error", "inside"],
// "@stylistic/wrap-regex": "error", // does that really clarify things? eh
"@stylistic/yield-star-spacing": ["error", "after"],
},
},
{
"files": [
"help/vaporwave.js",
"src/app-localization.js",
"src/app-state.js",
"src/copy-inkscape-labels.js",
"src/error-handling-basic.js",
"svg-paint/svg-paint.js",
"localization/**/*.js",
],
"languageOptions": {
"sourceType": "script",
},
},
{
"files": [
"forge.config.js",
"src/electron-injected.js",
"src/electron-main.js",
"sync-package.js",
"prune-globals.js",
"cypress/plugins/index.js",
"localization/*.js",
],
"languageOptions": {
"sourceType": "commonjs",
"globals": {
...globals.node,
},
},
},
{
"files": [
"cypress/**/*.js",
],
"languageOptions": {
"globals": {
...globals.mocha,
"expect": "readonly",
"cy": "readonly",
"Cypress": "readonly",
},
},
},
];
================================================
FILE: forge.config.js
================================================
const sharedDebRpmOptions = {
name: "jspaint",
productName: "JS Paint",
productDescription: "MS Paint clone with extra features",
genericName: "Image Editor",
homepage: "https://jspaint.app/about",
icon: "images/icons/512x512.png",
categories: [
"Graphics",
],
mimeType: [
// Affects whether the app shows as a recommended app in the "Open With" menu/dialog
"image/*", // wildcard doesn't seem to work
"image/bmp",
"image/gif",
"image/jpeg",
"image/png",
"image/tiff",
"image/webp",
"image/avif",
"image/x-icon",
"image/vnd.microsoft.icon",
"image/x-win-bitmap",
"image/x-icns",
"application/x-gimp-palette",
],
};
module.exports = {
packagerConfig: {
icon: "./images/icons/jspaint",
name: "JS Paint",
executableName: "jspaint",
appBundleId: "io.isaiahodhner.jspaint",
appCategoryType: "public.app-category.graphics-design",
appCopyright: "© 2024 Isaiah Odhner",
extendInfo: {
// Based on https://gist.github.com/sonnypgs/de2b6a4a4936d5b8e0fe43946002964a
// This extends Info.plist to allow dropping files onto the macOS dock icon.
// (all files, not just images, since it's much simpler and I support loading palettes from arbitrary text files)
CFBundleDocumentTypes: [
{
CFBundleTypeName: "All Files",
CFBundleTypeRole: "Editor", // *
LSHandlerRank: "Alternate",
LSItemContentTypes: [
"public.data",
"public.content",
],
},
],
// *Added, but... I'm not sure what CFBundleTypeRole exactly affects in practice.
// The app is an editor, of both images and palettes, but it's not an editor of all file types,
// so it's unclear if this is appropriate.
// TODO: granular image types?
// like https://github.com/electron/forge/issues/492#issuecomment-385956851
},
junk: true,
// TODO: assess filtering of files; I see eslint in node_modules, why? prune is true by default
ignore: [
".history", // VS Code "Local History" extension
"cypress", // Cypress tests
"cypress.json", // Cypress config
"browserconfig.xml", // Windows 8/10 start menu tile
"about.html", // homepage
"parse-rc-file.js", // localization
"preprocess.js", // localization
/\.rc$/, // localization
/\.sh$/, // localization
/\.psd$/, // theming source files
"images/meta", // images used on README, OpenGraph, etc. (arguably README images could be included)
// TODO: "lib/pdf.js/web", // PDF.js UI? (PDF.js is only used as a library, but does it use data from this folder?)
// TODO: Bubblegum theme has some files that are embedded in an SVG, so they're not used directly
// I'd want to move them to a folder or give them a suffix or something, rather than just ignoring them as they are,
// since I may want to use them in the future.
],
// TODO: maybe
// https://electron.github.io/packager/main/interfaces/Options.html#darwinDarkModeSupport
},
makers: [
{
name: "@electron-forge/maker-squirrel",
config: {
name: "jspaint",
exe: "jspaint.exe",
title: "JS Paint",
description: "MS Paint clone with extra features",
iconUrl: "https://raw.githubusercontent.com/1j01/jspaint/5af996478e28a32627794526ec9d25a799187119/images/icons/192x192.png",
setupIcon: "./images/icons/jspaint.ico",
loadingGif: "images/about/flagani.gif",
},
},
{
name: "@electron-forge/maker-zip",
platforms: [
"darwin", // macOS uses a .zip, which may be automatically extracted when opened
],
},
{
name: "@electron-forge/maker-deb",
config: {
options: {
...sharedDebRpmOptions,
section: "graphics",
maintainer: "Isaiah Odhner <isaiahodhner@gmail.com>",
},
},
},
{
name: "@electron-forge/maker-rpm",
config: {
options: {
...sharedDebRpmOptions,
license: "MIT",
},
},
},
],
publishers: [
{
name: "@electron-forge/publisher-github",
config: {
repository: {
owner: "1j01",
name: "jspaint",
},
prerelease: true,
draft: true,
},
},
],
};
================================================
FILE: help/coUA.css
================================================
/* Originally: Cascading Style Sheet for IE4.01 last updated 1-28-98 */
/* for scrollbars and selection color */
@import "../lib/os-gui/build/windows-98.css";
body {
background: #FFFFFF;
/* background: var(--Info); */
/* color: var(--InfoText); */
color: var(--WindowText);
font-size: 70%;
font-family: Verdana, Arial, Helvetica, "MS Sans Serif";
}
a:link {
color: #0000CC;
color: var(--HotTrackingColor);
}
a:active {
color: #996699;
}
a:visited {
color: #996699;
}
p {
margin-top: .6em;
margin-bottom: .6em;
}
p.bigfix {
margin-top: -.4em;
margin-bottom: 0em;
}
p.margin {
/* for SMS links */
margin-left: 2em;
margin-top: -1.75em;
}
p.K2 {
margin-top: 0em;
margin-left: 10pt;
}
/* HEADING TAGS */
h1 {
font-size: 145%;
margin-bottom: .5em;
}
h2 {
font-size: 125%;
margin-top: 1.5em;
margin-bottom: .5em;
}
h3 {
font-size: 110%;
margin-top: 1.2em;
margin-bottom: .5em;
}
h4 {
font-size: 105%;
margin-top: 1.2em;
margin-bottom: .5em;
}
h5 {
font-size: 100%;
margin-top: 1.2em;
margin-bottom: .5em;
}
big {
font-weight: bold;
font-size: 105%;
}
p.proclabel {
/* procedure heading */
font-weight: bold;
font-size: 100%;
margin-top: 1.2em;
}
/* LIST TAGS */
ol {
margin-top: .6em;
margin-bottom: 0em;
margin-left: 4em; /* @FIXME */
}
ul {
margin-top: .6em;
margin-bottom: 0em;
}
ol ul {
list-style: disc;
margin-top: .6em;
}
ul ul {
list-style: disc;
}
li {
margin-bottom: .7em;
margin-left: -2em;
}
/* TERM AND DEFINITION TAGS */
dl {
margin-top: 0em;
}
dt {
font-weight: bold;
margin-top: 1em;
/* margin-left: 0em; */ /* for SMS terms */
margin-left: 1.5em;
}
dd {
margin-bottom: 0em;
/*not currently working*/
margin-left: 1.5em;
}
dl li {
margin-bottom: .7em;
} /*list item inside a term/def list*/
dl dl {
margin-top: 0em;
margin-left: 0em;
} /*term/def list inside a term/def list*/
/* TABLE TAGS */
table {
font-size: 100%;
margin-top: 1em;
margin-bottom: 1em;
}
th {
text-align: left;
vertical-align: bottom;
background: #dddddd;
}
th.center {
text-align: center;
}
tr {
vertical-align: top;
}
td {
/* not used for K2 */
vertical-align: top;
background: #eeeeee;
}
/* MISC. TAGS */
pre {
font-family: Courier;
font-size: 125%;
margin-top: 1.2em;
margin-bottom: 1.5em;
}
code {
font-family: Courier;
font-size: 125%;
}
pre code {
font-size: 100%;
}
hr.sms {
/* SMS specific rule used under procedure title */
color: black;
text-align: left;
}
hr.iis {
/* IIS specific - preceding copyright */
color: black;
}
================================================
FILE: help/default.html
================================================
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<title>Welcome to Help</title>
<link href="nobgcolor.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="background-animation"></div>
<hr id="os-logo-colorbar">
<div id="foreground-contents">
<a href="https://98.js.org/" target="_blank" id="os-logo-link">
<img src="../images/98.js.org.svg" alt="98.js.org" id="os-logo" height="100">
</a>
<br>
<p><font size="2"><b>Welcome to Help</b></font></p>
<p>Use the Help system to learn more about <a href="https://98.js.org/" target="_blank">98.js.org</a> and JS Paint.</p>
<ul>
<li>Find answers to your questions.</li>
<li><strike>Browse the online version of the <i>Getting Started</i> book.</strike></li>
<li><strike>Connect to the Web to get software updates.</strike></li>
<li><strike>Troubleshoot your system.</strike></li>
</ul>
<br>
<br>
<br>
<br>
<br>
<br>
<p><a href="memcopy.html">Original documentation © 1998 Microsoft Corporation, all rights reserved.</a></p>
</div>
<script src="vaporwave.js"></script>
</body>
</html>
================================================
FILE: help/memcopy.html
================================================
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<title>Legal Information</title>
<link href="coUA.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1 id="LegalInformation">Legal Information</h1>
<p><strong>Microsoft Windows 98</strong></p>
<p>Information in this document is subject to change without notice. The names of companies, products, people, characters, and/or data mentioned herein are fictitious and are in no way intended to represent any real individual, company, product, or event, unless otherwise noted. Complying with all applicable copyright laws is the responsibility of the user. No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose, without the express written permission of Microsoft Corporation.</p>
<p>Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.</p>
<p>© 1998 Microsoft Corporation. All rights reserved.</p>
<p>Microsoft, ActiveX, BackOffice, MS, MS-DOS, MSN, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the U.S.A. and/or other countries.</p>
<p>Other product and company names mentioned herein may be the trademarks of their respective owners.</p>
</body>
</html>
================================================
FILE: help/mspaint.hhc
================================================
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.00">
<!-- Sitemap 1.0 -->
</HEAD><BODY>
<OBJECT type="text/site properties">
<param name="Window Styles" value="0x800624">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Drawing Lines and Shapes">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw a straight line ">
<param name="Local" value="paint_lines.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw a free-form line ">
<param name="Local" value="paint_freeform_lines.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw a curved line">
<param name="Local" value="paint_curves.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw an ellipse or circle ">
<param name="Local" value="paint_ovals.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw a rectangle or square ">
<param name="Local" value="paint_rectangles.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Draw a polygon ">
<param name="Local" value="paint_polygons.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Putting Text in Pictures">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Type and format text ">
<param name="Local" value="paint_text.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Working with Color">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Set the default foreground and background colors">
<param name="Local" value="paint_set_default_colors.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Fill an area with color ">
<param name="Local" value="paint_fill.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Paint with a brush ">
<param name="Local" value="paint_brush.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Create an airbrush effect ">
<param name="Local" value="paint_airbrush.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Create custom colors ">
<param name="Local" value="paint_custom_colors.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Use black and white instead of color ">
<param name="Local" value="paint_blackwhite.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Invert all the colors in a picture ">
<param name="Local" value="paint_invert.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Change the color of an existing line ">
<param name="Local" value="paint_change_color.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Copy color from one area or object to another ">
<param name="Local" value="paint_not_in_color_box.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Erasing">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Erase a small area">
<param name="Local" value="paint_erase_small.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Erase a large area">
<param name="Local" value="paint_erase_large.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Erase an entire image">
<param name="Local" value="paint_clear_image.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Undo changes ">
<param name="Local" value="paint_undo.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Working with Part of the Picture">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Select part of a picture ">
<param name="Local" value="paint_cutout_select.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Copy and paste part of a picture">
<param name="Local" value="paint_cutout_copy_move.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Save part of a picture into a bitmap file ">
<param name="Local" value="paint_cutout_save.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Changing How Your Picture Looks on the Screen">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Change the size of your picture">
<param name="Local" value="paint_change_size.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Zoom in or out ">
<param name="Local" value="paint_zoom.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Enlarge the size of the viewing area">
<param name="Local" value="paint_enlarge_area.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Display gridlines ">
<param name="Local" value="paint_grid.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Flip or rotate a picture ">
<param name="Local" value="paint_flip_picture.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Stretch or skew an item">
<param name="Local" value="paint_skew_picture.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Printing">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Print a picture ">
<param name="Local" value="paint_print.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Using Paint with Other Programs">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Insert a bitmap file into the current picture">
<param name="Local" value="paint_insert_file.html">
</OBJECT>
</UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Tips and Tricks">
</OBJECT>
<UL>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Use a picture as your desktop background ">
<param name="Local" value="paint_wallpaper.html">
</OBJECT>
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Display the tool box">
<param name="Local" value="paint_toolbox.html">
</OBJECT>
</UL>
</UL>
</BODY></HTML>
================================================
FILE: help/mspaint.hhk
================================================
<HTML>
<HEAD>
<!-- Sitemap 1.0 -->
</HEAD>
<BODY>
<OBJECT type="text/site properties">
<param name="FrameName" value="current">
</OBJECT>
<UL>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="adding custom colors">
<param name="Name" value="To copy color from one area or object to another">
<param name="Local" value="paint_not_in_color_box.html">
<param name="Name" value="To create custom colors">
<param name="Local" value="paint_custom_colors.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="airbrush tool">
<param name="Name" value="To create an airbrush effect">
<param name="Local" value="paint_airbrush.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="angles">
<param name="Name" value="To draw a polygon">
<param name="Local" value="paint_polygons.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="arcs">
<param name="Name" value="To draw a curve">
<param name="Local" value="paint_curves.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="attributes">
<param name="Name" value="To change the size of your picture">
<param name="Local" value="paint_change_size.html">
<param name="Name" value="To use black and white instead of color">
<param name="Local" value="paint_blackwhite.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="background (desktop)">
<param name="Name" value="To use a picture as the desktop background">
<param name="Local" value="paint_wallpaper.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="background color">
<param name="Name" value="To set the default foreground and background colors">
<param name="Local" value="paint_set_default_colors.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="bitmap view">
<param name="Name" value="To enlarge the size of the viewing area">
<param name="Local" value="paint_enlarge_area.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="bitmaps">
<param name="Name" value="To insert a bitmap into the current picture">
<param name="Local" value="paint_insert_file.html">
<param name="Name" value="To use a picture as the desktop background">
<param name="Local" value="paint_wallpaper.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="black and white">
<param name="Name" value="To use black and white instead of color">
<param name="Local" value="paint_blackwhite.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="blank picture">
<param name="Name" value="To clear an entire image">
<param name="Local" value="paint_clear_image.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="borders">
<param name="Name" value="To change the color of an existing line">
<param name="Local" value="paint_change_color.html">
<param name="Name" value="To draw a polygon">
<param name="Local" value="paint_polygons.html">
<param name="Name" value="To draw a rectangle or square">
<param name="Local" value="paint_rectangles.html">
<param name="Name" value="To draw an ellipse or circle">
<param name="Local" value="paint_ovals.html">
<param name="Name" value="To fill an area or object with color">
<param name="Local" value="paint_fill.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="boxes">
<param name="Name" value="To draw a rectangle or square">
<param name="Local" value="paint_rectangles.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="brush">
<param name="Name" value="To paint with a brush">
<param name="Local" value="paint_brush.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="buttons, see tools">
<param name="See Also" value="tools">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="can of paint">
<param name="Name" value="To change the color of an existing line">
<param name="Local" value="paint_change_color.html">
<param name="Name" value="To fill an area or object with color">
<param name="Local" value="paint_fill.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="canceling actions">
<param name="Name" value="To undo changes">
<param name="Local" value="paint_undo.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="centered wallpaper">
<param name="Name" value="To use a picture as the desktop background">
<param name="Local" value="paint_wallpaper.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="centimeters">
<param name="Name" value="To change the size of your picture">
<param name="Local" value="paint_change_size.html">
</OBJECT>
<LI><OBJECT type="Text/sitemap">
<param name="Name" value="changes, undoing">
<param name="Name" value="To undo changes">
<par
gitextract_p5h0c0f0/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ ├── run-command-on-all-files.ahk │ └── settings.json ├── CHANGELOG.md ├── CNAME ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── TODO.md ├── about.html ├── browserconfig.xml ├── cspell.json ├── cypress/ │ ├── cypress-image-snapshot-viewer.js │ ├── fixtures/ │ │ └── example.json │ ├── integration/ │ │ ├── tool-tests.spec.js │ │ └── visual-tests.spec.js │ ├── plugins/ │ │ └── index.js │ └── support/ │ ├── commands.js │ └── index.js ├── cypress.json ├── discord-activity/ │ ├── .gitignore │ ├── README.md │ ├── package.json │ └── packages/ │ └── server/ │ ├── environment.d.ts │ ├── package.json │ ├── src/ │ │ ├── app.ts │ │ ├── shared/ │ │ │ └── hello.ts │ │ └── utils.ts │ └── tsconfig.json ├── eslint.config.mjs ├── forge.config.js ├── help/ │ ├── coUA.css │ ├── default.html │ ├── memcopy.html │ ├── mspaint.hhc │ ├── mspaint.hhk │ ├── nobgcolor.css │ ├── online_support.htm │ ├── paint_airbrush.html │ ├── paint_blackwhite.html │ ├── paint_brush.html │ ├── paint_change_color.html │ ├── paint_change_size.html │ ├── paint_clear_image.html │ ├── paint_color_box.html │ ├── paint_curves.html │ ├── paint_custom_colors.html │ ├── paint_cutout_copy_move.html │ ├── paint_cutout_save.html │ ├── paint_cutout_select.html │ ├── paint_enlarge_area.html │ ├── paint_erase_large.html │ ├── paint_erase_small.html │ ├── paint_fill.html │ ├── paint_flip_picture.html │ ├── paint_freeform_lines.html │ ├── paint_grid.html │ ├── paint_insert_file.html │ ├── paint_invert.html │ ├── paint_lines.html │ ├── paint_not_in_color_box.html │ ├── paint_ovals.html │ ├── paint_polygons.html │ ├── paint_print.html │ ├── paint_rectangles.html │ ├── paint_set_default_colors.html │ ├── paint_skew_picture.html │ ├── paint_text.html │ ├── paint_toolbox.html │ ├── paint_trans_opaque.html │ ├── paint_undo.html │ ├── paint_wallpaper.html │ ├── paint_zoom.html │ ├── prettify-html.ahk │ └── vaporwave.js ├── images/ │ ├── 88x31/ │ │ └── custom/ │ │ ├── pipe-strip-88x31-v0.psd │ │ ├── pipe-strip-88x31-v1.psd │ │ ├── pipe-strip-88x31-v2.psd │ │ ├── pipe-strip-88x31-v3.psd │ │ ├── pipe-strip-88x31-v4.psd │ │ └── turbo-encabulator-88x31-v0.psd │ ├── bubblegum/ │ │ ├── bubblegum-recess.psd │ │ ├── eye-gaze-pause-button.psd │ │ └── fill-with-color.psd │ ├── icons/ │ │ └── jspaint.icns │ └── modern/ │ └── cursors/ │ ├── airbrush-alt.cur │ ├── airbrush.cur │ ├── crosshair-large.cur │ ├── crosshair.cur │ ├── ew-resize-large.cur │ ├── ew-resize.cur │ ├── eye-dropper-large.cur │ ├── eye-dropper.cur │ ├── magnifier-large.cur │ ├── magnifier.cur │ ├── move-large-alt.cur │ ├── move-large.cur │ ├── move.cur │ ├── nesw-resize-large.cur │ ├── nesw-resize.cur │ ├── ns-resize-large.cur │ ├── ns-resize.cur │ ├── nwse-resize-large.cur │ ├── nwse-resize.cur │ ├── paint-bucket-large.cur │ ├── paint-bucket.cur │ ├── pencil-large.cur │ ├── pencil.cur │ ├── precise-large.cur │ ├── precise.cur │ ├── select-alt.cur │ ├── select-large-alt.cur │ ├── select-large.cur │ ├── select.cur │ ├── text-large.cur │ ├── text.cur │ ├── zoom-in-large.cur │ ├── zoom-in.cur │ ├── zoom-out-large.cur │ └── zoom-out.cur ├── index.html ├── jsconfig.json ├── lib/ │ ├── 98.css/ │ │ ├── 98.custom-build.css │ │ ├── 98.custom-build.rtl.css │ │ ├── 98.custom-src.css │ │ └── modified-build.js │ ├── FileSaver.js │ ├── UPNG.js │ ├── UTIF.js │ ├── anypalette-0.6.0.js │ ├── bmp.js │ ├── discord-embedded-app-sdk-v1.2.0-bundled-with-skypack.js │ ├── firebase.js │ ├── font-detective.js │ ├── gif.js/ │ │ ├── gif.js │ │ └── gif.worker.js │ ├── imagetracer_v1.2.5.js │ ├── os-gui/ │ │ ├── $Window.js │ │ ├── MenuBar.js │ │ ├── build/ │ │ │ ├── blue.css │ │ │ ├── layout.css │ │ │ ├── layout.rtl.css │ │ │ ├── peggys-pastels.css │ │ │ ├── windows-98.css │ │ │ └── windows-default.css │ │ ├── os-gui.d.ts │ │ └── parse-theme.js │ ├── os-gui.patch │ ├── pdf.js/ │ │ ├── LICENSE │ │ ├── build/ │ │ │ ├── pdf.js │ │ │ ├── pdf.sandbox.js │ │ │ └── pdf.worker.js │ │ └── web/ │ │ ├── cmaps/ │ │ │ ├── 78-EUC-H.bcmap │ │ │ ├── 78-EUC-V.bcmap │ │ │ ├── 78-H.bcmap │ │ │ ├── 78-RKSJ-H.bcmap │ │ │ ├── 78-RKSJ-V.bcmap │ │ │ ├── 78-V.bcmap │ │ │ ├── 78ms-RKSJ-H.bcmap │ │ │ ├── 78ms-RKSJ-V.bcmap │ │ │ ├── 83pv-RKSJ-H.bcmap │ │ │ ├── 90ms-RKSJ-H.bcmap │ │ │ ├── 90ms-RKSJ-V.bcmap │ │ │ ├── 90msp-RKSJ-H.bcmap │ │ │ ├── 90msp-RKSJ-V.bcmap │ │ │ ├── 90pv-RKSJ-H.bcmap │ │ │ ├── 90pv-RKSJ-V.bcmap │ │ │ ├── Add-H.bcmap │ │ │ ├── Add-RKSJ-H.bcmap │ │ │ ├── Add-RKSJ-V.bcmap │ │ │ ├── Add-V.bcmap │ │ │ ├── Adobe-CNS1-0.bcmap │ │ │ ├── Adobe-CNS1-1.bcmap │ │ │ ├── Adobe-CNS1-2.bcmap │ │ │ ├── Adobe-CNS1-3.bcmap │ │ │ ├── Adobe-CNS1-4.bcmap │ │ │ ├── Adobe-CNS1-5.bcmap │ │ │ ├── Adobe-CNS1-6.bcmap │ │ │ ├── Adobe-CNS1-UCS2.bcmap │ │ │ ├── Adobe-GB1-0.bcmap │ │ │ ├── Adobe-GB1-1.bcmap │ │ │ ├── Adobe-GB1-2.bcmap │ │ │ ├── Adobe-GB1-3.bcmap │ │ │ ├── Adobe-GB1-4.bcmap │ │ │ ├── Adobe-GB1-5.bcmap │ │ │ ├── Adobe-GB1-UCS2.bcmap │ │ │ ├── Adobe-Japan1-0.bcmap │ │ │ ├── Adobe-Japan1-1.bcmap │ │ │ ├── Adobe-Japan1-2.bcmap │ │ │ ├── Adobe-Japan1-3.bcmap │ │ │ ├── Adobe-Japan1-4.bcmap │ │ │ ├── Adobe-Japan1-5.bcmap │ │ │ ├── Adobe-Japan1-6.bcmap │ │ │ ├── Adobe-Japan1-UCS2.bcmap │ │ │ ├── Adobe-Korea1-0.bcmap │ │ │ ├── Adobe-Korea1-1.bcmap │ │ │ ├── Adobe-Korea1-2.bcmap │ │ │ ├── Adobe-Korea1-UCS2.bcmap │ │ │ ├── B5-H.bcmap │ │ │ ├── B5-V.bcmap │ │ │ ├── B5pc-H.bcmap │ │ │ ├── B5pc-V.bcmap │ │ │ ├── CNS-EUC-H.bcmap │ │ │ ├── CNS-EUC-V.bcmap │ │ │ ├── CNS1-H.bcmap │ │ │ ├── CNS1-V.bcmap │ │ │ ├── CNS2-H.bcmap │ │ │ ├── CNS2-V.bcmap │ │ │ ├── ETHK-B5-H.bcmap │ │ │ ├── ETHK-B5-V.bcmap │ │ │ ├── ETen-B5-H.bcmap │ │ │ ├── ETen-B5-V.bcmap │ │ │ ├── ETenms-B5-H.bcmap │ │ │ ├── ETenms-B5-V.bcmap │ │ │ ├── EUC-H.bcmap │ │ │ ├── EUC-V.bcmap │ │ │ ├── Ext-H.bcmap │ │ │ ├── Ext-RKSJ-H.bcmap │ │ │ ├── Ext-RKSJ-V.bcmap │ │ │ ├── Ext-V.bcmap │ │ │ ├── GB-EUC-H.bcmap │ │ │ ├── GB-EUC-V.bcmap │ │ │ ├── GB-H.bcmap │ │ │ ├── GB-V.bcmap │ │ │ ├── GBK-EUC-H.bcmap │ │ │ ├── GBK-EUC-V.bcmap │ │ │ ├── GBK2K-H.bcmap │ │ │ ├── GBK2K-V.bcmap │ │ │ ├── GBKp-EUC-H.bcmap │ │ │ ├── GBKp-EUC-V.bcmap │ │ │ ├── GBT-EUC-H.bcmap │ │ │ ├── GBT-EUC-V.bcmap │ │ │ ├── GBT-H.bcmap │ │ │ ├── GBT-V.bcmap │ │ │ ├── GBTpc-EUC-H.bcmap │ │ │ ├── GBTpc-EUC-V.bcmap │ │ │ ├── GBpc-EUC-H.bcmap │ │ │ ├── GBpc-EUC-V.bcmap │ │ │ ├── H.bcmap │ │ │ ├── HKdla-B5-H.bcmap │ │ │ ├── HKdla-B5-V.bcmap │ │ │ ├── HKdlb-B5-H.bcmap │ │ │ ├── HKdlb-B5-V.bcmap │ │ │ ├── HKgccs-B5-H.bcmap │ │ │ ├── HKgccs-B5-V.bcmap │ │ │ ├── HKm314-B5-H.bcmap │ │ │ ├── HKm314-B5-V.bcmap │ │ │ ├── HKm471-B5-H.bcmap │ │ │ ├── HKm471-B5-V.bcmap │ │ │ ├── HKscs-B5-H.bcmap │ │ │ ├── HKscs-B5-V.bcmap │ │ │ ├── Hankaku.bcmap │ │ │ ├── Hiragana.bcmap │ │ │ ├── KSC-EUC-H.bcmap │ │ │ ├── KSC-EUC-V.bcmap │ │ │ ├── KSC-H.bcmap │ │ │ ├── KSC-Johab-H.bcmap │ │ │ ├── KSC-Johab-V.bcmap │ │ │ ├── KSC-V.bcmap │ │ │ ├── KSCms-UHC-H.bcmap │ │ │ ├── KSCms-UHC-HW-H.bcmap │ │ │ ├── KSCms-UHC-HW-V.bcmap │ │ │ ├── KSCms-UHC-V.bcmap │ │ │ ├── KSCpc-EUC-H.bcmap │ │ │ ├── KSCpc-EUC-V.bcmap │ │ │ ├── Katakana.bcmap │ │ │ ├── LICENSE │ │ │ ├── NWP-H.bcmap │ │ │ ├── NWP-V.bcmap │ │ │ ├── RKSJ-H.bcmap │ │ │ ├── RKSJ-V.bcmap │ │ │ ├── Roman.bcmap │ │ │ ├── UniCNS-UCS2-H.bcmap │ │ │ ├── UniCNS-UCS2-V.bcmap │ │ │ ├── UniCNS-UTF16-H.bcmap │ │ │ ├── UniCNS-UTF16-V.bcmap │ │ │ ├── UniCNS-UTF32-H.bcmap │ │ │ ├── UniCNS-UTF32-V.bcmap │ │ │ ├── UniCNS-UTF8-H.bcmap │ │ │ ├── UniCNS-UTF8-V.bcmap │ │ │ ├── UniGB-UCS2-H.bcmap │ │ │ ├── UniGB-UCS2-V.bcmap │ │ │ ├── UniGB-UTF16-H.bcmap │ │ │ ├── UniGB-UTF16-V.bcmap │ │ │ ├── UniGB-UTF32-H.bcmap │ │ │ ├── UniGB-UTF32-V.bcmap │ │ │ ├── UniGB-UTF8-H.bcmap │ │ │ ├── UniGB-UTF8-V.bcmap │ │ │ ├── UniJIS-UCS2-H.bcmap │ │ │ ├── UniJIS-UCS2-HW-H.bcmap │ │ │ ├── UniJIS-UCS2-HW-V.bcmap │ │ │ ├── UniJIS-UCS2-V.bcmap │ │ │ ├── UniJIS-UTF16-H.bcmap │ │ │ ├── UniJIS-UTF16-V.bcmap │ │ │ ├── UniJIS-UTF32-H.bcmap │ │ │ ├── UniJIS-UTF32-V.bcmap │ │ │ ├── UniJIS-UTF8-H.bcmap │ │ │ ├── UniJIS-UTF8-V.bcmap │ │ │ ├── UniJIS2004-UTF16-H.bcmap │ │ │ ├── UniJIS2004-UTF16-V.bcmap │ │ │ ├── UniJIS2004-UTF32-H.bcmap │ │ │ ├── UniJIS2004-UTF32-V.bcmap │ │ │ ├── UniJIS2004-UTF8-H.bcmap │ │ │ ├── UniJIS2004-UTF8-V.bcmap │ │ │ ├── UniJISPro-UCS2-HW-V.bcmap │ │ │ ├── UniJISPro-UCS2-V.bcmap │ │ │ ├── UniJISPro-UTF8-V.bcmap │ │ │ ├── UniJISX0213-UTF32-H.bcmap │ │ │ ├── UniJISX0213-UTF32-V.bcmap │ │ │ ├── UniJISX02132004-UTF32-H.bcmap │ │ │ ├── UniJISX02132004-UTF32-V.bcmap │ │ │ ├── UniKS-UCS2-H.bcmap │ │ │ ├── UniKS-UCS2-V.bcmap │ │ │ ├── UniKS-UTF16-H.bcmap │ │ │ ├── UniKS-UTF16-V.bcmap │ │ │ ├── UniKS-UTF32-H.bcmap │ │ │ ├── UniKS-UTF32-V.bcmap │ │ │ ├── UniKS-UTF8-H.bcmap │ │ │ ├── UniKS-UTF8-V.bcmap │ │ │ ├── V.bcmap │ │ │ └── WP-Symbol.bcmap │ │ ├── debugger.js │ │ ├── images/ │ │ │ ├── grab.cur │ │ │ └── grabbing.cur │ │ ├── locale/ │ │ │ ├── ach/ │ │ │ │ └── viewer.properties │ │ │ ├── af/ │ │ │ │ └── viewer.properties │ │ │ ├── an/ │ │ │ │ └── viewer.properties │ │ │ ├── ar/ │ │ │ │ └── viewer.properties │ │ │ ├── ast/ │ │ │ │ └── viewer.properties │ │ │ ├── az/ │ │ │ │ └── viewer.properties │ │ │ ├── be/ │ │ │ │ └── viewer.properties │ │ │ ├── bg/ │ │ │ │ └── viewer.properties │ │ │ ├── bn/ │ │ │ │ └── viewer.properties │ │ │ ├── bo/ │ │ │ │ └── viewer.properties │ │ │ ├── br/ │ │ │ │ └── viewer.properties │ │ │ ├── brx/ │ │ │ │ └── viewer.properties │ │ │ ├── bs/ │ │ │ │ └── viewer.properties │ │ │ ├── ca/ │ │ │ │ └── viewer.properties │ │ │ ├── cak/ │ │ │ │ └── viewer.properties │ │ │ ├── ckb/ │ │ │ │ └── viewer.properties │ │ │ ├── cs/ │ │ │ │ └── viewer.properties │ │ │ ├── cy/ │ │ │ │ └── viewer.properties │ │ │ ├── da/ │ │ │ │ └── viewer.properties │ │ │ ├── de/ │ │ │ │ └── viewer.properties │ │ │ ├── dsb/ │ │ │ │ └── viewer.properties │ │ │ ├── el/ │ │ │ │ └── viewer.properties │ │ │ ├── en-CA/ │ │ │ │ └── viewer.properties │ │ │ ├── en-GB/ │ │ │ │ └── viewer.properties │ │ │ ├── en-US/ │ │ │ │ └── viewer.properties │ │ │ ├── eo/ │ │ │ │ └── viewer.properties │ │ │ ├── es-AR/ │ │ │ │ └── viewer.properties │ │ │ ├── es-CL/ │ │ │ │ └── viewer.properties │ │ │ ├── es-ES/ │ │ │ │ └── viewer.properties │ │ │ ├── es-MX/ │ │ │ │ └── viewer.properties │ │ │ ├── et/ │ │ │ │ └── viewer.properties │ │ │ ├── eu/ │ │ │ │ └── viewer.properties │ │ │ ├── fa/ │ │ │ │ └── viewer.properties │ │ │ ├── ff/ │ │ │ │ └── viewer.properties │ │ │ ├── fi/ │ │ │ │ └── viewer.properties │ │ │ ├── fr/ │ │ │ │ └── viewer.properties │ │ │ ├── fy-NL/ │ │ │ │ └── viewer.properties │ │ │ ├── ga-IE/ │ │ │ │ └── viewer.properties │ │ │ ├── gd/ │ │ │ │ └── viewer.properties │ │ │ ├── gl/ │ │ │ │ └── viewer.properties │ │ │ ├── gn/ │ │ │ │ └── viewer.properties │ │ │ ├── gu-IN/ │ │ │ │ └── viewer.properties │ │ │ ├── he/ │ │ │ │ └── viewer.properties │ │ │ ├── hi-IN/ │ │ │ │ └── viewer.properties │ │ │ ├── hr/ │ │ │ │ └── viewer.properties │ │ │ ├── hsb/ │ │ │ │ └── viewer.properties │ │ │ ├── hu/ │ │ │ │ └── viewer.properties │ │ │ ├── hy-AM/ │ │ │ │ └── viewer.properties │ │ │ ├── hye/ │ │ │ │ └── viewer.properties │ │ │ ├── ia/ │ │ │ │ └── viewer.properties │ │ │ ├── id/ │ │ │ │ └── viewer.properties │ │ │ ├── is/ │ │ │ │ └── viewer.properties │ │ │ ├── it/ │ │ │ │ └── viewer.properties │ │ │ ├── ja/ │ │ │ │ └── viewer.properties │ │ │ ├── ka/ │ │ │ │ └── viewer.properties │ │ │ ├── kab/ │ │ │ │ └── viewer.properties │ │ │ ├── kk/ │ │ │ │ └── viewer.properties │ │ │ ├── km/ │ │ │ │ └── viewer.properties │ │ │ ├── kn/ │ │ │ │ └── viewer.properties │ │ │ ├── ko/ │ │ │ │ └── viewer.properties │ │ │ ├── lij/ │ │ │ │ └── viewer.properties │ │ │ ├── lo/ │ │ │ │ └── viewer.properties │ │ │ ├── locale.properties │ │ │ ├── lt/ │ │ │ │ └── viewer.properties │ │ │ ├── ltg/ │ │ │ │ └── viewer.properties │ │ │ ├── lv/ │ │ │ │ └── viewer.properties │ │ │ ├── meh/ │ │ │ │ └── viewer.properties │ │ │ ├── mk/ │ │ │ │ └── viewer.properties │ │ │ ├── mr/ │ │ │ │ └── viewer.properties │ │ │ ├── ms/ │ │ │ │ └── viewer.properties │ │ │ ├── my/ │ │ │ │ └── viewer.properties │ │ │ ├── nb-NO/ │ │ │ │ └── viewer.properties │ │ │ ├── ne-NP/ │ │ │ │ └── viewer.properties │ │ │ ├── nl/ │ │ │ │ └── viewer.properties │ │ │ ├── nn-NO/ │ │ │ │ └── viewer.properties │ │ │ ├── oc/ │ │ │ │ └── viewer.properties │ │ │ ├── pa-IN/ │ │ │ │ └── viewer.properties │ │ │ ├── pl/ │ │ │ │ └── viewer.properties │ │ │ ├── pt-BR/ │ │ │ │ └── viewer.properties │ │ │ ├── pt-PT/ │ │ │ │ └── viewer.properties │ │ │ ├── rm/ │ │ │ │ └── viewer.properties │ │ │ ├── ro/ │ │ │ │ └── viewer.properties │ │ │ ├── ru/ │ │ │ │ └── viewer.properties │ │ │ ├── scn/ │ │ │ │ └── viewer.properties │ │ │ ├── si/ │ │ │ │ └── viewer.properties │ │ │ ├── sk/ │ │ │ │ └── viewer.properties │ │ │ ├── sl/ │ │ │ │ └── viewer.properties │ │ │ ├── son/ │ │ │ │ └── viewer.properties │ │ │ ├── sq/ │ │ │ │ └── viewer.properties │ │ │ ├── sr/ │ │ │ │ └── viewer.properties │ │ │ ├── sv-SE/ │ │ │ │ └── viewer.properties │ │ │ ├── szl/ │ │ │ │ └── viewer.properties │ │ │ ├── ta/ │ │ │ │ └── viewer.properties │ │ │ ├── te/ │ │ │ │ └── viewer.properties │ │ │ ├── th/ │ │ │ │ └── viewer.properties │ │ │ ├── tl/ │ │ │ │ └── viewer.properties │ │ │ ├── tr/ │ │ │ │ └── viewer.properties │ │ │ ├── trs/ │ │ │ │ └── viewer.properties │ │ │ ├── uk/ │ │ │ │ └── viewer.properties │ │ │ ├── ur/ │ │ │ │ └── viewer.properties │ │ │ ├── uz/ │ │ │ │ └── viewer.properties │ │ │ ├── vi/ │ │ │ │ └── viewer.properties │ │ │ ├── wo/ │ │ │ │ └── viewer.properties │ │ │ ├── xh/ │ │ │ │ └── viewer.properties │ │ │ ├── zh-CN/ │ │ │ │ └── viewer.properties │ │ │ └── zh-TW/ │ │ │ └── viewer.properties │ │ ├── viewer.css │ │ ├── viewer.html │ │ └── viewer.js │ └── tracky-mouse/ │ ├── .gitattributes │ ├── .gitignore │ ├── .gitrepo │ ├── .vscode/ │ │ ├── extensions.json │ │ ├── launch.json │ │ └── settings.json │ ├── API.md │ ├── CHANGELOG.md │ ├── CLI.md │ ├── LICENSE.txt │ ├── README.md │ ├── core/ │ │ ├── README.md │ │ ├── facemesh.worker.js │ │ ├── lib/ │ │ │ ├── clmtrackr.js │ │ │ ├── facemesh/ │ │ │ │ ├── blazeface/ │ │ │ │ │ └── model.json │ │ │ │ ├── facemesh/ │ │ │ │ │ └── model.json │ │ │ │ └── facemesh.js │ │ │ ├── jsfeat-min.js │ │ │ ├── no-eval.js │ │ │ ├── stats.js │ │ │ └── tf.js │ │ ├── package.json │ │ ├── tracky-mouse.css │ │ └── tracky-mouse.js │ ├── cspell.json │ ├── desktop-app/ │ │ ├── forge.config.js │ │ ├── images/ │ │ │ └── tracky-mouse-logo.icns │ │ ├── package.json │ │ └── src/ │ │ ├── electron-app.html │ │ ├── electron-main/ │ │ │ ├── cli.js │ │ │ ├── electron-main.js │ │ │ ├── menus.js │ │ │ ├── spawner.js │ │ │ ├── squirrel-update.js │ │ │ ├── version.js │ │ │ └── win-powershell.js │ │ ├── electron-screen-overlay.html │ │ ├── preload-app-window.js │ │ ├── preload-screen-overlay.js │ │ ├── screen-overlay.css │ │ ├── screen-overlay.js │ │ └── tracky-mouse-bin.js │ ├── eslint.config.js │ ├── images/ │ │ ├── tracky-mouse-logo.blend │ │ └── tracky-mouse-logo.icns │ ├── package.json │ └── website/ │ ├── CNAME │ ├── demo.js │ ├── eval-is-evil.html │ ├── index.html │ ├── package.json │ └── tracky-mouse-homepage.css ├── localization/ │ ├── ar/ │ │ ├── Dialog/ │ │ │ └── 0401/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0401/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0401/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── cs/ │ │ ├── Dialog/ │ │ │ └── 0405/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0405/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0405/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── da/ │ │ ├── Dialog/ │ │ │ └── 0406/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0406/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0406/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── de/ │ │ ├── Dialog/ │ │ │ └── 0407/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0407/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0407/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── el/ │ │ ├── Dialog/ │ │ │ └── 0408/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0408/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0408/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── en/ │ │ ├── Dialog/ │ │ │ └── 0409/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0409/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ └── String Table/ │ │ └── 0409/ │ │ ├── 1.rc │ │ ├── 129.rc │ │ ├── 130.rc │ │ ├── 131.rc │ │ ├── 132.rc │ │ ├── 135.rc │ │ ├── 139.rc │ │ ├── 141.rc │ │ ├── 144.rc │ │ ├── 145.rc │ │ ├── 153.rc │ │ ├── 2.rc │ │ ├── 2049.rc │ │ ├── 2050.rc │ │ ├── 222.rc │ │ ├── 2354.rc │ │ ├── 2355.rc │ │ ├── 2356.rc │ │ ├── 2610.rc │ │ ├── 2628.rc │ │ ├── 2753.rc │ │ ├── 2757.rc │ │ ├── 2758.rc │ │ ├── 2765.rc │ │ ├── 2794.rc │ │ ├── 3.rc │ │ ├── 3585.rc │ │ ├── 3601.rc │ │ ├── 3602.rc │ │ ├── 3603.rc │ │ ├── 3605.rc │ │ ├── 3606.rc │ │ ├── 3713.rc │ │ ├── 3714.rc │ │ ├── 3825.rc │ │ ├── 3826.rc │ │ ├── 3841.rc │ │ ├── 3842.rc │ │ ├── 3843.rc │ │ ├── 3845.rc │ │ ├── 3849.rc │ │ ├── 3850.rc │ │ ├── 3857.rc │ │ ├── 3858.rc │ │ ├── 3859.rc │ │ ├── 3865.rc │ │ ├── 3866.rc │ │ ├── 3867.rc │ │ ├── 3868.rc │ │ ├── 3869.rc │ │ ├── 39.rc │ │ ├── 40.rc │ │ ├── 41.rc │ │ ├── 430.rc │ │ ├── 442.rc │ │ ├── 578.rc │ │ ├── 626.rc │ │ ├── 63.rc │ │ └── 7.rc │ ├── es/ │ │ ├── Dialog/ │ │ │ └── 0C0A/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0C0A/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0C0A/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── fi/ │ │ ├── Dialog/ │ │ │ └── 040B/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 040B/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 040B/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── fr/ │ │ ├── Dialog/ │ │ │ └── 040C/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 040C/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 040C/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── grab-files-from-vm.sh │ ├── he/ │ │ ├── Dialog/ │ │ │ └── 040D/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 040D/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 040D/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── hu/ │ │ ├── Dialog/ │ │ │ └── 040E/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 040E/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 040E/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── install-windows-98.sh │ ├── it/ │ │ ├── Dialog/ │ │ │ └── 0410/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0410/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0410/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── ja/ │ │ ├── Dialog/ │ │ │ └── 0411/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0411/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0411/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── ko/ │ │ ├── Dialog/ │ │ │ └── 0412/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0412/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0412/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── nl/ │ │ ├── Dialog/ │ │ │ └── 0413/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0413/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0413/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── no/ │ │ ├── Dialog/ │ │ │ └── 0414/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0414/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0414/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── parse-rc-file.js │ ├── pl/ │ │ ├── Dialog/ │ │ │ └── 0415/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0415/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0415/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── preprocess.js │ ├── pt/ │ │ ├── Dialog/ │ │ │ └── 0816/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0816/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0816/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── pt-br/ │ │ ├── Dialog/ │ │ │ └── 0416/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0416/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0416/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── ru/ │ │ ├── Dialog/ │ │ │ └── 0419/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0419/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0419/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── sk/ │ │ ├── Dialog/ │ │ │ └── 041B/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 041B/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 041B/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── sl/ │ │ ├── Dialog/ │ │ │ └── 0424/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0424/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0424/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── sv/ │ │ ├── Dialog/ │ │ │ └── 041D/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 041D/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 041D/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── tr/ │ │ ├── Dialog/ │ │ │ └── 041F/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 041F/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 041F/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ ├── zh/ │ │ ├── Dialog/ │ │ │ └── 0404/ │ │ │ ├── 105.rc │ │ │ ├── 108.rc │ │ │ ├── 112.rc │ │ │ ├── 113.rc │ │ │ ├── 132.rc │ │ │ ├── 30721.rc │ │ │ ├── 30722.rc │ │ │ ├── 30723.rc │ │ │ ├── 37.rc │ │ │ └── 4001.rc │ │ ├── Menu/ │ │ │ └── 0404/ │ │ │ ├── 113.rc │ │ │ ├── 118.rc │ │ │ ├── 119.rc │ │ │ ├── 2.rc │ │ │ ├── 4.rc │ │ │ └── 5.rc │ │ ├── String Table/ │ │ │ └── 0404/ │ │ │ ├── 1.rc │ │ │ ├── 129.rc │ │ │ ├── 130.rc │ │ │ ├── 131.rc │ │ │ ├── 132.rc │ │ │ ├── 135.rc │ │ │ ├── 139.rc │ │ │ ├── 141.rc │ │ │ ├── 144.rc │ │ │ ├── 145.rc │ │ │ ├── 153.rc │ │ │ ├── 2.rc │ │ │ ├── 2049.rc │ │ │ ├── 2050.rc │ │ │ ├── 222.rc │ │ │ ├── 2354.rc │ │ │ ├── 2355.rc │ │ │ ├── 2356.rc │ │ │ ├── 2610.rc │ │ │ ├── 2628.rc │ │ │ ├── 2753.rc │ │ │ ├── 2757.rc │ │ │ ├── 2758.rc │ │ │ ├── 2765.rc │ │ │ ├── 2794.rc │ │ │ ├── 3.rc │ │ │ ├── 3585.rc │ │ │ ├── 3601.rc │ │ │ ├── 3602.rc │ │ │ ├── 3603.rc │ │ │ ├── 3605.rc │ │ │ ├── 3606.rc │ │ │ ├── 3713.rc │ │ │ ├── 3714.rc │ │ │ ├── 3825.rc │ │ │ ├── 3826.rc │ │ │ ├── 3841.rc │ │ │ ├── 3842.rc │ │ │ ├── 3843.rc │ │ │ ├── 3845.rc │ │ │ ├── 3849.rc │ │ │ ├── 3850.rc │ │ │ ├── 3857.rc │ │ │ ├── 3858.rc │ │ │ ├── 3859.rc │ │ │ ├── 3865.rc │ │ │ ├── 3866.rc │ │ │ ├── 3867.rc │ │ │ ├── 3868.rc │ │ │ ├── 3869.rc │ │ │ ├── 39.rc │ │ │ ├── 40.rc │ │ │ ├── 41.rc │ │ │ ├── 430.rc │ │ │ ├── 442.rc │ │ │ ├── 578.rc │ │ │ ├── 626.rc │ │ │ ├── 63.rc │ │ │ └── 7.rc │ │ └── localizations.js │ └── zh-simplified/ │ ├── Dialog/ │ │ └── 0804/ │ │ ├── 105.rc │ │ ├── 108.rc │ │ ├── 112.rc │ │ ├── 113.rc │ │ ├── 132.rc │ │ ├── 30721.rc │ │ ├── 30722.rc │ │ ├── 30723.rc │ │ ├── 37.rc │ │ └── 4001.rc │ ├── Menu/ │ │ └── 0804/ │ │ ├── 113.rc │ │ ├── 118.rc │ │ ├── 119.rc │ │ ├── 2.rc │ │ ├── 4.rc │ │ └── 5.rc │ ├── String Table/ │ │ └── 0804/ │ │ ├── 1.rc │ │ ├── 129.rc │ │ ├── 130.rc │ │ ├── 131.rc │ │ ├── 132.rc │ │ ├── 135.rc │ │ ├── 139.rc │ │ ├── 141.rc │ │ ├── 144.rc │ │ ├── 145.rc │ │ ├── 153.rc │ │ ├── 2.rc │ │ ├── 2049.rc │ │ ├── 2050.rc │ │ ├── 222.rc │ │ ├── 2354.rc │ │ ├── 2355.rc │ │ ├── 2356.rc │ │ ├── 2610.rc │ │ ├── 2628.rc │ │ ├── 2753.rc │ │ ├── 2757.rc │ │ ├── 2758.rc │ │ ├── 2765.rc │ │ ├── 2794.rc │ │ ├── 3.rc │ │ ├── 3585.rc │ │ ├── 3601.rc │ │ ├── 3602.rc │ │ ├── 3603.rc │ │ ├── 3605.rc │ │ ├── 3606.rc │ │ ├── 3713.rc │ │ ├── 3714.rc │ │ ├── 3825.rc │ │ ├── 3826.rc │ │ ├── 3841.rc │ │ ├── 3842.rc │ │ ├── 3843.rc │ │ ├── 3845.rc │ │ ├── 3849.rc │ │ ├── 3850.rc │ │ ├── 3857.rc │ │ ├── 3858.rc │ │ ├── 3859.rc │ │ ├── 3865.rc │ │ ├── 3866.rc │ │ ├── 3867.rc │ │ ├── 3868.rc │ │ ├── 3869.rc │ │ ├── 39.rc │ │ ├── 40.rc │ │ ├── 41.rc │ │ ├── 430.rc │ │ ├── 442.rc │ │ ├── 578.rc │ │ ├── 626.rc │ │ ├── 63.rc │ │ └── 7.rc │ └── localizations.js ├── manifest.webmanifest ├── package.json ├── privacy.html ├── prune-globals.js ├── src/ │ ├── $ColorBox.js │ ├── $Component.js │ ├── $FontBox.js │ ├── $ToolBox.js │ ├── $ToolWindow.js │ ├── Handles.js │ ├── OnCanvasHelperLayer.js │ ├── OnCanvasObject.js │ ├── OnCanvasSelection.js │ ├── OnCanvasTextBox.js │ ├── app-localization.js │ ├── app-state.js │ ├── app.js │ ├── color-data.js │ ├── copy-inkscape-labels.js │ ├── discord-activity-client.js │ ├── edit-colors.js │ ├── electron-injected.js │ ├── electron-main.js │ ├── error-handling-basic.js │ ├── error-handling-enhanced.js │ ├── extra-tools.js │ ├── eye-gaze-mode.js │ ├── file-format-data.js │ ├── functions.js │ ├── globals.d.ts │ ├── help.js │ ├── helpers.js │ ├── image-manipulation.js │ ├── imgur.js │ ├── konami.js │ ├── manage-storage.js │ ├── menus.js │ ├── msgbox.js │ ├── repack-spritesheet.js │ ├── save-history-as-spritesheet.js │ ├── sessions.js │ ├── simulate-random-gestures.js │ ├── speech-recognition.js │ ├── storage.js │ ├── test-news.js │ ├── theme.js │ ├── tool-options.js │ ├── tools.js │ └── vaporwave-fun.js ├── styles/ │ ├── about.css │ ├── layout.css │ ├── layout.rtl.css │ ├── legal.css │ ├── normalize.css │ ├── print.css │ └── themes/ │ ├── bubblegum.css │ ├── classic.css │ ├── dark.css │ ├── modern-dark.css │ ├── modern.css │ ├── occult.css │ ├── red-wine.css │ ├── vista-esque-midnight-green.css │ └── winter.css ├── svg-paint/ │ ├── index.html │ └── svg-paint.js ├── sync-package.js └── test-news-newer.html
Showing preview only (605K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8103 symbols across 72 files)
FILE: cypress/cypress-image-snapshot-viewer.js
function showDiffView (line 17) | function showDiffView(originalImg) {
FILE: discord-activity/packages/server/environment.d.ts
type ProcessEnv (line 3) | interface ProcessEnv {
FILE: discord-activity/packages/server/src/shared/hello.ts
function hello (line 1) | function hello() {
FILE: discord-activity/packages/server/src/utils.ts
function sleep (line 1) | function sleep(ms: number) {
function fetchAndRetry (line 9) | async function fetchAndRetry(
FILE: lib/98.css/modified-build.js
function buildCSS (line 13) | function buildCSS() {
function buildDocs (line 35) | function buildDocs() {
function build (line 74) | function build() {
FILE: lib/FileSaver.js
function bom (line 29) | function bom(blob, opts) {
function download (line 49) | function download(url, name, opts) {
function corsEnabled (line 65) | function corsEnabled(url) {
function click (line 78) | function click(node) {
FILE: lib/UPNG.js
function n (line 256) | function n(A,l,M){while(l--!=0)A.push(0,M)}
FILE: lib/UTIF.js
function log (line 14) | function log() { if (typeof process=="undefined" || process.env.NODE_ENV...
function W (line 19) | function W(p){this.message="JPEG error: "+p}
function ak (line 19) | function ak(Q){if(Q==null)Q={};if(Q.w==null)Q.w=-1;this.V=Q.n;this.N=Q.w}
function a5 (line 19) | function a5(Q,h){var f=0,G=[],n,E,a=16,F;while(a>0&&!Q[a-1]){a--}G.push(...
function a2 (line 20) | function a2(Q,h,f){return 64*((Q.P+1)*h+f)}
function a7 (line 20) | function a7(Q,h,f,G,n,E,a,C,F,d){if(d==null)d=!1;var T=f.m,U=f.Z,z=h,J=0...
function al (line 24) | function al(Q,h,f){var G=Q.$,n=Q.D,E,a,C,F,d,T,U,z,J,V,Y,u,m,j,v,$,b;if(...
function a0 (line 27) | function a0(Q,h){var f=h.P,G=h.c,n=new Int16Array(64);for(var E=0;E<G;E+...
function an (line 27) | function an(Q,h,f){if(f==null)f=h;var G=Q.length-1,n=f<h?f:h;if(h>=G){re...
method parse (line 27) | parse(Q,h){if(h==null)h={};
method Y (line 32) | Y(Q,h,f){if(f==null)f=!1;var G=this.width/Q,n=this.height/h,E,a,C,F,d,T,...
method f (line 32) | get f(){if(this.b){return!!this.b.a}if(this.p===3){if(this.N===0){return...
function a9 (line 37) | function a9(p,t){return p[t]<<24>>24}
function Z (line 37) | function Z(p,t){return p[t]<<8|p[t+1]}
function am (line 37) | function am(p,t){return(p[t]<<24|p[t+1]<<16|p[t+2]<<8|p[t+3])>>>0}
function A (line 211) | function A(B){var P=B[1],D=B[0][P>>>3]>>>7-(P&7)&1;B[1]++;return D}
function aj (line 211) | function aj(B,P){if(x==null){x={};
function Q (line 213) | function Q(B,P){for(var D=0;D<P;D++){if((B&1)==1)B++;B=B>>>1}return B}
function c (line 213) | function c(B,P){return B>>P}
function N (line 213) | function N(B,P,D,U,X,y){P[D]=c(c(11*B[X]-4*B[X+y]+B[X+y+y]+4,3)+B[U],1);
function g (line 214) | function g(B,P,D,U,X,y){var n=B[X-y]-B[X+y],S=B[X],O=B[U];
function L (line 215) | function L(B,P,D,U,X,y){P[D]=c(c(5*B[X]+4*B[X-y]-B[X-y-y]+4,3)+B[U],1);
function t (line 216) | function t(B){B=B<0?0:B>4095?4095:B;B=H[B]>>>2;return B}
function ab (line 216) | function ab(B,P,D,U,X){U=new Uint16Array(U.buffer);
function q (line 1196) | function q(){return y[D++]}
function a (line 1196) | function a(){return y[D++]<<8|y[D++]}
function b (line 1196) | function b(){var p=q(),r=[0,0,0,255],c=[],E=8;
function m (line 1199) | function m(p,r,c,z){if(p[r+3]!=255)return 0;if(c==0)return r;for(var G=0...
function B (line 1200) | function B(p){var r=p.e,c=p.c;
function g (line 1201) | function g(p,r){if(r.e<p)B(r);
function w (line 1202) | function w(p,r){var c=p[0],z=0,G=255,I=0;if(r.e<16)B(r);var E=r.c>>r.e-8...
function o (line 1203) | function o(p,r){if(p<32768>>16-r)p+=-(1<<r)+1;
function x (line 1204) | function x(p,r){var c=w(p,r);if(c==0)return 0;if(c==16)return-32768;var ...
function n (line 1204) | function n(p,r,c){var z=i,G=H,I=l,E=e;
function f (line 1209) | function f(p,r){return o(g(p,r),p)}
function d (line 1209) | function d(p,r,c){var z=y.length-D;
function h (line 1212) | function h(p){y=p;D=0;C=[],e=[];if(a()!=65496)throw"e";
function a4 (line 1220) | function a4($){var z=UTIF._binBE.readUshort,v={m:z($,0),f:$[2],r:$[3],a:...
function a6 (line 1222) | function a6($,z){var v=new Array(z.v),i=16+4*z.v;
function a7 (line 1224) | function a7($,z){for(var v=-z[4],i=0;v<=z[4];i++,v++){$[i]=v<=-z[3]?-4:v...
function a3 (line 1224) | function a3($,z,v){var i=[z,3*z+18,5*z+67,7*z+276,v];
function a1 (line 1225) | function a1($){var z={u:new Int8Array(2<<$.a)};
function N (line 1226) | function N($){var z=[[],[],[]],v=Math.max(2,$.i+32>>>6);for(var i=0;i<3;...
function a8 (line 1227) | function a8($){for(var z=-1,v=0;!v;z++){v=$[$.l]>>>7-$.s&1;$.s++;$.s&=7;
function R (line 1228) | function R($,z){var v=0,i=8-$.s,y=$.l,A=$.s;if(z){if(z>=i){do{v<<=i;z-=i...
function a2 (line 1229) | function a2($,z){var v=0;
function V (line 1230) | function V($,z,v,i,y,A,B,r){if(r==null)r=0;var W=A+1,o=W%2,J=0,K=0,f=0,E...
function S (line 1234) | function S($,z,v){var i=$[0].length;for(var y=z;y<=v;
function b (line 1235) | function b($){S($,l,U);S($,n,w);S($,Y,M)}
function m (line 1235) | function m($,z,v,i,y,A,B,r,W,o,J,K,f){var E=0,p=1,h=y<t&&y>w;
function a0 (line 1237) | function a0($,z,v,i,y,A){m($,z,v,i,n,l,y,A,0,0,1,0,8);
function a5 (line 1239) | function a5($,z,v,i,y,A){var B=A.length,r=$.n;if(y+1==$.v)r=$.h-y*$.n;va...
FILE: lib/anypalette-0.6.0.js
function r (line 112) | function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==...
function getLens (line 134) | function getLens (b64) {
function byteLength (line 154) | function byteLength (b64) {
function _byteLength (line 161) | function _byteLength (b64, validLen, placeHoldersLen) {
function toByteArray (line 165) | function toByteArray (b64) {
function tripletToBase64 (line 211) | function tripletToBase64 (num) {
function encodeChunk (line 218) | function encodeChunk (uint8, start, end) {
function fromByteArray (line 231) | function fromByteArray (uint8) {
function typedArraySupport (line 312) | function typedArraySupport () {
function createBuffer (line 339) | function createBuffer (length) {
function Buffer (line 359) | function Buffer (arg, encodingOrOffset, length) {
function from (line 385) | function from (value, encodingOrOffset, length) {
function assertSize (line 450) | function assertSize (size) {
function alloc (line 458) | function alloc (size, fill, encoding) {
function allocUnsafe (line 482) | function allocUnsafe (size) {
function fromString (line 500) | function fromString (string, encoding) {
function fromArrayLike (line 524) | function fromArrayLike (array) {
function fromArrayBuffer (line 533) | function fromArrayBuffer (array, byteOffset, length) {
function fromObject (line 556) | function fromObject (obj) {
function checked (line 581) | function checked (length) {
function SlowBuffer (line 591) | function SlowBuffer (length) {
function byteLength (line 682) | function byteLength (string, encoding) {
function slowToString (line 731) | function slowToString (encoding, start, end) {
function swap (line 809) | function swap (b, n, m) {
function bidirectionalIndexOf (line 949) | function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
function arrayIndexOf (line 1005) | function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
function hexWrite (line 1073) | function hexWrite (buf, string, offset, length) {
function utf8Write (line 1098) | function utf8Write (buf, string, offset, length) {
function asciiWrite (line 1102) | function asciiWrite (buf, string, offset, length) {
function latin1Write (line 1106) | function latin1Write (buf, string, offset, length) {
function base64Write (line 1110) | function base64Write (buf, string, offset, length) {
function ucs2Write (line 1114) | function ucs2Write (buf, string, offset, length) {
function base64Slice (line 1196) | function base64Slice (buf, start, end) {
function utf8Slice (line 1204) | function utf8Slice (buf, start, end) {
function decodeCodePointsArray (line 1282) | function decodeCodePointsArray (codePoints) {
function asciiSlice (line 1300) | function asciiSlice (buf, start, end) {
function latin1Slice (line 1310) | function latin1Slice (buf, start, end) {
function hexSlice (line 1320) | function hexSlice (buf, start, end) {
function utf16leSlice (line 1333) | function utf16leSlice (buf, start, end) {
function checkOffset (line 1372) | function checkOffset (offset, ext, length) {
function checkInt (line 1547) | function checkInt (buf, value, offset, ext, max, min) {
function checkIEEE754 (line 1735) | function checkIEEE754 (buf, value, offset, ext, max, min) {
function writeFloat (line 1740) | function writeFloat (buf, value, offset, littleEndian, noAssert) {
function writeDouble (line 1758) | function writeDouble (buf, value, offset, littleEndian, noAssert) {
function base64clean (line 1897) | function base64clean (str) {
function toHex (line 1911) | function toHex (n) {
function utf8ToBytes (line 1916) | function utf8ToBytes (string, units) {
function asciiToBytes (line 1996) | function asciiToBytes (str) {
function utf16leToBytes (line 2005) | function utf16leToBytes (str, units) {
function base64ToBytes (line 2021) | function base64ToBytes (str) {
function blitBuffer (line 2025) | function blitBuffer (src, dst, offset, length) {
function isInstance (line 2036) | function isInstance (obj, type) {
function numberIsNaN (line 2041) | function numberIsNaN (obj) {
function ProcessEmitWarning (line 2204) | function ProcessEmitWarning(warning) {
function EventEmitter (line 2212) | function EventEmitter() {
function checkListener (line 2229) | function checkListener(listener) {
function _getMaxListeners (line 2269) | function _getMaxListeners(that) {
function _addListener (line 2323) | function _addListener(target, type, listener, prepend) {
function onceWrapper (line 2396) | function onceWrapper() {
function _onceWrap (line 2406) | function _onceWrap(target, type, listener) {
function _listeners (line 2533) | function _listeners(target, type, unwrap) {
function listenerCount (line 2567) | function listenerCount(type) {
function arrayClone (line 2587) | function arrayClone(arr, n) {
function spliceOne (line 2594) | function spliceOne(list, index) {
function unwrapListeners (line 2600) | function unwrapListeners(arr) {
function once (line 2608) | function once(emitter, name) {
function is (line 2731) | function is(obj, Ctor) {
function arrayFrom (line 2734) | function arrayFrom(arrayLike, forceCopy) {
function defined (line 2737) | function defined(value, defaultValue) {
function jDataView (line 2740) | function jDataView(buffer, byteOffset, byteLength, littleEndian) {
function getCharCodes (line 2755) | function getCharCodes(string) {
function pow2 (line 2760) | function pow2(n) {
function Uint64 (line 2763) | function Uint64(lo, hi) {
function Int64 (line 2766) | function Int64() {
function normalizeOffset (line 2918) | function normalizeOffset(offset, byteLength) {
function defaultSetTimout (line 3081) | function defaultSetTimout() {
function defaultClearTimeout (line 3084) | function defaultClearTimeout () {
function runTimeout (line 3107) | function runTimeout(fun) {
function runClearTimeout (line 3132) | function runClearTimeout(marker) {
function cleanUpNextTick (line 3164) | function cleanUpNextTick() {
function drainQueue (line 3179) | function drainQueue() {
function Item (line 3217) | function Item(fun, array) {
function noop (line 3231) | function noop() {}
function copyProps (line 3261) | function copyProps (src, dst) {
function SafeBuffer (line 3274) | function SafeBuffer (arg, encodingOrOffset, length) {
function SAXParser (line 3365) | function SAXParser (strict, opt) {
function F (line 3404) | function F () {}
function checkBufferLength (line 3419) | function checkBufferLength (parser) {
function clearBuffers (line 3455) | function clearBuffers (parser) {
function flushBuffers (line 3461) | function flushBuffers (parser) {
function createStream (line 3492) | function createStream (strict, opt) {
function SAXStream (line 3496) | function SAXStream (strict, opt) {
function isWhitespace (line 3606) | function isWhitespace (c) {
function isQuote (line 3610) | function isQuote (c) {
function isAttribEnd (line 3614) | function isAttribEnd (c) {
function isMatch (line 3618) | function isMatch (regex, c) {
function notMatch (line 3622) | function notMatch (regex, c) {
function emit (line 3943) | function emit (parser, event, data) {
function emitNode (line 3947) | function emitNode (parser, nodeType, data) {
function closeText (line 3952) | function closeText (parser) {
function textopts (line 3958) | function textopts (opt, text) {
function error (line 3964) | function error (parser, er) {
function end (line 3977) | function end (parser) {
function strictFail (line 3992) | function strictFail (parser, message) {
function newTag (line 4001) | function newTag (parser) {
function qname (line 4014) | function qname (name, attribute) {
function attrib (line 4029) | function attrib (parser) {
function openTag (line 4081) | function openTag (parser, selfClosing) {
function closeTag (line 4160) | function closeTag (parser) {
function parseEntity (line 4231) | function parseEntity (parser) {
function beginWhiteSpace (line 4264) | function beginWhiteSpace (parser, c) {
function charAt (line 4277) | function charAt (chunk, i) {
function write (line 4285) | function write (chunk) {
function Stream (line 4933) | function Stream() {
function ondata (line 4940) | function ondata(chunk) {
function ondrain (line 4950) | function ondrain() {
function onend (line 4966) | function onend() {
function onclose (line 4974) | function onclose() {
function onerror (line 4982) | function onerror(er) {
function cleanup (line 4993) | function cleanup() {
function _inheritsLoose (line 5052) | function _inheritsLoose(subClass, superClass) { subClass.prototype = Obj...
function createErrorType (line 5056) | function createErrorType(code, message, Base) {
function oneOf (line 5087) | function oneOf(expected, thing) {
function startsWith (line 5107) | function startsWith(str, search, pos) {
function endsWith (line 5112) | function endsWith(str, search, this_len) {
function includes (line 5121) | function includes(str, search, start) {
function Duplex (line 5237) | function Duplex(options) {
function onend (line 5282) | function onend() {
function onEndNT (line 5290) | function onEndNT(self) {
function PassThrough (line 5353) | function PassThrough(options) {
function _uint8ArrayToBuffer (line 5412) | function _uint8ArrayToBuffer(chunk) {
function _isUint8Array (line 5416) | function _isUint8Array(obj) {
function prependListener (line 5457) | function prependListener(emitter, event, fn) {
function ReadableState (line 5468) | function ReadableState(options, stream, isDuplex) {
function Readable (line 5531) | function Readable(options) {
function readableAddChunk (line 5611) | function readableAddChunk(stream, chunk, encoding, addToFront, skipChunk...
function addChunk (line 5657) | function addChunk(stream, state, chunk, addToFront) {
function chunkInvalid (line 5671) | function chunkInvalid(state, chunk) {
function computeNewHighWaterMark (line 5711) | function computeNewHighWaterMark(n) {
function howMuchToRead (line 5732) | function howMuchToRead(n, state) {
function onEofChunk (line 5849) | function onEofChunk(stream, state) {
function emitReadable (line 5883) | function emitReadable(stream) {
function emitReadable_ (line 5895) | function emitReadable_(stream) {
function maybeReadMore (line 5920) | function maybeReadMore(stream, state) {
function maybeReadMore_ (line 5927) | function maybeReadMore_(stream, state) {
function onunpipe (line 5995) | function onunpipe(readable, unpipeInfo) {
function onend (line 6006) | function onend() {
function cleanup (line 6019) | function cleanup() {
function ondata (line 6041) | function ondata(chunk) {
function onerror (line 6062) | function onerror(er) {
function onclose (line 6072) | function onclose() {
function onfinish (line 6079) | function onfinish() {
function unpipe (line 6087) | function unpipe() {
function pipeOnDrain (line 6103) | function pipeOnDrain(src) {
function updateReadableListening (line 6228) | function updateReadableListening(self) {
function nReadingNextTick (line 6241) | function nReadingNextTick(self) {
function resume (line 6264) | function resume(stream, state) {
function resume_ (line 6271) | function resume_(stream, state) {
function flow (line 6297) | function flow(stream) {
function fromList (line 6425) | function fromList(n, state) {
function endReadable (line 6440) | function endReadable(stream) {
function endReadableNT (line 6450) | function endReadableNT(state, stream) {
function indexOf (line 6480) | function indexOf(xs, x) {
function afterTransform (line 6565) | function afterTransform(er, data) {
function Transform (line 6587) | function Transform(options) {
function prefinish (line 6614) | function prefinish() {
function done (line 6680) | function done(stream, er, data) {
function WriteReq (line 6721) | function WriteReq(chunk, encoding, cb) {
function CorkedRequest (line 6730) | function CorkedRequest(state) {
function _uint8ArrayToBuffer (line 6766) | function _uint8ArrayToBuffer(chunk) {
function _isUint8Array (line 6770) | function _isUint8Array(obj) {
function nop (line 6793) | function nop() {}
function WritableState (line 6795) | function WritableState(options, stream, isDuplex) {
function Writable (line 6921) | function Writable(options) {
function writeAfterEnd (line 6952) | function writeAfterEnd(stream, cb) {
function validChunk (line 6962) | function validChunk(stream, state, chunk, cb) {
function decodeChunk (line 7035) | function decodeChunk(state, chunk, encoding) {
function writeOrBuffer (line 7055) | function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
function doWrite (line 7096) | function doWrite(stream, state, writev, len, chunk, encoding, cb) {
function onwriteError (line 7105) | function onwriteError(stream, state, sync, er, cb) {
function onwriteStateUpdate (line 7129) | function onwriteStateUpdate(state) {
function onwrite (line 7136) | function onwrite(stream, er) {
function afterWrite (line 7158) | function afterWrite(stream, state, finished, cb) {
function onwriteDrain (line 7168) | function onwriteDrain(stream, state) {
function clearBuffer (line 7176) | function clearBuffer(stream, state) {
function needFinish (line 7277) | function needFinish(state) {
function callFinal (line 7281) | function callFinal(stream, state) {
function prefinish (line 7295) | function prefinish(stream, state) {
function finishMaybe (line 7308) | function finishMaybe(stream, state) {
function endWritable (line 7333) | function endWritable(stream, state, cb) {
function onCorkedFinish (line 7345) | function onCorkedFinish(corkReq, state, err) {
function _defineProperty (line 7398) | function _defineProperty(obj, key, value) { if (key in obj) { Object.def...
function createIterResult (line 7410) | function createIterResult(value, done) {
function readAndResolve (line 7417) | function readAndResolve(iter) {
function onReadable (line 7434) | function onReadable(iter) {
function wrapForNext (line 7440) | function wrapForNext(lastPromise, iter) {
method stream (line 7455) | get stream() {
function ownKeys (line 7606) | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object...
function _objectSpread (line 7608) | function _objectSpread(target) { for (var i = 1; i < arguments.length; i...
function _defineProperty (line 7610) | function _defineProperty(obj, key, value) { if (key in obj) { Object.def...
function _classCallCheck (line 7612) | function _classCallCheck(instance, Constructor) { if (!(instance instanc...
function _defineProperties (line 7614) | function _defineProperties(target, props) { for (var i = 0; i < props.le...
function _createClass (line 7616) | function _createClass(Constructor, protoProps, staticProps) { if (protoP...
function copyBuffer (line 7626) | function copyBuffer(src, target, offset) {
function BufferList (line 7633) | function BufferList() {
function destroy (line 7818) | function destroy(err, cb) {
function emitErrorAndCloseNT (line 7871) | function emitErrorAndCloseNT(self, err) {
function emitCloseNT (line 7876) | function emitCloseNT(self) {
function undestroy (line 7882) | function undestroy() {
function emitErrorNT (line 7901) | function emitErrorNT(self, err) {
function errorOrDestroy (line 7905) | function errorOrDestroy(stream, err) {
function once (line 7930) | function once(callback) {
function noop (line 7944) | function noop() {}
function isRequest (line 7946) | function isRequest(stream) {
function eos (line 7950) | function eos(stream, opts, callback) {
function once (line 8040) | function once(callback) {
function noop (line 8053) | function noop(err) {
function isRequest (line 8058) | function isRequest(stream) {
function destroyer (line 8062) | function destroyer(stream, reading, writing, callback) {
function call (line 8089) | function call(fn) {
function pipe (line 8093) | function pipe(from, to) {
function popCallback (line 8097) | function popCallback(streams) {
function pipeline (line 8103) | function pipeline() {
function highWaterMarkFrom (line 8136) | function highWaterMarkFrom(options, isDuplex, duplexKey) {
function getHighWaterMark (line 8140) | function getHighWaterMark(state, options, duplexKey, isDuplex) {
function _normalizeEncoding (line 8201) | function _normalizeEncoding(enc) {
function normalizeEncoding (line 8231) | function normalizeEncoding(enc) {
function StringDecoder (line 8241) | function StringDecoder(encoding) {
function utf8CheckByte (line 8302) | function utf8CheckByte(byte) {
function utf8CheckIncomplete (line 8310) | function utf8CheckIncomplete(self, buf, i) {
function utf8CheckExtraBytes (line 8343) | function utf8CheckExtraBytes(self, buf, p) {
function utf8FillLast (line 8363) | function utf8FillLast(buf) {
function utf8Text (line 8378) | function utf8Text(buf, i) {
function utf8End (line 8389) | function utf8End(buf) {
function utf16Text (line 8399) | function utf16Text(buf, i) {
function utf16End (line 8422) | function utf16End(buf) {
function base64Text (line 8431) | function base64Text(buf, i) {
function base64End (line 8445) | function base64End(buf) {
function simpleWrite (line 8452) | function simpleWrite(buf) {
function simpleEnd (line 8456) | function simpleEnd(buf) {
function deprecate (line 8486) | function deprecate (fn, msg) {
function config (line 8517) | function config (name) {
function validateOptions (line 8565) | function validateOptions(userOptions) {
function writeIndentation (line 8609) | function writeIndentation(options, depth, firstLine) {
function writeAttributes (line 8613) | function writeAttributes(attributes, options, depth) {
function writeDeclaration (line 8637) | function writeDeclaration(declaration, options, depth) {
function writeInstruction (line 8643) | function writeInstruction(instruction, options, depth) {
function writeComment (line 8665) | function writeComment(comment, options) {
function writeCdata (line 8669) | function writeCdata(cdata, options) {
function writeDoctype (line 8673) | function writeDoctype(doctype, options) {
function writeText (line 8677) | function writeText(text, options) {
function hasContent (line 8685) | function hasContent(element, options) {
function writeElement (line 8717) | function writeElement(element, options, depth) {
function writeElements (line 8748) | function writeElements(elements, options, depth, firstLine) {
function hasContentCompact (line 8765) | function hasContentCompact(element, options, anyContent) {
function writeElementCompact (line 8799) | function writeElementCompact(element, name, options, depth, indent) {
function writeElementsCompact (line 8840) | function writeElementsCompact(element, options, depth, firstLine) {
function validateOptions (line 8959) | function validateOptions(userOptions) {
function nativeType (line 9002) | function nativeType(value) {
function addField (line 9016) | function addField(type, value) {
function manipulateAttributes (line 9086) | function manipulateAttributes(attributes) {
function onInstruction (line 9110) | function onInstruction(instruction) {
function onStartElement (line 9149) | function onStartElement(name, attributes) {
function onText (line 9203) | function onText(text) {
function onComment (line 9222) | function onComment(comment) {
function onEndElement (line 9232) | function onEndElement(name) {
function onCdata (line 9240) | function onCdata(cdata) {
function onDoctype (line 9250) | function onDoctype(doctype) {
function onError (line 9261) | function onError(error) {
function validateOptions (line 9317) | function validateOptions (userOptions) {
method constructor (line 9357) | constructor(options) {
method toString (line 9487) | toString() {
method is (line 9505) | static is(colorA, colorB, epsilon = 0.0001) {
method constructor (line 9521) | constructor(...args) {
method add (line 9529) | add(o) {
method constructor (line 11438) | constructor(errors1) {
FILE: lib/bmp.js
function encodeBMP (line 12) | function encodeBMP(imgData, bitsPerPixel = 24) {
function decodeBMP (line 224) | function decodeBMP(arrayBuffer) {
function maskColor (line 285) | function maskColor(maskRed, maskGreen, maskBlue, maskAlpha) {
class BmpDecoder (line 303) | class BmpDecoder {
method constructor (line 304) | constructor(arrayBuffer, { toRGBA } = { toRGBA: false }) {
method parseHeader (line 321) | parseHeader() {
method parseRGBA (line 404) | parseRGBA() {
method parse1bpp (line 426) | parse1bpp() {
method parse4bpp (line 452) | parse4bpp() {
method parse8bpp (line 531) | parse8bpp() {
method parse16bpp (line 601) | parse16bpp() {
method parse24bpp (line 612) | parse24bpp() {
method parse32bpp (line 625) | parse32bpp() {
method scanImage (line 635) | scanImage(padding = 0, width = this.width, processPixel) {
method setPixelData (line 647) | setPixelData(location, rgbIndex) {
FILE: lib/discord-embedded-app-sdk-v1.2.0-bundled-with-skypack.js
function getDefaultExportFromCjs (line 3) | function getDefaultExportFromCjs(x) {
function Events2 (line 9) | function Events2() {
function EE (line 16) | function EE(fn, context, once) {
function addListener (line 21) | function addListener(emitter, event, fn, context, once) {
function clearEvent (line 34) | function clearEvent(emitter, evt) {
function EventEmitter2 (line 40) | function EventEmitter2() {
function assertIs (line 188) | function assertIs(_arg) {
function assertNever (line 191) | function assertNever(_x) {
function joinValues (line 232) | function joinValues(array, separator = " | ") {
class ZodError (line 337) | class ZodError extends Error {
method constructor (line 338) | constructor(issues) {
method errors (line 356) | get errors() {
method format (line 359) | format(_mapper) {
method toString (line 395) | toString() {
method message (line 398) | get message() {
method isEmpty (line 401) | get isEmpty() {
method flatten (line 404) | flatten(mapper = (issue) => issue.message) {
method formErrors (line 417) | get formErrors() {
function setErrorMap (line 524) | function setErrorMap(map) {
function getErrorMap (line 527) | function getErrorMap() {
constant EMPTY_PATH (line 548) | const EMPTY_PATH = [];
function addIssueToContext (line 549) | function addIssueToContext(ctx, issueData) {
class ParseStatus (line 563) | class ParseStatus {
method constructor (line 564) | constructor() {
method dirty (line 567) | dirty() {
method abort (line 571) | abort() {
method mergeArray (line 575) | static mergeArray(status, results) {
method mergeObjectAsync (line 586) | static async mergeObjectAsync(status, pairs) {
method mergeObjectSync (line 596) | static mergeObjectSync(status, pairs) {
constant INVALID (line 615) | const INVALID = Object.freeze({
class ParseInputLazyPath (line 629) | class ParseInputLazyPath {
method constructor (line 630) | constructor(parent, value, path, key) {
method path (line 637) | get path() {
method error (line 657) | get error() {
function processCreateParams (line 667) | function processCreateParams(params) {
class ZodType (line 686) | class ZodType {
method constructor (line 687) | constructor(def) {
method description (line 715) | get description() {
method _getType (line 718) | _getType(input) {
method _getOrReturnCtx (line 721) | _getOrReturnCtx(input, ctx) {
method _processInputParams (line 731) | _processInputParams(input) {
method _parseSync (line 744) | _parseSync(input) {
method _parseAsync (line 751) | _parseAsync(input) {
method parse (line 755) | parse(data, params) {
method safeParse (line 761) | safeParse(data, params) {
method parseAsync (line 778) | async parseAsync(data, params) {
method safeParseAsync (line 784) | async safeParseAsync(data, params) {
method refine (line 801) | refine(check, message) {
method refinement (line 835) | refinement(check, refinementData) {
method _refinement (line 845) | _refinement(refinement) {
method superRefine (line 852) | superRefine(refinement) {
method optional (line 855) | optional() {
method nullable (line 858) | nullable() {
method nullish (line 861) | nullish() {
method array (line 864) | array() {
method promise (line 867) | promise() {
method or (line 870) | or(option) {
method and (line 873) | and(incoming) {
method transform (line 876) | transform(transform2) {
method default (line 884) | default(def) {
method brand (line 893) | brand() {
method catch (line 900) | catch(def) {
method describe (line 909) | describe(description) {
method pipe (line 916) | pipe(target) {
method readonly (line 919) | readonly() {
method isOptional (line 922) | isOptional() {
method isNullable (line 925) | isNullable() {
function isValidIP (line 959) | function isValidIP(ip, version) {
class ZodString (line 968) | class ZodString extends ZodType {
method _parse (line 969) | _parse(input) {
method _regex (line 1188) | _regex(regex, validation, message) {
method _addCheck (line 1195) | _addCheck(check) {
method email (line 1201) | email(message) {
method url (line 1204) | url(message) {
method emoji (line 1207) | emoji(message) {
method uuid (line 1210) | uuid(message) {
method cuid (line 1213) | cuid(message) {
method cuid2 (line 1216) | cuid2(message) {
method ulid (line 1219) | ulid(message) {
method ip (line 1222) | ip(options) {
method datetime (line 1225) | datetime(options) {
method regex (line 1242) | regex(regex, message) {
method includes (line 1249) | includes(value, options) {
method startsWith (line 1257) | startsWith(value, message) {
method endsWith (line 1264) | endsWith(value, message) {
method min (line 1271) | min(minLength, message) {
method max (line 1278) | max(maxLength, message) {
method length (line 1285) | length(len, message) {
method nonempty (line 1292) | nonempty(message) {
method trim (line 1295) | trim() {
method toLowerCase (line 1301) | toLowerCase() {
method toUpperCase (line 1307) | toUpperCase() {
method isDatetime (line 1313) | get isDatetime() {
method isEmail (line 1316) | get isEmail() {
method isURL (line 1319) | get isURL() {
method isEmoji (line 1322) | get isEmoji() {
method isUUID (line 1325) | get isUUID() {
method isCUID (line 1328) | get isCUID() {
method isCUID2 (line 1331) | get isCUID2() {
method isULID (line 1334) | get isULID() {
method isIP (line 1337) | get isIP() {
method minLength (line 1340) | get minLength() {
method maxLength (line 1350) | get maxLength() {
function floatSafeRemainder (line 1370) | function floatSafeRemainder(val, step) {
class ZodNumber (line 1378) | class ZodNumber extends ZodType {
method constructor (line 1379) | constructor() {
method _parse (line 1385) | _parse(input) {
method gte (line 1466) | gte(value, message) {
method gt (line 1469) | gt(value, message) {
method lte (line 1472) | lte(value, message) {
method lt (line 1475) | lt(value, message) {
method setLimit (line 1478) | setLimit(kind, value, inclusive, message) {
method _addCheck (line 1492) | _addCheck(check) {
method int (line 1498) | int(message) {
method positive (line 1504) | positive(message) {
method negative (line 1512) | negative(message) {
method nonpositive (line 1520) | nonpositive(message) {
method nonnegative (line 1528) | nonnegative(message) {
method multipleOf (line 1536) | multipleOf(value, message) {
method finite (line 1543) | finite(message) {
method safe (line 1549) | safe(message) {
method minValue (line 1562) | get minValue() {
method maxValue (line 1572) | get maxValue() {
method isInt (line 1582) | get isInt() {
method isFinite (line 1585) | get isFinite() {
class ZodBigInt (line 1609) | class ZodBigInt extends ZodType {
method constructor (line 1610) | constructor() {
method _parse (line 1615) | _parse(input) {
method gte (line 1674) | gte(value, message) {
method gt (line 1677) | gt(value, message) {
method lte (line 1680) | lte(value, message) {
method lt (line 1683) | lt(value, message) {
method setLimit (line 1686) | setLimit(kind, value, inclusive, message) {
method _addCheck (line 1700) | _addCheck(check) {
method positive (line 1706) | positive(message) {
method negative (line 1714) | negative(message) {
method nonpositive (line 1722) | nonpositive(message) {
method nonnegative (line 1730) | nonnegative(message) {
method multipleOf (line 1738) | multipleOf(value, message) {
method minValue (line 1745) | get minValue() {
method maxValue (line 1755) | get maxValue() {
class ZodBoolean (line 1775) | class ZodBoolean extends ZodType {
method _parse (line 1776) | _parse(input) {
class ZodDate (line 1800) | class ZodDate extends ZodType {
method _parse (line 1801) | _parse(input) {
method _addCheck (line 1860) | _addCheck(check) {
method min (line 1866) | min(minDate, message) {
method max (line 1873) | max(maxDate, message) {
method minDate (line 1880) | get minDate() {
method maxDate (line 1890) | get maxDate() {
class ZodSymbol (line 1909) | class ZodSymbol extends ZodType {
method _parse (line 1910) | _parse(input) {
class ZodUndefined (line 1930) | class ZodUndefined extends ZodType {
method _parse (line 1931) | _parse(input) {
class ZodNull (line 1951) | class ZodNull extends ZodType {
method _parse (line 1952) | _parse(input) {
class ZodAny (line 1972) | class ZodAny extends ZodType {
method constructor (line 1973) | constructor() {
method _parse (line 1977) | _parse(input) {
class ZodUnknown (line 1987) | class ZodUnknown extends ZodType {
method constructor (line 1988) | constructor() {
method _parse (line 1992) | _parse(input) {
class ZodNever (line 2002) | class ZodNever extends ZodType {
method _parse (line 2003) | _parse(input) {
class ZodVoid (line 2019) | class ZodVoid extends ZodType {
method _parse (line 2020) | _parse(input) {
class ZodArray (line 2040) | class ZodArray extends ZodType {
method _parse (line 2041) | _parse(input) {
method element (line 2106) | get element() {
method min (line 2109) | min(minLength, message) {
method max (line 2115) | max(maxLength, message) {
method length (line 2121) | length(len, message) {
method nonempty (line 2127) | nonempty(message) {
function deepPartialify (line 2141) | function deepPartialify(schema) {
class ZodObject (line 2167) | class ZodObject extends ZodType {
method constructor (line 2168) | constructor() {
method _getCached (line 2174) | _getCached() {
method _parse (line 2181) | _parse(input) {
method shape (line 2264) | get shape() {
method strict (line 2267) | strict(message) {
method strip (line 2287) | strip() {
method passthrough (line 2293) | passthrough() {
method extend (line 2299) | extend(augmentation) {
method merge (line 2308) | merge(merging) {
method setKey (line 2320) | setKey(key, schema) {
method catchall (line 2323) | catchall(index) {
method pick (line 2329) | pick(mask) {
method omit (line 2341) | omit(mask) {
method deepPartial (line 2353) | deepPartial() {
method partial (line 2356) | partial(mask) {
method required (line 2371) | required(mask) {
method keyof (line 2390) | keyof() {
class ZodUnion (line 2421) | class ZodUnion extends ZodType {
method _parse (line 2422) | _parse(input) {
method options (line 2501) | get options() {
class ZodDiscriminatedUnion (line 2533) | class ZodDiscriminatedUnion extends ZodType {
method _parse (line 2534) | _parse(input) {
method discriminator (line 2569) | get discriminator() {
method options (line 2572) | get options() {
method optionsMap (line 2575) | get optionsMap() {
method create (line 2578) | static create(discriminator, options, params) {
function mergeValues (line 2601) | function mergeValues(a, b) {
class ZodIntersection (line 2639) | class ZodIntersection extends ZodType {
method _parse (line 2640) | _parse(input) {
class ZodTuple (line 2692) | class ZodTuple extends ZodType {
method _parse (line 2693) | _parse(input) {
method items (line 2738) | get items() {
method rest (line 2741) | rest(rest) {
class ZodRecord (line 2759) | class ZodRecord extends ZodType {
method keySchema (line 2760) | get keySchema() {
method valueSchema (line 2763) | get valueSchema() {
method _parse (line 2766) | _parse(input) {
method element (line 2791) | get element() {
method create (line 2794) | static create(first, second, third) {
class ZodMap (line 2811) | class ZodMap extends ZodType {
method keySchema (line 2812) | get keySchema() {
method valueSchema (line 2815) | get valueSchema() {
method _parse (line 2818) | _parse(input) {
class ZodSet (line 2877) | class ZodSet extends ZodType {
method _parse (line 2878) | _parse(input) {
method min (line 2934) | min(minSize, message) {
method max (line 2940) | max(maxSize, message) {
method size (line 2946) | size(size, message) {
method nonempty (line 2949) | nonempty(message) {
class ZodFunction (line 2962) | class ZodFunction extends ZodType {
method constructor (line 2963) | constructor() {
method _parse (line 2967) | _parse(input) {
method parameters (line 3042) | parameters() {
method returnType (line 3045) | returnType() {
method args (line 3048) | args(...items) {
method returns (line 3054) | returns(returnType) {
method implement (line 3060) | implement(func) {
method strictImplement (line 3064) | strictImplement(func) {
method create (line 3068) | static create(args, returns, params) {
class ZodLazy (line 3077) | class ZodLazy extends ZodType {
method schema (line 3078) | get schema() {
method _parse (line 3081) | _parse(input) {
class ZodLiteral (line 3094) | class ZodLiteral extends ZodType {
method _parse (line 3095) | _parse(input) {
method value (line 3107) | get value() {
function createZodEnum (line 3118) | function createZodEnum(values, params) {
class ZodEnum (line 3125) | class ZodEnum extends ZodType {
method _parse (line 3126) | _parse(input) {
method options (line 3149) | get options() {
method enum (line 3152) | get enum() {
method Values (line 3159) | get Values() {
method Enum (line 3166) | get Enum() {
method extract (line 3173) | extract(values) {
method exclude (line 3176) | exclude(values) {
class ZodNativeEnum (line 3181) | class ZodNativeEnum extends ZodType {
method _parse (line 3182) | _parse(input) {
method enum (line 3205) | get enum() {
class ZodPromise (line 3216) | class ZodPromise extends ZodType {
method unwrap (line 3217) | unwrap() {
method _parse (line 3220) | _parse(input) {
class ZodEffects (line 3246) | class ZodEffects extends ZodType {
method innerType (line 3247) | innerType() {
method sourceType (line 3250) | sourceType() {
method _parse (line 3253) | _parse(input) {
class ZodOptional (line 3370) | class ZodOptional extends ZodType {
method _parse (line 3371) | _parse(input) {
method unwrap (line 3378) | unwrap() {
class ZodNullable (line 3389) | class ZodNullable extends ZodType {
method _parse (line 3390) | _parse(input) {
method unwrap (line 3397) | unwrap() {
class ZodDefault (line 3408) | class ZodDefault extends ZodType {
method _parse (line 3409) | _parse(input) {
method removeDefault (line 3421) | removeDefault() {
class ZodCatch (line 3433) | class ZodCatch extends ZodType {
method _parse (line 3434) | _parse(input) {
method removeCatch (line 3474) | removeCatch() {
class ZodNaN (line 3486) | class ZodNaN extends ZodType {
method _parse (line 3487) | _parse(input) {
constant BRAND (line 3507) | const BRAND = Symbol("zod_brand");
class ZodBranded (line 3508) | class ZodBranded extends ZodType {
method _parse (line 3509) | _parse(input) {
method unwrap (line 3518) | unwrap() {
class ZodPipeline (line 3522) | class ZodPipeline extends ZodType {
method _parse (line 3523) | _parse(input) {
method create (line 3569) | static create(a, b) {
class ZodReadonly (line 3577) | class ZodReadonly extends ZodType {
method _parse (line 3578) | _parse(input) {
constant NEVER (line 3698) | const NEVER = INVALID;
method util (line 3715) | get util() {
method objectUtil (line 3718) | get objectUtil() {
method ZodFirstPartyTypeKind (line 3766) | get ZodFirstPartyTypeKind() {
function Integer (line 3819) | function Integer(v, radix, alphabet, caseSensitive) {
function BigInteger2 (line 3826) | function BigInteger2(value, sign) {
function SmallInteger (line 3832) | function SmallInteger(value) {
function NativeBigInt (line 3838) | function NativeBigInt(value) {
function isPrecise (line 3842) | function isPrecise(n) {
function smallToArray (line 3845) | function smallToArray(n) {
function arrayToSmall (line 3852) | function arrayToSmall(arr) {
function trim (line 3869) | function trim(v) {
function createArray (line 3875) | function createArray(length) {
function truncate2 (line 3883) | function truncate2(n) {
function add2 (line 3888) | function add2(a, b) {
function addAny (line 3904) | function addAny(a, b) {
function addSmall (line 3909) | function addSmall(a, carry) {
function subtract2 (line 3954) | function subtract2(a, b) {
function subtractAny (line 3981) | function subtractAny(a, b, sign) {
function subtractSmall (line 3997) | function subtractSmall(a, b, sign) {
function multiplyLong (line 4062) | function multiplyLong(a, b) {
function multiplySmall (line 4077) | function multiplySmall(a, b) {
function shiftLeft (line 4090) | function shiftLeft(x, n) {
function multiplyKaratsuba (line 4096) | function multiplyKaratsuba(x, y) {
function useKaratsuba (line 4107) | function useKaratsuba(l1, l2) {
function multiplySmallAndArray (line 4130) | function multiplySmallAndArray(a, b, sign) {
function square (line 4159) | function square(a) {
function divMod1 (line 4187) | function divMod1(a, b) {
function divMod2 (line 4234) | function divMod2(a, b) {
function divModSmall (line 4262) | function divModSmall(value, lambda) {
function divModAny (line 4273) | function divModAny(self2, v) {
function compareAbs (line 4439) | function compareAbs(a, b) {
function isBasicPrime (line 4601) | function isBasicPrime(v) {
function millerRabinTest (line 4612) | function millerRabinTest(n, a) {
function shift_isSmall (line 4720) | function shift_isSmall(n) {
function bitwise (line 4760) | function bitwise(x, y, fn) {
function roughLOB (line 4811) | function roughLOB(n) {
function integerLogarithm (line 4815) | function integerLogarithm(value, base) {
function max (line 4836) | function max(a, b) {
function min (line 4841) | function min(a, b) {
function gcd (line 4846) | function gcd(a, b) {
function lcm (line 4878) | function lcm(a, b) {
function randBetween (line 4883) | function randBetween(a, b, rng2) {
function parseBaseFromArray (line 4946) | function parseBaseFromArray(digits, base, isNegative) {
function stringify (line 4954) | function stringify(digit, alphabet) {
function toBase (line 4961) | function toBase(n, base) {
function toBaseString (line 5011) | function toBaseString(n, base, alphabet) {
function parseStringValue (line 5061) | function parseStringValue(v) {
function parseNumberValue (line 5109) | function parseNumberValue(v) {
function parseValue (line 5120) | function parseValue(v) {
constant MAX_BIG_INT (line 5159) | const MAX_BIG_INT = 64;
constant SMALL_INT (line 5160) | const SMALL_INT = 16;
constant PARTS (line 5161) | const PARTS = MAX_BIG_INT / SMALL_INT;
function checkBrowserSupportsBigInt (line 5162) | function checkBrowserSupportsBigInt() {
function fromHexReverseArray (line 5170) | function fromHexReverseArray(hexValues, start, size) {
function toHexReverseArray (line 5181) | function toHexReverseArray(value) {
function splitBigInt (line 5193) | function splitBigInt(value) {
class HighLow (line 5201) | class HighLow {
method fromString (line 5202) | static fromString(value) {
method fromBit (line 5205) | static fromBit(index) {
method constructor (line 5213) | constructor(parts, str) {
method and (line 5217) | and({parts}) {
method or (line 5220) | or({parts}) {
method xor (line 5223) | xor({parts}) {
method not (line 5226) | not() {
method equals (line 5229) | equals({parts}) {
method toString (line 5232) | toString() {
method toJSON (line 5245) | toJSON() {
constant SUPPORTS_BIGINT (line 5249) | const SUPPORTS_BIGINT = checkBrowserSupportsBigInt();
constant HIGH_LOW_CACHE (line 5255) | const HIGH_LOW_CACHE = {};
constant EMPTY_FLAG (line 5271) | const EMPTY_FLAG = convertToBigFlag(0);
function flagOrMultiple (line 5300) | function flagOrMultiple(...flags) {
function flagHas (line 5307) | function flagHas(base, flag) {
function flagHasAny (line 5310) | function flagHasAny(base, flag) {
function flagAdd (line 5313) | function flagAdd(base, flag) {
function flagRemove (line 5316) | function flagRemove(base, flag) {
function zodCoerceUnhandledValue (line 5369) | function zodCoerceUnhandledValue(inputObject) {
function fallbackToDefault (line 5379) | function fallbackToDefault(schema) {
constant DISPATCH (line 5487) | const DISPATCH = "DISPATCH";
method Commands (line 5974) | get Commands() {
constant ERROR (line 6024) | const ERROR = "ERROR";
function parseEventPayload (line 6057) | function parseEventPayload(data) {
function assertUnreachable (line 6166) | function assertUnreachable(_x, runtimeError) {
function parseResponseData (line 6242) | function parseResponseData({cmd, data}) {
function parseResponsePayload (line 6302) | function parseResponsePayload(payload) {
function parseIncomingPayload (line 6353) | function parseIncomingPayload(payload) {
function commandFactory (line 6364) | function commandFactory(sendCommand, cmd, response, transferTransform = ...
function schemaCommandFactory (line 6375) | function schemaCommandFactory(cmd, transferTransform = () => void 0) {
function compatCommandFactory (line 6419) | function compatCommandFactory({sendCommand, cmd, response, fallbackTrans...
function commands (line 6458) | function commands(sendCommand) {
class SDKError (line 6481) | class SDKError extends Error {
method constructor (line 6482) | constructor(code, message = "") {
function getDefaultSdkConfiguration (line 6489) | function getDefaultSdkConfiguration() {
function wrapConsoleMethod (line 6495) | function wrapConsoleMethod(console2, level, callback) {
function rng (line 6514) | function rng() {
function unsafeStringify (line 6527) | function unsafeStringify(arr, offset = 0) {
function v4 (line 6530) | function v4(options, buf, offset) {
constant ALLOWED_ORIGINS (line 6554) | const ALLOWED_ORIGINS = new Set(getAllowedOrigins());
function getAllowedOrigins (line 6555) | function getAllowedOrigins() {
function getRPCServerSource (line 6572) | function getRPCServerSource() {
class DiscordSDK (line 6576) | class DiscordSDK {
method getTransfer (line 6577) | getTransfer(payload) {
method constructor (line 6587) | constructor(clientId, configuration) {
method close (line 6663) | close(code, message) {
method subscribe (line 6669) | async subscribe(event, listener, ...rest) {
method unsubscribe (line 6682) | async unsubscribe(event, listener, ...rest) {
method ready (line 6693) | async ready() {
method handshake (line 6702) | handshake() {
method addOnReadyListener (line 6714) | addOnReadyListener() {
method overrideConsoleLogging (line 6720) | overrideConsoleLogging() {
method handleClose (line 6733) | handleClose(data) {
method handleHandshake (line 6736) | handleHandshake() {
method handleFrame (line 6738) | handleFrame(payload) {
method _getSearch (line 6767) | _getSearch() {
function can (line 6771) | function can(permission, permissions) {
function add (line 7135) | function add(x, y) {
function checkInt32 (line 7191) | function checkInt32(i, min, max) {
function digitsToString (line 7196) | function digitsToString(d) {
function multiplyInteger (line 7220) | function multiplyInteger(x, k) {
function compare (line 7231) | function compare(a, b, aL, bL) {
function subtract2 (line 7245) | function subtract2(a, b, aL) {
function exp (line 7364) | function exp(x, sd) {
function getBase10Exponent (line 7398) | function getBase10Exponent(x) {
function getLn10 (line 7404) | function getLn10(Ctor, sd, pr) {
function getZeroString (line 7413) | function getZeroString(k) {
function ln (line 7419) | function ln(y, sd) {
function parseDecimal (line 7479) | function parseDecimal(x, str) {
function round (line 7526) | function round(x, sd, rm) {
function subtract (line 7598) | function subtract(x, y) {
function toString (line 7675) | function toString(x, isExp, sd) {
function truncate (line 7703) | function truncate(arr, len) {
function clone (line 7709) | function clone(obj) {
function config (line 7780) | function config(obj) {
function formatPrice (line 8186) | function formatPrice(price, locale = "en-US") {
function convertToMajorCurrencyUnits (line 8191) | function convertToMajorCurrencyUnits(minorUnitValue, currency) {
function arrayEach (line 8234) | function arrayEach(array, iteratee) {
function arraySome (line 8243) | function arraySome(array, predicate) {
function baseProperty (line 8252) | function baseProperty(key) {
function baseTimes (line 8257) | function baseTimes(n, iteratee) {
function baseUnary (line 8264) | function baseUnary(func) {
function getValue (line 8269) | function getValue(object, key) {
function isHostObject (line 8272) | function isHostObject(value) {
function mapToArray (line 8282) | function mapToArray(map) {
function overArg (line 8289) | function overArg(func, transform3) {
function setToArray (line 8294) | function setToArray(set) {
function Hash (line 8316) | function Hash(entries) {
function hashClear (line 8324) | function hashClear() {
function hashDelete (line 8327) | function hashDelete(key) {
function hashGet (line 8330) | function hashGet(key) {
function hashHas (line 8338) | function hashHas(key) {
function hashSet (line 8342) | function hashSet(key, value) {
function ListCache (line 8352) | function ListCache(entries) {
function listCacheClear (line 8360) | function listCacheClear() {
function listCacheDelete (line 8363) | function listCacheDelete(key) {
function listCacheGet (line 8376) | function listCacheGet(key) {
function listCacheHas (line 8380) | function listCacheHas(key) {
function listCacheSet (line 8383) | function listCacheSet(key, value) {
function MapCache (line 8397) | function MapCache(entries) {
function mapCacheClear (line 8405) | function mapCacheClear() {
function mapCacheDelete (line 8412) | function mapCacheDelete(key) {
function mapCacheGet (line 8415) | function mapCacheGet(key) {
function mapCacheHas (line 8418) | function mapCacheHas(key) {
function mapCacheSet (line 8421) | function mapCacheSet(key, value) {
function SetCache (line 8430) | function SetCache(values) {
function setCacheAdd (line 8437) | function setCacheAdd(value) {
function setCacheHas (line 8441) | function setCacheHas(value) {
function Stack (line 8446) | function Stack(entries) {
function stackClear (line 8449) | function stackClear() {
function stackDelete (line 8452) | function stackDelete(key) {
function stackGet (line 8455) | function stackGet(key) {
function stackHas (line 8458) | function stackHas(key) {
function stackSet (line 8461) | function stackSet(key, value) {
function arrayLikeKeys (line 8479) | function arrayLikeKeys(value, inherited) {
function assocIndexOf (line 8489) | function assocIndexOf(array, key) {
function baseCreate (line 8498) | function baseCreate(proto) {
function baseForOwn (line 8502) | function baseForOwn(object, iteratee) {
function baseGet (line 8505) | function baseGet(object, path) {
function baseGetTag (line 8513) | function baseGetTag(value) {
function baseHasIn (line 8516) | function baseHasIn(object, key) {
function baseIsEqual (line 8519) | function baseIsEqual(value, other, customizer, bitmask, stack) {
function baseIsEqualDeep (line 8528) | function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, ...
function baseIsMatch (line 8557) | function baseIsMatch(object, source, matchData, customizer) {
function baseIsNative (line 8588) | function baseIsNative(value) {
function baseIsTypedArray (line 8595) | function baseIsTypedArray(value) {
function baseIteratee (line 8598) | function baseIteratee(value) {
function baseKeys (line 8610) | function baseKeys(object) {
function baseMatches (line 8622) | function baseMatches(source) {
function baseMatchesProperty (line 8631) | function baseMatchesProperty(path, srcValue) {
function basePropertyDeep (line 8640) | function basePropertyDeep(path) {
function baseToString (line 8645) | function baseToString(value) {
function castPath (line 8655) | function castPath(value) {
function createBaseFor (line 8658) | function createBaseFor(fromRight) {
function equalArrays (line 8670) | function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
function equalByTag (line 8712) | function equalByTag(object, other, tag, equalFunc, customizer, bitmask, ...
function equalObjects (line 8758) | function equalObjects(object, other, equalFunc, customizer, bitmask, sta...
function getMapData (line 8800) | function getMapData(map, key) {
function getMatchData (line 8804) | function getMatchData(object) {
function getNative (line 8812) | function getNative(object, key) {
function hasPath (line 8837) | function hasPath(object, path, hasFunc) {
function isIndex (line 8853) | function isIndex(value, length) {
function isKey (line 8857) | function isKey(value, object) {
function isKeyable (line 8867) | function isKeyable(value) {
function isMasked (line 8871) | function isMasked(func) {
function isPrototype (line 8874) | function isPrototype(value) {
function isStrictComparable (line 8878) | function isStrictComparable(value) {
function matchesStrictComparable (line 8881) | function matchesStrictComparable(key, srcValue) {
function toKey (line 8900) | function toKey(value) {
function toSource (line 8907) | function toSource(func) {
function memoize (line 8920) | function memoize(func, resolver) {
function eq (line 8937) | function eq(value, other) {
function isArguments (line 8940) | function isArguments(value) {
function isArrayLike (line 8944) | function isArrayLike(value) {
function isArrayLikeObject (line 8947) | function isArrayLikeObject(value) {
function isFunction (line 8950) | function isFunction(value) {
function isLength (line 8954) | function isLength(value) {
function isObject (line 8957) | function isObject(value) {
function isObjectLike (line 8961) | function isObjectLike(value) {
function isSymbol (line 8964) | function isSymbol(value) {
function toString2 (line 8968) | function toString2(value) {
function get (line 8971) | function get(object, path, defaultValue) {
function hasIn (line 8975) | function hasIn(object, path) {
function keys (line 8978) | function keys(object) {
function transform2 (line 8981) | function transform2(object, iteratee, accumulator) {
function identity (line 9001) | function identity(value) {
function property (line 9004) | function property(path) {
class DiscordSDKMock (line 9011) | class DiscordSDKMock {
method constructor (line 9012) | constructor(clientId, guildId, channelId) {
method _updateCommandMocks (line 9025) | _updateCommandMocks(newCommands) {
method emitReady (line 9034) | emitReady() {
method close (line 9037) | close(...args) {
method ready (line 9040) | ready() {
method subscribe (line 9043) | async subscribe(event, listener, ..._subscribeArgs) {
method unsubscribe (line 9046) | async unsubscribe(event, listener, ..._unsubscribeArgs) {
method emitEvent (line 9049) | emitEvent(event, data) {
function __rest (line 9104) | function __rest(s, e) {
constant SUBSTITUTION_REGEX (line 9120) | const SUBSTITUTION_REGEX = /\{([a-z]+)\}/g;
function regexFromTarget (line 9121) | function regexFromTarget(target) {
function matchAndRewriteURL (line 9125) | function matchAndRewriteURL({originalURL, prefix, prefixHost, target}) {
function absoluteURL (line 9147) | function absoluteURL(url, protocol = window.location.protocol, host = wi...
function patchUrlMappings (line 9150) | function patchUrlMappings(mappings, {patchFetch = true, patchWebSocket =...
function recursivelyRemapChildNodes (line 9223) | function recursivelyRemapChildNodes(node, mappings) {
function attemptSetNodeSrc (line 9231) | function attemptSetNodeSrc(node, mappings) {
function attemptRemap (line 9240) | function attemptRemap({url, mappings}) {
FILE: lib/firebase.js
function r (line 6) | function r(e){if(o[e])return o[e].exports;var n=o[e]={i:e,l:!1,exports:{...
function t (line 6) | function t(){c.onerror=c.onload=null,clearTimeout(s);var t=i[e];0!==t&&(...
function n (line 6) | function n(e){for(var r in e)t.hasOwnProperty(r)||(t[r]=e[r])}
function n (line 6) | function n(){function e(e){l(d[e],"delete"),delete d[e]}function t(e){re...
function o (line 6) | function o(e,t){throw h.create(e,t)}
function e (line 6) | function e(e,t,r){this.r=r,this.a=!1,this.u={},this.f=t,this.h=Object(i....
function r (line 6) | function r(){throw Error("setTimeout has not been defined")}
function n (line 6) | function n(){throw Error("clearTimeout has not been defined")}
function o (line 6) | function o(e){if(f===setTimeout)return setTimeout(e,0);if((f===r||!f)&&s...
function i (line 6) | function i(e){if(h===clearTimeout)return clearTimeout(e);if((h===n||!h)&...
function a (line 6) | function a(){v&&p&&(v=!1,p.length?d=p.concat(d):y=-1,d.length&&c())}
function c (line 6) | function c(){if(!v){var e=o(a);v=!0;for(var t=d.length;t;){for(p=d,d=[];...
function s (line 6) | function s(e,t){this.fun=e,this.array=t}
function u (line 6) | function u(){}
method ENCODED_VALS (line 6) | get ENCODED_VALS(){return this.ENCODED_VALS_BASE+"+/="}
method ENCODED_VALS_WEBSAFE (line 6) | get ENCODED_VALS_WEBSAFE(){return this.ENCODED_VALS_BASE+"-_."}
function n (line 6) | function n(e){return JSON.parse(e)}
function o (line 6) | function o(e){return JSON.stringify(e)}
function n (line 6) | function n(){}
function o (line 6) | function o(e,t){return function(){e.apply(t,arguments)}}
function i (line 6) | function i(e){if("object"!=typeof this)throw new TypeError("Promises mus...
function a (line 6) | function a(e,t){for(;3===e._state;)e=e._value;if(0===e._state)return voi...
function c (line 6) | function c(e,t){try{if(t===e)throw new TypeError("A promise cannot be re...
function s (line 6) | function s(e,t){e._state=2,e._value=t,u(e)}
function u (line 6) | function u(e){2===e._state&&0===e.T.length&&i.A(function(){e._handled||i...
function f (line 6) | function f(e,t,r){this.onFulfilled="function"==typeof e?e:null,this.onRe...
function h (line 6) | function h(e,t){var r=!1;try{e(function(e){r||(r=!0,c(t,e))},function(e)...
function n (line 6) | function n(i,a){try{if(a&&("object"==typeof a||"function"==typeof a)){va...
function o (line 6) | function o(e,t){this.P=e,this._clearFn=t}
function n (line 6) | function n(e){"function"!=typeof e&&(e=Function(""+e));for(var t=Array(a...
function o (line 6) | function o(e){delete u[e]}
function i (line 6) | function i(e){var t=e.callback,n=e.args;switch(n.length){case 0:t();brea...
function a (line 6) | function a(e){if(f)setTimeout(a,0,e);else{var t=u[e];if(t){f=!0;try{i(t)...
function n (line 6) | function n(e){return o(void 0,e)}
function o (line 6) | function o(e,t){if(!(t instanceof Object))return t;switch(t.constructor)...
function i (line 6) | function i(e,t,r){e[t]=r}
function e (line 6) | function e(){var e=this;this.promise=new Promise(function(t,r){e.resolve...
function n (line 6) | function n(e){var t=i;return i=e,t}
function e (line 6) | function e(e,t){if(this.code=e,this.message=t,i)i(this,c.prototype.creat...
function e (line 6) | function e(e,t,r){this.service=e,this.serviceName=t,this.errors=r,this.p...
function n (line 6) | function n(){this.constructor=t}
function t (line 6) | function t(){var t=e.call(this)||this;t.D=[],t.I=[],t.x=[],t.F=[],t.L=0,...
function e (line 6) | function e(){this.blockSize=-1}
function n (line 6) | function n(e,t){var r=new c(e,t);return r.subscribe.bind(r)}
function o (line 6) | function o(e,t){return function(){for(var r=[],n=0;n<arguments.length;n+...
function i (line 6) | function i(e,t){if("object"!=typeof e||null===e)return!1;for(var r=0,n=t...
function a (line 6) | function a(){}
function e (line 6) | function e(e,t){var r=this;this.observers=[],this.unsubscribes=[],this.o...
function n (line 6) | function n(e,t,r){var n="";switch(t){case 1:n=r?"first":"First";break;ca...
function o (line 6) | function o(e,t,r,o){if((!o||r)&&"string"!=typeof r)throw Error(n(e,t,o)+...
function i (line 6) | function i(e,t,r,o){if((!o||r)&&"function"!=typeof r)throw Error(n(e,t,o...
function a (line 6) | function a(e,t,r,o){if((!o||r)&&("object"!=typeof r||null===r))throw Err...
function t (line 13) | function t(t){return"string"==typeof t}
function n (line 13) | function n(t){return"boolean"==typeof t}
function i (line 13) | function i(){}
function r (line 13) | function r(t){var n=typeof t;if("object"==n){if(!t)return"null";if(t ins...
function o (line 13) | function o(t){return null===t}
function a (line 13) | function a(t){return"array"==r(t)}
function s (line 13) | function s(t){var n=r(t);return"array"==n||"object"==n&&"number"==typeof...
function u (line 13) | function u(t){return"function"==r(t)}
function c (line 13) | function c(t){var n=typeof t;return"object"==n&&null!=t||"function"==n}
function h (line 13) | function h(t,n,e){return t.call.apply(t.bind,arguments)}
function f (line 13) | function f(t,n,e){if(!t)throw Error();if(2<arguments.length){var i=Array...
function l (line 13) | function l(t,n,e){return l=Function.prototype.bind&&-1!=(""+Function.pro...
function d (line 13) | function d(t,n){var e=Array.prototype.slice.call(arguments,1);return fun...
function p (line 13) | function p(t,n){function e(){}e.prototype=n.prototype,t.ib=n.prototype,t...
function v (line 13) | function v(t){if(Error.captureStackTrace)Error.captureStackTrace(this,v)...
function m (line 13) | function m(t,n){for(var e=t.split("%s"),i="",r=Array.prototype.slice.cal...
function g (line 13) | function g(t){return wu.test(t)?(-1!=t.indexOf("&")&&(t=t.replace(du,"&a...
function b (line 13) | function b(t,n){return-1!=t.indexOf(n)}
function w (line 13) | function w(t,n){return t<n?-1:t>n?1:0}
function y (line 13) | function y(t,n){n.unshift(t),v.call(this,m.apply(null,n)),n.shift()}
function I (line 13) | function I(t,n){throw new y("Failure"+(t?": "+t:""),Array.prototype.slic...
function T (line 13) | function T(n,e){var i=n.length,r=t(n)?n.split(""):n;for(--i;0<=i;--i)i i...
function A (line 13) | function A(n){t:{for(var e=Ae,i=n.length,r=t(n)?n.split(""):n,o=0;o<i;o+...
function k (line 13) | function k(t,n){return 0<=Iu(t,n)}
function E (line 13) | function E(t,n){n=Iu(t,n);var e;return(e=0<=n)&&Array.prototype.splice.c...
function N (line 13) | function N(t,n){var e=0;T(t,function(i,r){n.call(void 0,i,r,t)&&1==Array...
function S (line 13) | function S(t){return Array.prototype.concat.apply([],arguments)}
function O (line 13) | function O(t){var n=t.length;if(0<n){for(var e=Array(n),i=0;i<n;i++)e[i]...
function P (line 13) | function P(t){return b(yu,t)}
function C (line 13) | function C(t,n){for(var e in t)n.call(void 0,t[e],e,t)}
function R (line 13) | function R(t){var n,e=[],i=0;for(n in t)e[i++]=t[n];return e}
function _ (line 13) | function _(t){var n,e=[],i=0;for(n in t)e[i++]=n;return e}
function D (line 13) | function D(t){for(var n in t)return!1;return!0}
function L (line 13) | function L(t,n){for(var e in t)if(!(e in n)||t[e]!==n[e])return!1;for(e ...
function x (line 13) | function x(t){var n,e={};for(n in t)e[n]=t[n];return e}
function U (line 13) | function U(t,n){for(var e,i,r=1;r<arguments.length;r++){i=arguments[r];f...
function j (line 13) | function j(t){return j[" "](t),t}
function M (line 13) | function M(t,n){var e=Vu;return Object.prototype.hasOwnProperty.call(e,t...
function V (line 13) | function V(){var t=uu.document;return t?t.documentMode:void 0}
function F (line 13) | function F(t){return M(t,function(){for(var n=0,e=lu(Ou+"").split("."),i...
function K (line 13) | function K(t){t.prototype.then=t.prototype.then,t.prototype.$goog_Thenab...
function q (line 13) | function q(t){if(!t)return!1;try{return!!t.$goog_Thenable}catch(t){retur...
function X (line 13) | function X(t,n,e){this.f=e,this.c=t,this.g=n,this.b=0,this.a=null}
function B (line 13) | function B(t,n){t.g(n),t.b<t.f&&(t.b++,n.next=t.a,t.a=n)}
function H (line 13) | function H(){var t=Hu,n=null;return t.a&&(n=t.a,t.a=t.a.next,t.a||(t.b=n...
function W (line 13) | function W(){this.next=this.b=this.a=null}
function G (line 13) | function G(t){uu.setTimeout(function(){throw t},0)}
function z (line 13) | function z(){var t=uu.MessageChannel;if(void 0===t&&"undefined"!=typeof ...
function J (line 13) | function J(t,n){Xu||Y(),Bu||(Xu(),Bu=!0);var e=Hu,i=Ku.get();i.set(t,n),...
function Y (line 13) | function Y(){if(-1!=(uu.Promise+"").indexOf("[native code]")){var t=uu.P...
function $ (line 13) | function $(){for(var t;t=H();){try{t.a.call(t.b)}catch(t){G(t)}B(Ku,t)}B...
function Z (line 13) | function Z(t,n){if(this.a=Wu,this.i=void 0,this.f=this.b=this.c=null,thi...
function Q (line 13) | function Q(){this.next=this.f=this.b=this.g=this.a=null,this.c=!1}
function tt (line 13) | function tt(t,n,e){var i=Ju.get();return i.g=t,i.b=n,i.f=e,i}
function nt (line 13) | function nt(t){if(t instanceof Z)return t;var n=new Z(i);return ht(n,Gu,...
function et (line 13) | function et(t){return new Z(function(n,e){e(t)})}
function it (line 13) | function it(t,n,e){ft(t,n,e,null)||J(d(n,t))}
function rt (line 13) | function rt(t){return new Z(function(n,e){var i=t.length,r=[];if(i)for(v...
function ot (line 13) | function ot(t){return new Z(function(n){var e=t.length,i=[];if(e)for(var...
function at (line 13) | function at(t,n){return n=tt(n,n,void 0),n.c=!0,ut(t,n),t}
function st (line 13) | function st(t,n){if(t.a==Wu)if(t.c){var e=t.c;if(e.b){for(var i=0,r=null...
function ut (line 13) | function ut(t,n){t.b||t.a!=Gu&&t.a!=zu||dt(t),t.f?t.f.next=n:t.b=n,t.f=n}
function ct (line 13) | function ct(t,n,e,i){var r=tt(null,null,null);return r.a=new Z(function(...
function ht (line 13) | function ht(t,n,e){t.a==Wu&&(t===e&&(n=zu,e=new TypeError("Promise canno...
function ft (line 13) | function ft(t,n,e,r){if(t instanceof Z)return ut(t,tt(n||i,e||null,r)),!...
function lt (line 13) | function lt(t,n,e,i,r){function o(t){s||(s=!0,i.call(r,t))}function a(t)...
function dt (line 13) | function dt(t){t.h||(t.h=!0,J(t.Qb,t))}
function pt (line 13) | function pt(t){var n=null;return t.b&&(n=t.b,t.b=n.next,n.next=null),t.b...
function vt (line 13) | function vt(t,n,e,i){if(e==zu&&n.b&&!n.c)for(;t&&t.g;t=t.c)t.g=!1;if(n.a...
function mt (line 13) | function mt(t,n,e){n==Gu?t.g.call(t.f,e):t.b&&t.b.call(t.f,e)}
function gt (line 13) | function gt(t,n){t.g=!0,J(function(){t.g&&Yu.call(null,n)})}
function bt (line 13) | function bt(t){v.call(this,t)}
function wt (line 13) | function wt(){this.a="",this.b=Zu}
function yt (line 13) | function yt(t){return t instanceof wt&&t.constructor===wt&&t.b===Zu?t.a:...
function It (line 13) | function It(t){var n=new wt;return n.a=t,n}
function Tt (line 13) | function Tt(){this.a="",this.b=nc}
function At (line 13) | function At(t){return t instanceof Tt&&t.constructor===Tt&&t.b===nc?t.a:...
function kt (line 13) | function kt(t,n){return t=Et(t,n),n=new Tt,n.a=t,n}
function Et (line 13) | function Et(t,n){var e=yt(t);if(!tc.test(e))throw Error("Invalid Trusted...
function Nt (line 13) | function Nt(){this.a="",this.b=ic}
function St (line 13) | function St(t){return t instanceof Nt&&t.constructor===Nt&&t.b===ic?t.a:...
function Ot (line 13) | function Ot(t){return t instanceof Nt?t:(t=t.la?t.ja():t+"",ec.test(t)||...
function Pt (line 13) | function Pt(t){var n=new Nt;return n.a=t,n}
function Ct (line 13) | function Ct(){this.a="",this.b=rc}
function Rt (line 13) | function Rt(t){return t instanceof Ct&&t.constructor===Ct&&t.b===rc?t.a:...
function _t (line 13) | function _t(t){var n=new Ct;return n.a=t,n}
function Dt (line 13) | function Dt(n){var e=document;return t(n)?e.getElementById(n):n}
function Lt (line 13) | function Lt(t,n){C(n,function(n,e){n&&n.la&&(n=n.ja()),"style"==e?t.styl...
function xt (line 13) | function xt(n,e,i){var r=arguments,o=document,s=r[0]+"",u=r[1];if(!$u&&u...
function Ut (line 13) | function Ut(n,e,i){function r(i){i&&e.appendChild(t(i)?n.createTextNode(...
function jt (line 13) | function jt(t){if(t&&"number"==typeof t.length){if(c(t))return"function"...
function Mt (line 13) | function Mt(t){var n=[];return Ft(new Vt,t,n),n.join("")}
function Vt (line 13) | function Vt(){}
function Ft (line 13) | function Ft(t,n,e){if(null==n)e.push("null");else{if("object"==typeof n)...
function Kt (line 13) | function Kt(t,n){n.push('"',t.replace(sc,function(t){var n=ac[t];return ...
function qt (line 13) | function qt(){0!=uc&&(cc[this[cu]||(this[cu]=++hu)]=this),this.oa=this.o...
function Xt (line 13) | function Xt(t){t.oa||(t.oa=!0,t.ta(),0!=uc&&(t=t[cu]||(t[cu]=++hu),delet...
function Bt (line 13) | function Bt(t,n){this.type=t,this.b=this.target=n,this.Bb=!0}
function Ht (line 13) | function Ht(n,e){if(Bt.call(this,n?n.type:""),this.relatedTarget=this.b=...
function Wt (line 13) | function Wt(t,n,e,i,r){this.listener=t,this.a=null,this.src=n,this.type=...
function Gt (line 13) | function Gt(t){t.ma=!0,t.listener=null,t.a=null,t.src=null,t.La=null}
function zt (line 13) | function zt(t){this.src=t,this.a={},this.b=0}
function Jt (line 13) | function Jt(t,n,e,i,r,o){var a=""+n;(n=t.a[a])||(n=t.a[a]=[],t.b++);var ...
function Yt (line 13) | function Yt(t,n){var e=n.type;e in t.a&&E(t.a[e],n)&&(Gt(n),0==t.a[e].le...
function $t (line 13) | function $t(t,n,e,i){for(var r=0;r<t.length;++r){var o=t[r];if(!o.ma&&o....
function Zt (line 13) | function Zt(t,n,e,i,r){if(i&&i.once)nn(t,n,e,i,r);else if(a(n))for(var o...
function Qt (line 13) | function Qt(t,n,e,i,r,o){if(!n)throw Error("Invalid event type");var a=c...
function tn (line 13) | function tn(){var t=un,n=fc?function(e){return t.call(n.src,n.listener,e...
function nn (line 13) | function nn(t,n,e,i,r){if(a(n))for(var o=0;o<n.length;o++)nn(t,n[o],e,i,...
function en (line 13) | function en(t,n,e,i,r){if(a(n))for(var o=0;o<n.length;o++)en(t,n[o],e,i,...
function rn (line 13) | function rn(t){if("number"!=typeof t&&t&&!t.ma){var n=t.src;if(n&&n[vc])...
function on (line 13) | function on(t){return t in bc?bc[t]:bc[t]="on"+t}
function an (line 13) | function an(t,n,e,i){var r=!0;if((t=cn(t))&&(n=t.a[""+n]))for(n=n.concat...
function sn (line 13) | function sn(t,n){var e=t.listener,i=t.La||t.src;return t.Ha&&rn(t),e.cal...
function un (line 13) | function un(t,n){if(t.ma)return!0;if(!fc){if(!n)t:{n=["window","event"];...
function cn (line 13) | function cn(t){return t=t[gc],t instanceof zt?t:null}
function hn (line 13) | function hn(t){return u(t)?t:(t[yc]||(t[yc]=function(n){return t.handleE...
function fn (line 13) | function fn(){qt.call(this),this.u=new zt(this),this.Ib=this,this.Ra=null}
function ln (line 13) | function ln(n,e){var i,r=n.Ra;if(r)for(i=[];r;r=r.Ra)i.push(r);if(n=n.Ib...
function dn (line 13) | function dn(t,n,e,i,r){Jt(t.u,n+"",e,!1,i,r)}
function pn (line 13) | function pn(t,n,e,i,r){Jt(t.u,n+"",e,!0,i,r)}
function vn (line 13) | function vn(t,n,e,i){if(!(n=t.u.a[n+""]))return!0;n=n.concat();for(var r...
function mn (line 13) | function mn(t,n,e){if(u(t))e&&(t=l(t,e));else{if(!t||"function"!=typeof ...
function gn (line 13) | function gn(t){var n=null;return new Z(function(e,i){-1==(n=mn(function(...
function bn (line 13) | function bn(t,n,e,i,r){this.reset(t,n,e,i,r)}
function wn (line 13) | function wn(t){this.f=t,this.b=this.c=this.a=null}
function yn (line 13) | function yn(t,n){this.name=t,this.value=n}
function In (line 13) | function In(t){return t.c?t.c:t.a?In(t.a):(I("Root logger has no level s...
function Tn (line 13) | function Tn(t){Nc||(Nc=new wn(""),Ec[""]=Nc,Nc.c=Ac);var n;if(!(n=Ec[t])...
function An (line 13) | function An(t,n){this.b={},this.a=[],this.c=0;var e=arguments.length;if(...
function kn (line 13) | function kn(t){if(t.c!=t.a.length){for(var n=0,e=0;n<t.a.length;){var i=...
function En (line 13) | function En(t,n){return Object.prototype.hasOwnProperty.call(t,n)}
function Nn (line 13) | function Nn(t,n){t&&t.log(kc,n,void 0)}
function Sn (line 13) | function Sn(t){return Au(t,function(t){return t=t.toString(16),1<t.lengt...
function On (line 13) | function On(t){var n="";return Pn(t,function(t){n+=String.fromCharCode(t...
function Pn (line 13) | function Pn(t,n){function e(n){for(;i<t.length;){var e=t.charAt(i++),r=O...
function Cn (line 13) | function Cn(){if(!Sc){Sc={},Oc={};for(var t=0;65>t;t++)Sc[t]="ABCDEFGHIJ...
function Rn (line 13) | function Rn(t,n){this.g=[],this.v=t,this.o=n||null,this.f=this.a=!1,this...
function _n (line 13) | function _n(t,n,e){t.a=!0,t.c=e,t.f=!n,jn(t)}
function Dn (line 13) | function Dn(t){if(t.a){if(!t.u)throw new Mn;t.u=!1}}
function Ln (line 13) | function Ln(t,n){xn(t,null,n,void 0)}
function xn (line 13) | function xn(t,n,e,i){t.g.push([n,e,i]),t.a&&jn(t)}
function Un (line 13) | function Un(t){return ku(t.g,function(t){return u(t[1])})}
function jn (line 13) | function jn(t){if(t.h&&t.a&&Un(t)){var n=t.h,e=Cc[n];e&&(uu.clearTimeout...
function Mn (line 13) | function Mn(){v.call(this)}
function Vn (line 13) | function Vn(){v.call(this)}
function Fn (line 13) | function Fn(t){this.a=uu.setTimeout(l(this.c,this),0),this.b=t}
function Kn (line 13) | function Kn(){this.b=-1}
function qn (line 13) | function qn(t,n){this.b=-1,this.b=Rc,this.f=uu.Uint8Array?new Uint8Array...
function Xn (line 13) | function Xn(t){for(var n=t.f,e=t.l,i=0,r=0;r<n.length;)e[i++]=n[r]<<24|n...
function Bn (line 13) | function Bn(n,e,i){void 0===i&&(i=e.length);var r=0,o=n.c;if(t(e))for(;r...
function Hn (line 13) | function Hn(){qn.call(this,8,jc)}
function Wn (line 13) | function Wn(n){if(n.P&&"function"==typeof n.P)return n.P();if(t(n))retur...
function Gn (line 13) | function Gn(n){if(n.S&&"function"==typeof n.S)return n.S();if(!n.P||"fun...
function zn (line 13) | function zn(n,e){if(n.forEach&&"function"==typeof n.forEach)n.forEach(e,...
function Jn (line 13) | function Jn(t,n){if(t){t=t.split("&");for(var e=0;e<t.length;e++){var i=...
function Yn (line 13) | function Yn(t,n){if(this.b=this.l=this.c="",this.i=null,this.h=this.g=""...
function $n (line 13) | function $n(t,n,e){t.c=e?re(n,!0):n,t.c&&(t.c=t.c.replace(/:$/,""))}
function Zn (line 13) | function Zn(t,n){if(n){if(n=+n,isNaN(n)||0>n)throw Error("Bad port numbe...
function Qn (line 13) | function Qn(t,n,e){n instanceof se?(t.a=n,ve(t.a,t.f)):(e||(n=oe(n,qc)),...
function te (line 13) | function te(t,n,e){t.a.set(n,e)}
function ne (line 13) | function ne(t,n){return t.a.get(n)}
function ee (line 13) | function ee(t){return t instanceof Yn?new Yn(t):new Yn(t,void 0)}
function ie (line 13) | function ie(t,n){var e=new Yn(null,void 0);return $n(e,"https"),t&&(e.b=...
function re (line 13) | function re(t,n){return t?n?decodeURI(t.replace(/%25/g,"%2525")):decodeU...
function oe (line 13) | function oe(n,e,i){return t(n)?(n=encodeURI(n).replace(e,ae),i&&(n=n.rep...
function ae (line 13) | function ae(t){return t=t.charCodeAt(0),"%"+(t>>4&15).toString(16)+(15&t...
function se (line 13) | function se(t,n,e){this.b=this.a=null,this.c=t||null,this.f=!!e}
function ue (line 13) | function ue(t){t.a||(t.a=new An,t.b=0,t.c&&Jn(t.c,function(n,e){he(t,dec...
function ce (line 13) | function ce(t){var n=Gn(t);if(void 0===n)throw Error("Keys are undefined...
function he (line 13) | function he(t,n,e){ue(t),t.c=null,n=pe(t,n);var i=t.a.get(n);i||t.a.set(...
function fe (line 13) | function fe(t,n){ue(t),n=pe(t,n),En(t.a.b,n)&&(t.c=null,t.b-=t.a.get(n)....
function le (line 13) | function le(t,n){return ue(t),n=pe(t,n),En(t.a.b,n)}
function de (line 13) | function de(t,n,e){fe(t,n),0<e.length&&(t.c=null,t.a.set(pe(t,n),O(e)),t...
function pe (line 13) | function pe(t,n){return n+="",t.f&&(n=n.toLowerCase()),n}
function ve (line 13) | function ve(t,n){n&&!t.f&&(ue(t),t.c=null,t.a.forEach(function(t,n){var ...
function me (line 13) | function me(){}
function ge (line 13) | function ge(t){return t.c||(t.c=t.b())}
function be (line 13) | function be(){}
function we (line 13) | function we(t){if(!t.f&&"undefined"==typeof XMLHttpRequest&&"undefined"!...
function ye (line 13) | function ye(t){fn.call(this),this.headers=new An,this.w=t||null,this.b=!...
function Ie (line 13) | function Ie(t,n,e,i,r){if(t.a)throw Error("[goog.net.XhrIo] Object is ac...
function Te (line 13) | function Te(t){return Cu&&F(9)&&"number"==typeof t.timeout&&void 0!==t.o...
function Ae (line 13) | function Ae(t){return"content-type"==t.toLowerCase()}
function ke (line 13) | function ke(t,n){t.b=!1,t.a&&(t.c=!0,t.a.abort(),t.c=!1),t.g=n,Ee(t),Se(t)}
function Ee (line 13) | function Ee(t){t.A||(t.A=!0,ln(t,"complete"),ln(t,"error"))}
function Ne (line 13) | function Ne(t){if(t.b&&void 0!==su)if(t.v[1]&&4==Pe(t)&&2==Ce(t))Nn(t.J,...
function Se (line 13) | function Se(t,n){if(t.a){Oe(t);var e=t.a,r=t.v[0]?i:null;t.a=null,t.v=nu...
function Oe (line 13) | function Oe(t){t.a&&t.o&&(t.a.ontimeout=null),"number"==typeof t.m&&(uu....
function Pe (line 13) | function Pe(t){return t.a?t.a.readyState:0}
function Ce (line 13) | function Ce(t){try{return 2<Pe(t)?t.a.status:-1}catch(t){return-1}}
function Re (line 13) | function Re(t){try{return t.a?t.a.responseText:""}catch(n){return Nn(t.J...
function _e (line 13) | function _e(t,n){return n+" ["+t.I+" "+t.i+" "+Ce(t)+"]"}
function De (line 13) | function De(t){var n={},e=n.document||document,i=At(t),r=document.create...
function Le (line 13) | function Le(t){var n;return(n=(t||document).getElementsByTagName("HEAD")...
function xe (line 13) | function xe(){if(this&&this.Cb){var t=this.Cb;t&&"SCRIPT"==t.tagName&&Ue...
function Ue (line 13) | function Ue(t,n,e){null!=e&&uu.clearTimeout(e),t.onload=i,t.onerror=i,t....
function je (line 13) | function je(t,n){var e="Jsloader error (code #"+t+")";n&&(e+=": "+n),v.c...
function Me (line 13) | function Me(){}
function Ve (line 13) | function Ve(){this.a=new XDomainRequest,this.readyState=0,this.onreadyst...
function Fe (line 13) | function Fe(t,n){t.readyState=n,t.onreadystatechange&&t.onreadystatechan...
function Ke (line 13) | function Ke(){var t=ri();return Cu&&!!Mu&&11==Mu||/Edge\/\d+/.test(t)}
function qe (line 13) | function qe(){return uu.window&&uu.window.location.href||""}
function Xe (line 13) | function Xe(t,n){n=n||uu.window;var e="about:blank";t&&(e=St(Ot(t))),n.l...
function Be (line 13) | function Be(t,n){var e,i=[];for(e in t)e in n?typeof t[e]!=typeof n[e]?i...
function He (line 13) | function He(){var t=ri();return!((t=ei(t)!=nh?null:(t=t.match(/\sChrome\...
function We (line 13) | function We(t){return t=(t||ri()).toLowerCase(),!!(t.match(/android/)||t...
function Ge (line 13) | function Ge(t){t=t||uu.window;try{t.close()}catch(t){}}
function ze (line 13) | function ze(t,n,e){var i=""+Math.floor(1e9*Math.random());n=n||500,e=e||...
function Je (line 13) | function Je(t){return new Z(function(n){function e(){gn(2e3).then(functi...
function Ye (line 13) | function Ye(){var t=null;return new Z(function(n){"complete"==uu.documen...
function $e (line 13) | function $e(){return Ze(void 0)?Ye().then(function(){return new Z(functi...
function Ze (line 13) | function Ze(t){return t=t||ri(),!("file:"!==ci()||!t.toLowerCase().match...
function Qe (line 13) | function Qe(){var t=uu.window;try{return!(!t||t==t.top)}catch(t){return!1}}
function ti (line 13) | function ti(){return au.INTERNAL.hasOwnProperty("reactNative")?"ReactNat...
function ni (line 13) | function ni(){var t=ti();return"ReactNative"===t||"Node"===t}
function ei (line 13) | function ei(t){var n=t.toLowerCase();return b(n,"opera/")||b(n,"opr/")||...
function ii (line 13) | function ii(t,n){n=n||[];var e,i=[],r={};for(e in eh)r[eh[e]]=!0;for(e=0...
function ri (line 13) | function ri(){return uu.navigator&&uu.navigator.userAgent||""}
function oi (line 13) | function oi(t,n){t=t.split("."),n=n||uu;for(var e=0;e<t.length&&"object"...
function ai (line 13) | function ai(){try{var t=uu.localStorage,n=pi();if(t)return t.setItem(n,"...
function si (line 13) | function si(){return(ui()||"chrome-extension:"===ci()||Ze())&&!ni()&&ai()}
function ui (line 13) | function ui(){return"http:"===ci()||"https:"===ci()}
function ci (line 13) | function ci(){return uu.location&&uu.location.protocol||null}
function hi (line 13) | function hi(t){return t=t||ri(),!We(t)&&ei(t)!=th}
function fi (line 13) | function fi(t){return void 0===t?null:Mt(t)}
function li (line 13) | function li(t){var n,e={};for(n in t)t.hasOwnProperty(n)&&null!==t[n]&&v...
function di (line 13) | function di(t){if(null!==t)return JSON.parse(t)}
function pi (line 13) | function pi(t){return t||""+Math.floor(1e9*Math.random())}
function vi (line 13) | function vi(t){return t=t||ri(),"Safari"!=ei(t)&&!t.toLowerCase().match(...
function mi (line 13) | function mi(){var t=uu.___jsl;if(t&&t.H)for(var n in t.H)if(t.H[n].r=t.H...
function gi (line 13) | function gi(){var t=uu.navigator;return!t||"boolean"!=typeof t.onLine||!...
function bi (line 13) | function bi(t,n,e,i){if(t>n)throw Error("Short delay should be less than...
function wi (line 13) | function wi(){var t=uu.document;return!t||void 0===t.visibilityState||"v...
function yi (line 13) | function yi(){var t=uu.document,n=null;return wi()||!t?nt():new Z(functi...
function Ii (line 13) | function Ii(t){try{var n=new Date(parseInt(t,10));if(!isNaN(n.getTime())...
function Ti (line 13) | function Ti(t,n,e){ih?Object.defineProperty(t,n,{configurable:!0,enumera...
function Ai (line 13) | function Ai(t,n){if(n)for(var e in n)n.hasOwnProperty(e)&&Ti(t,e,n[e])}
function ki (line 13) | function ki(t){var n={};return Ai(n,t),n}
function Ei (line 13) | function Ei(t){var n,e={};for(n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);re...
function Ni (line 13) | function Ni(t,n){if(!n||!n.length)return!0;if(!t)return!1;for(var e=0;e<...
function Si (line 13) | function Si(t){var n=t;if("object"==typeof t&&null!=t){n="length"in t?[]...
function Oi (line 13) | function Oi(t){var n={},e=t[ah],i=t[sh];if(t=t[uh],!e||!t)throw Error("I...
function Pi (line 13) | function Pi(t,n){this.code=dh+t,this.message=n||ph[t]||""}
function Ci (line 13) | function Ci(t){var n=t&&t.code;return n?new Pi(n.substring(dh.length),t....
function Ri (line 13) | function Ri(t){var n=t[bh];if(void 0===n)throw new Pi("missing-continue-...
function _i (line 13) | function _i(t){var n={};n.continueUrl=t.h,n.canHandleCodeInApp=t.f,(n.an...
function Di (line 13) | function Di(t){this.b=t.sub,fu(),this.a=t.provider_id||t.firebase&&t.fir...
function Li (line 13) | function Li(t){if(t=t.split("."),3!=t.length)return null;t=t[1];for(var ...
function xi (line 13) | function xi(t){for(var n in Eh)if(Eh[n].Na==t)return Eh[n];return null}
function Ui (line 13) | function Ui(t){var n={};n["facebook.com"]=Vi,n["google.com"]=Ki,n["githu...
function ji (line 13) | function ji(t){var n=t[Sh];if(!n&&t[Nh]){var e=Li(t[Nh]);e&&e.a&&(n=e.a)...
function Mi (line 13) | function Mi(t){ji.call(this,t),t=di(t.rawUserInfo||"{}"),Ti(this,"profil...
function Vi (line 13) | function Vi(t){if(Mi.call(this,t),"facebook.com"!=this.providerId)throw ...
function Fi (line 13) | function Fi(t){if(Mi.call(this,t),"github.com"!=this.providerId)throw Er...
function Ki (line 13) | function Ki(t){if(Mi.call(this,t),"google.com"!=this.providerId)throw Er...
function qi (line 13) | function qi(t){if(Mi.call(this,t),"twitter.com"!=this.providerId)throw E...
function Xi (line 13) | function Xi(t,n){return t.then(function(t){if(t[Ph]){var e=Li(t[Ph]);if(...
function Bi (line 13) | function Bi(t,n){if(n.idToken||n.accessToken)n.idToken&&Ti(this,"idToken...
function Hi (line 13) | function Hi(t){var n={};return t.idToken&&(n.id_token=t.idToken),t.acces...
function Wi (line 13) | function Wi(t,n){this.rc=n||[],Ai(this,{providerId:t,isOAuthProvider:!0}...
function Gi (line 13) | function Gi(t){Wi.call(this,t,kh),this.a=[]}
function zi (line 13) | function zi(){Gi.call(this,"facebook.com")}
function Ji (line 13) | function Ji(t){if(!t)throw new Pi("argument-error","credential failed: e...
function Yi (line 13) | function Yi(){Gi.call(this,"github.com")}
function $i (line 13) | function $i(t){if(!t)throw new Pi("argument-error","credential failed: e...
function Zi (line 13) | function Zi(){Gi.call(this,"google.com"),this.sa("profile")}
function Qi (line 13) | function Qi(t,n){var e=t;return c(t)&&(e=t.idToken,n=t.accessToken),(new...
function tr (line 13) | function tr(){Wi.call(this,"twitter.com",Ah)}
function nr (line 13) | function nr(t,n){var e=t;if(c(e)||(e={oauthToken:t,oauthTokenSecret:n}),...
function er (line 13) | function er(t,n){this.a=t,this.f=n,Ti(this,"providerId","password")}
function ir (line 13) | function ir(){Ai(this,{providerId:"password",isOAuthProvider:!1})}
function rr (line 13) | function rr(t){if(!(t.Pa&&t.Oa||t.Da&&t.Y))throw new Pi("internal-error"...
function or (line 13) | function or(t){return t.a.Da&&t.a.Y?{temporaryProof:t.a.Da,phoneNumber:t...
function ar (line 13) | function ar(t){try{this.a=t||au.auth()}catch(t){throw new Pi("argument-e...
function sr (line 13) | function sr(t,n){if(!t)throw new Pi("missing-verification-id");if(!n)thr...
function ur (line 13) | function ur(t){if(t.temporaryProof&&t.phoneNumber)return new rr({Da:t.te...
function cr (line 13) | function cr(t){if(!t.isOAuthProvider)throw new Pi("invalid-oauth-provide...
function hr (line 13) | function hr(t,n,e,i,r){if(this.b=t,this.c=n||null,this.f=e||null,this.g=...
function fr (line 13) | function fr(t){return t=t||{},t.type?new hr(t.type,t.eventId,t.urlRespon...
function lr (line 13) | function lr(t){var n="unauthorized-domain",e=void 0,i=ee(t);t=i.b,i=i.c,...
function dr (line 13) | function dr(t,n,e){Pi.call(this,t,e),t=n||{},t.sb&&Ti(this,"email",t.sb)...
function pr (line 13) | function pr(t){if(t.code){var n=t.code||"";0==n.indexOf(dh)&&(n=n.substr...
function vr (line 13) | function vr(t){this.f=t}
function mr (line 13) | function mr(t,n,e){var i="Node"==ti();if(!(i=uu.XMLHttpRequest||i&&au.IN...
function gr (line 13) | function gr(t,n){n?t.a["X-Firebase-Locale"]=n:delete t.a["X-Firebase-Loc...
function br (line 13) | function br(t,n){n?(t.a["X-Client-Version"]=n,t.c["X-Client-Version"]=n)...
function wr (line 13) | function wr(t,n,e,i,r,o,a){gi()?(He()?t=l(t.m,t):(Oh||(Oh=new Z(function...
function yr (line 13) | function yr(t,n){((window.gapi||{}).client||{}).request?t():(uu[xh]=func...
function Ir (line 13) | function Ir(t,n){return new Z(function(e,i){"refresh_token"==n.grant_typ...
function Tr (line 13) | function Tr(t,n,e,i,r,o){var a=ee(t.g+n);te(a,"key",t.b),o&&te(a,"cb",""...
function Ar (line 13) | function Ar(t){if(!Yc.test(t.email))throw new Pi("invalid-email")}
function kr (line 13) | function kr(t){"email"in t&&Ar(t)}
function Er (line 13) | function Er(t,n){return jr(t,Kh,{identifier:n,continueUri:ui()?qe():"htt...
function Nr (line 13) | function Nr(t){return jr(t,Gh,{}).then(function(t){return t.authorizedDo...
function Sr (line 13) | function Sr(t){if(!t[Ph])throw new Pi("internal-error")}
function Or (line 13) | function Or(t){if(t.phoneNumber||t.temporaryProof){if(!t.phoneNumber||!t...
function Pr (line 13) | function Pr(t,n){return jr(t,Yh,n)}
function Cr (line 13) | function Cr(t,n,e){return jr(t,Xh,{idToken:n,deleteProvider:e})}
function Rr (line 13) | function Rr(t){if(!t.requestUri||!t.sessionId&&!t.postBody)throw new Pi(...
function _r (line 13) | function _r(t){var n=null;if(t.needConfirmation?(t.code="account-exists-...
function Dr (line 13) | function Dr(t,n){return n.returnIdpCredential=!0,jr(t,tf,n)}
function Lr (line 13) | function Lr(t,n){return n.returnIdpCredential=!0,jr(t,ef,n)}
function xr (line 13) | function xr(t,n){return n.returnIdpCredential=!0,n.autoCreate=!1,jr(t,nf...
function Ur (line 13) | function Ur(t){if(!t.oobCode)throw new Pi("invalid-action-code")}
function jr (line 13) | function jr(t,n,e){if(!Ni(e,n.ea))return et(new Pi("internal-error"));va...
function Mr (line 13) | function Mr(t){return Vr({error:{errors:[{message:t}],code:400,message:t...
function Vr (line 13) | function Vr(t,n){var e=(t.error&&t.error.errors&&t.error.errors[0]||{})....
function Fr (line 13) | function Fr(t){for(var n in cf)if(cf[n].id===t)return t=cf[n],{firebaseE...
function Kr (line 13) | function Kr(t){this.b=t,this.a=null,this.Ya=qr(this)}
function qr (line 13) | function qr(t){return Hr().then(function(){return new Z(function(n,e){oi...
function Xr (line 13) | function Xr(t,n){return t.Ya.then(function(){return new Z(function(e){t....
function Br (line 13) | function Br(t,n){t.Ya.then(function(){t.a.register("authEvent",n,oi("gap...
function Hr (line 13) | function Hr(){return df||(df=new Z(function(t,n){if(gi()){var e=function...
function Wr (line 13) | function Wr(t,n,e){this.i=t,this.g=n,this.h=e,this.f=null,this.a=ie(this...
function Gr (line 13) | function Gr(t,n,e,i,r){this.m=t,this.u=n,this.c=e,this.l=i,this.i=this.g...
function zr (line 13) | function zr(t){try{return au.app(t).auth().Ka()}catch(t){return[]}}
function Jr (line 13) | function Jr(t,n,e,i,r){this.u=t,this.f=n,this.b=e,this.c=i||null,this.h=...
function Yr (line 13) | function Yr(t){var n=qe();return Nr(t).then(function(t){t:{var e=ee(n),i...
function $r (line 13) | function $r(t){return t.l?t.l:(t.l=Ye().then(function(){if(!t.o){var n=t...
function Zr (line 13) | function Zr(t){return t.m||(t.v=t.c?ii(t.c,zr(t.b)):null,t.m=new mr(t.f,...
function Qr (line 13) | function Qr(t,n,e,i,r,o,a,s,u,c){return t=new Gr(t,n,e,i,r),t.h=o,t.g=a,...
function to (line 13) | function to(t){if(!t.i)throw Error("IfcHandler must be initialized!");Br...
function no (line 13) | function no(t){var n={type:"webStorageSupport"};return $r(t).then(functi...
function eo (line 13) | function eo(t){if(this.a=t||au.INTERNAL.reactNative&&au.INTERNAL.reactNa...
function io (line 13) | function io(){this.a={}}
function ro (line 13) | function ro(t,n,e,i,r,o){try{var a=!!uu.indexedDB}catch(t){a=!1}if(!a)th...
function oo (line 13) | function oo(t){return new Z(function(n,e){var i=t.o.open(t.u,t.m);i.oner...
function ao (line 13) | function ao(t){return t.i||(t.i=oo(t)),t.i}
function so (line 13) | function so(t,n){return n.objectStore(t.h)}
function uo (line 13) | function uo(t,n,e){return n.transaction([t.h],e?"readwrite":"readonly")}
function co (line 13) | function co(t){return new Z(function(n,e){t.onsuccess=function(t){t&&t.t...
function ho (line 13) | function ho(t){function n(){return t.b=gn(800).then(l(t.zc,t)).then(func...
function fo (line 13) | function fo(){if(!po()){if("Node"==ti())throw new Pi("internal-error","T...
function lo (line 13) | function lo(){try{var t=uu.localStorage,n=pi();return t&&(t.setItem(n,"1...
function po (line 13) | function po(){var t="Node"==ti();if(!(t=lo()||t&&au.INTERNAL.node&&au.IN...
function vo (line 13) | function vo(){}
function mo (line 13) | function mo(){if(!bo()){if("Node"==ti())throw new Pi("internal-error","T...
function go (line 13) | function go(){try{var t=uu.sessionStorage,n=pi();return t&&(t.setItem(n,...
function bo (line 13) | function bo(){var t="Node"==ti();if(!(t=go()||t&&au.INTERNAL.node&&au.IN...
function wo (line 13) | function wo(){var t={};t.Browser=gf,t.Node=bf,t.ReactNative=wf,this.a=t[...
function yo (line 13) | function yo(t){var n=new Pi("invalid-persistence-type"),e=new Pi("unsupp...
function Io (line 13) | function Io(t,n,e,i,r){this.i=t,this.g=n,this.A=e,this.u=i,this.v=r,this...
function To (line 13) | function To(){return mf||(mf=new Io("firebase",":",!(vi(ri())||!Qe()),hi...
function Ao (line 13) | function Ao(t,n){switch(n){case"session":return t.o;case"none":return t....
function ko (line 13) | function ko(t,n,e){return t.i+t.g+n.name+(e?t.g+e:"")}
function Eo (line 13) | function Eo(t,n,e){return e=ko(t,n,e),"local"==n.C&&(t.b[e]=null),Ao(t,n...
function No (line 13) | function No(t,n,e,i){n=ko(t,n,e),t.v&&(t.b[n]=uu.localStorage.getItem(n)...
function So (line 13) | function So(t,n,e){n=ko(t,cs("local"),n),t.a[n]&&(N(t.a[n],function(t){r...
function Oo (line 13) | function Oo(t){Po(t),t.f=setInterval(function(){for(var n in t.a){var e=...
function Po (line 13) | function Po(t){t.f&&(clearInterval(t.f),t.f=null)}
function Co (line 13) | function Co(t){Ao(t,"local").da(t.h),Po(t)}
function Ro (line 13) | function Ro(t){this.a=t,this.b=To()}
function _o (line 13) | function _o(t){return t.b.get(If,t.a).then(function(t){return fr(t)})}
function Do (line 13) | function Do(){this.a=To()}
function Lo (line 13) | function Lo(t,n,e,i,r,o,a){this.u=t,this.i=n,this.l=e,this.m=i||null,thi...
function xo (line 13) | function xo(t){return new Pi("invalid-cordova-configuration",t)}
function Uo (line 13) | function Uo(){for(var t=20,n=[];0<t;)n.push("1234567890abcdefghijklmnopq...
function jo (line 13) | function jo(t){var n=new Hn;Bn(n,t),t=[];var e=8*n.g;56>n.c?Bn(n,xc,56-n...
function Mo (line 13) | function Mo(t,n,e,i){var r=Uo(),o=new hr(n,i,null,r,new Pi("no-auth-even...
function Vo (line 13) | function Vo(t,n){for(var e=0;e<t.b.length;e++)try{t.b[e](n)}catch(t){}}
function Fo (line 13) | function Fo(t){return t.f||(t.f=t.ba().then(function(){return new Z(func...
function Ko (line 13) | function Ko(t){var n=null;return _o(t.g).then(function(e){return n=e,e=t...
function qo (line 13) | function qo(t){function n(n){r=!0,o&&o.cancel(),Ko(t).then(function(e){v...
function Xo (line 13) | function Xo(t){this.a=t,this.b=To()}
function Bo (line 13) | function Bo(t){return t.b.set(Tf,"pending",t.a)}
function Ho (line 13) | function Ho(t){return Eo(t.b,Tf,t.a)}
function Wo (line 13) | function Wo(t){return t.b.get(Tf,t.a).then(function(t){return"pending"==...
function Go (line 13) | function Go(t,n,e){this.v=t,this.l=n,this.u=e,this.h=[],this.f=!1,this.i...
function zo (line 13) | function zo(t,n,e,i){var r=au.SDK_VERSION||null;return Ze()?new Lo(t,n,e...
function Jo (line 13) | function Jo(t){t.f||(t.f=!0,t.a.ua(t.i));var n=t.a;return t.a.ba().s(fun...
function Yo (line 13) | function Yo(t){t.a.Db()&&Jo(t).s(function(n){var e=new hr("unknown",null...
function $o (line 13) | function $o(t,n,e,i,r,o){return t.a.vb(n,e,i,function(){t.f||(t.f=!0,t.a...
function Zo (line 13) | function Zo(t){return!(!t||"auth/cordova-not-ready"!=t.code)}
function Qo (line 13) | function Qo(t,n,e){var i=n+":"+e;return Ef[i]||(Ef[i]=new Go(t,n,e)),Ef[i]}
function ta (line 13) | function ta(){this.b=null,this.f=[],this.c=[],this.a=null,this.g=!1}
function na (line 13) | function na(t){t.g||(t.g=!0,oa(t,!1,null,null))}
function ea (line 13) | function ea(t,n,e){e=e.va(n.b,n.c);var i=n.f,r=n.g,o=!!n.b.match(/Redire...
function ia (line 13) | function ia(t,n){if(t.b=function(){return et(n)},t.c.length)for(var e=0;...
function ra (line 13) | function ra(t,n){if(t.b=function(){return nt(n)},t.f.length)for(var e=0;...
function oa (line 13) | function oa(t,n,e,i){n?i?ia(t,i):ra(t,e):ra(t,{user:null}),t.f=[],t.c=[]}
function aa (line 13) | function aa(t){var n=new Pi("timeout");t.a&&t.a.cancel(),t.a=gn(kf.get()...
function sa (line 13) | function sa(){}
function ua (line 13) | function ua(t,n){var e=t.c,i=t.b;return n.va(i,e)(t.f,t.g).then(function...
function ca (line 13) | function ca(t,n){this.a=n,Ti(this,"verificationId",t)}
function ha (line 13) | function ha(t,n,e,i){return new ar(t).Qa(n,e).then(function(t){return ne...
function fa (line 13) | function fa(t,n,e,i,r,o){if(this.h=t,this.i=n,this.g=e,this.c=i,this.f=r...
function la (line 13) | function la(t,n){return n?(t.a=t.c,t.g()):(n=t.a,t.a*=2,t.a>t.f&&(t.a=t....
function da (line 13) | function da(t,n){pa(t),t.b=gn(la(t,n)).then(function(){return t.l?nt():y...
function pa (line 13) | function pa(t){t.b&&(t.b.cancel(),t.b=null)}
function va (line 13) | function va(t){this.f=t,this.b=this.a=null,this.c=0}
function ma (line 13) | function ma(t,n){var e=n[Ph],i=n.refreshToken;n=ga(n.expiresIn),t.b=e,t....
function ga (line 13) | function ga(t){return fu()+1e3*parseInt(t,10)}
function ba (line 13) | function ba(t,n){return Ir(t.f,n).then(function(n){return t.b=n.access_t...
function wa (line 13) | function wa(t,n){this.a=t||null,this.b=n||null,Ai(this,{lastSignInTime:I...
function ya (line 13) | function ya(t){return new wa(t.a,t.b)}
function Ia (line 13) | function Ia(t,n,e,i,r,o){Ai(this,{uid:t,displayName:i||null,photoURL:r||...
function Ta (line 13) | function Ta(t,n){Bt.call(this,t);for(var e in n)this[e]=n[e]}
function Aa (line 13) | function Aa(t,n,e){this.A=[],this.G=t.apiKey,this.o=t.appName,this.w=t.a...
function ka (line 13) | function ka(t,n){t.W&&en(t.W,"languageCodeChanged",t.ra),(t.W=n)&&Zt(n,"...
function Ea (line 13) | function Ea(t,n){t.R=n,br(t.c,au.SDK_VERSION?ii(au.SDK_VERSION,t.R):null)}
function Na (line 13) | function Na(t,n){t.V&&en(t.V,"frameworkChanged",t.qa),(t.V=n)&&Zt(n,"fra...
function Sa (line 13) | function Sa(t){try{return au.app(t.o).auth()}catch(n){throw new Pi("inte...
function Oa (line 13) | function Oa(t){return new fa(function(){return t.F(!0)},function(t){retu...
function Pa (line 13) | function Pa(t){t.m||t.l.b||(t.l.start(),en(t,"tokenChanged",t.U),Zt(t,"t...
function Ca (line 13) | function Ca(t){en(t,"tokenChanged",t.U),pa(t.l)}
function Ra (line 13) | function Ra(t,n){t.pa=n,Ti(t,"_lat",n)}
function _a (line 13) | function _a(t,n){N(t.N,function(t){return t==n})}
function Da (line 13) | function Da(t){for(var n=[],e=0;e<t.N.length;e++)n.push(t.N[e](t));retur...
function La (line 13) | function La(t){t.a&&!t.I&&(t.I=!0,t.a.subscribe(t))}
function xa (line 13) | function xa(t,n){Ai(t,{uid:n.uid,displayName:n.displayName||null,photoUR...
function Ua (line 13) | function Ua(){}
function ja (line 13) | function ja(t){return nt().then(function(){if(t.m)throw new Pi("app-dele...
function Ma (line 13) | function Ma(t){return Au(t.providerData,function(t){return t.providerId})}
function Va (line 13) | function Va(t,n){n&&(Fa(t,n.providerId),t.providerData.push(n))}
function Fa (line 13) | function Fa(t,n){N(t.providerData,function(t){return t.providerId==n})}
function Ka (line 13) | function Ka(t,n,e){("uid"!=n||e)&&t.hasOwnProperty(n)&&Ti(t,n,e)}
function qa (line 13) | function qa(t,n){t!=n&&(Ai(t,{uid:n.uid,displayName:n.displayName,photoU...
function Xa (line 13) | function Xa(t){return t.F().then(function(n){var e=t.isAnonymous;return ...
function Ba (line 13) | function Ba(t,n){n[Ph]&&t.pa!=n[Ph]&&(ma(t.h,n),ln(t,new Ta("tokenChange...
function Ha (line 13) | function Ha(t,n){return jr(t.c,Bh,{idToken:n}).then(l(t.kc,t))}
function Wa (line 13) | function Wa(t){return(t=t.providerUserInfo)&&t.length?Au(t,function(t){r...
function Ga (line 13) | function Ga(t,n){return Xa(t).then(function(){if(k(Ma(t),n))return Da(t)...
function za (line 13) | function za(t,n,e){var i=ur(n);return n=Ui(n),ki({user:t,credential:i,ad...
function Ja (line 13) | function Ja(t,n){return Ba(t,n),t.reload().then(function(){return t})}
function Ya (line 13) | function Ya(t,n,e,i,r){if(!si())return et(new Pi("operation-not-supporte...
function $a (line 13) | function $a(t,n,e,i,r){if(!si())return et(new Pi("operation-not-supporte...
function Za (line 13) | function Za(t){if(!t.a||!t.I){if(t.a&&!t.I)throw new Pi("internal-error"...
function Qa (line 13) | function Qa(t,n,e){var i=ts(t,n,e);return t.A.push(i),at(i,function(){E(...
function ts (line 13) | function ts(t,n,e){return t.i&&!e?(n.cancel(),et(t.i)):n.s(function(n){t...
function ns (line 13) | function ns(t){if(!t.apiKey)return null;var n={apiKey:t.apiKey,authDomai...
function es (line 13) | function es(t,n,e,i){var r=new Aa(t,n);return e&&(r.ca=e),i&&Ea(r,i),r.r...
function is (line 13) | function is(t){this.a=t,this.b=To()}
function rs (line 13) | function rs(t){return Eo(t.b,Nf,t.a)}
function os (line 13) | function os(t,n){return t.b.get(Nf,t.a).then(function(t){return t&&n&&(t...
function as (line 13) | function as(t,n){this.a=t,this.b=n||To(),this.c=null,this.f=us(this),No(...
function ss (line 13) | function ss(t,n){var e,i=[];for(e in yf)yf[e]!==n&&i.push(Eo(t.b,cs(yf[e...
function us (line 13) | function us(t){var n=cs("local"),e=cs("session"),i=cs("none");return t.b...
function cs (line 13) | function cs(t){return{name:"authUser",C:t}}
function hs (line 13) | function hs(t){return ps(t,function(){return t.b.set(Sf,t.c.C,t.a)})}
function fs (line 13) | function fs(t,n){return ps(t,function(){return t.b.set(t.c,n.B(),t.a)})}
function ls (line 13) | function ls(t){return ps(t,function(){return Eo(t.b,t.c,t.a)})}
function ds (line 13) | function ds(t,n){return ps(t,function(){return t.b.get(t.c,t.a).then(fun...
function ps (line 13) | function ps(t,n){return t.f=t.f.then(n,n),t.f}
function vs (line 13) | function vs(t){if(this.l=!1,Ti(this,"app",t),!Ss(this).options||!Ss(this...
function ms (line 13) | function ms(t){Bt.call(this,"languageCodeChanged"),this.h=t}
function gs (line 13) | function gs(t){Bt.call(this,"frameworkChanged"),this.f=t}
function bs (line 13) | function bs(t){Object.defineProperty(t,"lc",{get:function(){return this....
function ws (line 13) | function ws(t){return t.Jb||et(new Pi("auth-domain-config-required"))}
function ys (line 13) | function ys(t){var n=Ss(t).options.authDomain,e=Ss(t).options.apiKey;n&&...
function Is (line 13) | function Is(t,n){var e={};return e.apiKey=Ss(t).options.apiKey,e.authDom...
function Ts (line 13) | function Ts(t,n){Os(t)&&(_a(Os(t),t.Ga),en(Os(t),"tokenChanged",t.pa),en...
function As (line 13) | function As(t){var n=os(t.G,Ss(t).options.authDomain).then(function(n){r...
function ks (line 13) | function ks(t){var n=Ss(t).options.authDomain,e=As(t).then(function(){re...
function Es (line 13) | function Es(t){return t.U.then(function(){return t.aa()}).s(function(){}...
function Ns (line 13) | function Ns(t,n){var e=null,i=null;return _s(t,n.then(function(n){return...
function Ss (line 13) | function Ss(t){return t.app}
function Os (line 13) | function Os(t){return t.currentUser}
function Ps (line 13) | function Ps(t){return Os(t)&&Os(t)._lat||null}
function Cs (line 13) | function Cs(t){if(t.W){for(var n=0;n<t.m.length;n++)t.m[n]&&t.m[n](Ps(t)...
function Rs (line 13) | function Rs(t,n){t.I.push(n),_s(t,t.i.then(function(){!t.l&&k(t.I,n)&&t....
function _s (line 13) | function _s(t,n){return t.N.push(n),at(n,function(){E(t.N,n)}),n}
function Ds (line 13) | function Ds(t,n,e,i){t:{e=Array.prototype.slice.call(e);for(var r=0,o=!1...
function Ls (line 13) | function Ls(n,e){return{name:n||"",K:"a valid string",optional:!!e,M:t}}
function xs (line 13) | function xs(){return{name:"opt_forceRefresh",K:"a boolean",optional:!0,M...
function Us (line 13) | function Us(t,n){return{name:t||"",K:"a valid object",optional:!!n,M:c}}
function js (line 13) | function js(t,n){return{name:t||"",K:"a function",optional:!!n,M:u}}
function Ms (line 13) | function Ms(t,n){return{name:t||"",K:"null",optional:!!n,M:o}}
function Vs (line 13) | function Vs(){return{name:"",K:"an HTML element",optional:!1,M:function(...
function Fs (line 13) | function Fs(){return{name:"auth",K:"an instance of Firebase Auth",option...
function Ks (line 13) | function Ks(){return{name:"app",K:"an instance of Firebase App",optional...
function qs (line 13) | function qs(t){return{name:t?t+"Credential":"credential",K:t?"a valid "+...
function Xs (line 13) | function Xs(){return{name:"authProvider",K:"a valid Auth provider",optio...
function Bs (line 13) | function Bs(){return{name:"applicationVerifier",K:"an implementation of ...
function Hs (line 13) | function Hs(t,n,e,i){return{name:e||"",K:t.K+" or "+n.K,optional:!!i,M:f...
function Ws (line 13) | function Ws(t,n,e,i,r,o){if(Ti(this,"type","recaptcha"),this.b=this.c=nu...
function Gs (line 13) | function Gs(t,n){for(var e=0;e<t.i.length;e++)try{t.i[e](n)}catch(t){}}
function zs (line 13) | function zs(t,n){N(t.i,function(t){return t==n})}
function Js (line 13) | function Js(t,n){return t.g.push(n),at(n,function(){E(t.g,n)}),n}
function Ys (line 13) | function Ys(t){if(t.m)throw new Pi("internal-error","RecaptchaVerifier i...
function $s (line 13) | function $s(){this.b=uu.grecaptcha?1/0:0,this.c=null,this.a="__rcb"+Math...
function Zs (line 13) | function Zs(t,n){return new Z(function(e,i){if(gi())if(!uu.grecaptcha||n...
function Qs (line 13) | function Qs(){return Lf||(Lf=new $s),Lf}
function tu (line 13) | function tu(t,n,e){try{this.f=e||au.app()}catch(t){throw new Pi("argumen...
function nu (line 13) | function nu(t,n){for(var e in n){var i=n[e].name;t[i]=iu(i,t[e],n[e].j)}}
function eu (line 13) | function eu(t,n,e,i){t[n]=iu(n,e,i)}
function iu (line 13) | function iu(t,n,e){function i(){var t=Array.prototype.slice.call(argumen...
function ru (line 13) | function ru(t){return t=t.split("."),t[t.length-1]}
function e (line 20) | function e(e,t){if(void 0===t){this.n=e.split("/");for(var n=0,r=0;r<thi...
function e (line 20) | function e(e,t){this.o=t,this.u=e.slice(),this.l=Math.max(1,this.u.lengt...
function r (line 20) | function r(e){a=e}
function i (line 20) | function i(e){s=e}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(){return null!==e&&e.apply(this,arguments)||this}
function r (line 20) | function r(){this.constructor=t}
function e (line 20) | function e(e,t,n){this._=e,this.y=t,this.g=n,this.m=null,this.y&&l.valid...
function t (line 20) | function t(){return e.call(this,new s.SortedMap(f.NAME_COMPARATOR),_.EMP...
function e (line 20) | function e(e,t){this.name=e,this.node=t}
function e (line 20) | function e(e,t,n,i){this.fromUser=e,this.fromServer=t,this.queryId=n,thi...
function e (line 20) | function e(e,t,n,r,i){this.type=e,this.snapshotNode=t,this.childName=n,t...
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(){return null!==e&&e.apply(this,arguments)||this}
function r (line 20) | function r(e,t){if(void 0===t&&(t=null),null===e)return i.ChildrenNode.E...
function e (line 20) | function e(){}
function e (line 20) | function e(t,n){void 0===n&&(n=e.__childrenNodeConstructor.EMPTY_NODE),t...
function e (line 20) | function e(e,t,n,r,i){void 0===i&&(i=null),this.I=r,this.R=i,this.O=[];f...
function e (line 20) | function e(t,n,r,i,o){this.key=t,this.value=n,this.color=null!=r?r:e.RED...
function e (line 20) | function e(){}
function e (line 20) | function e(t,n){void 0===n&&(n=e.EMPTY_NODE),this.U=t,this.B=n}
function e (line 20) | function e(e,t,n){var r=this;this.H=e,this.app=n,this.dataUpdateCount=0,...
function e (line 20) | function e(e,t,n){this._e=e,this.ye=t,this.ve=n}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(t,n){if(!(t instanceof l.Repo))throw Error("new Reference() n...
function e (line 20) | function e(e,t,n){this._e=e,this.ge=t,this.me=n}
function e (line 20) | function e(e,t){void 0===t&&(t=u()),this.value=e,this.children=t}
function e (line 20) | function e(e){this.me=e}
function e (line 20) | function e(){}
function e (line 20) | function e(){this.Te={},this.we=!1}
function e (line 20) | function e(e){this.Ie=e,e instanceof s.Repo||r.fatal("Don't call new Dat...
function e (line 20) | function e(e){this.database=e}
function r (line 20) | function r(e){for(var t="",n=e.split("/"),r=0;r<n.length;r++)if(n[r].len...
function e (line 20) | function e(e,t,n,r,i){void 0===i&&(i=""),this.secure=t,this.namespace=n,...
function e (line 20) | function e(e,t){this.Ie=e,this.Oe=t}
function e (line 20) | function e(e,t,n,r){this.repo=e,this.path=t,this.Ae=n,this.De=r}
function r (line 20) | function r(e){i=e}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(){return null!==e&&e.apply(this,arguments)||this}
function e (line 20) | function e(e,t){this.ke=e,this.We=t}
function e (line 20) | function e(e){this.count=function(e){return parseInt(Math.log(e)/o,10)}(...
function r (line 20) | function r(e,t){return o.nameCompare(e.name,t.name)}
function i (line 20) | function i(e,t){return o.nameCompare(e,t)}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(t){var n=e.call(this)||this;return n.Qe=t,i.assert(!t.isEmpty...
function e (line 20) | function e(){this.T=null,this._=null}
function e (line 20) | function e(){this.set={}}
function e (line 20) | function e(e,t,n){this.source=e,this.path=t,this.snap=n,this.type=r.Oper...
function e (line 20) | function e(){this.qe={}}
function e (line 20) | function e(e,t){this.Ue=e,this.Be=t}
function e (line 20) | function e(e){this.He=e,this.Ge=null}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(n,r,i,o,a,s){var l=e.call(this)||this;if(l.H=n,l.ee=r,l.te=i,...
function e (line 20) | function e(e){this.Vt=e,this.Qt={},r.assert(Array.isArray(e)&&e.length>0...
function e (line 20) | function e(e,t,n,i,o,s,u){this.id=e,this.H=t,this.Ut=n,this.At=i,this.z=...
function e (line 20) | function e(e,t,n,i){this.connId=e,this.repoInfo=t,this.transportSessionI...
function e (line 20) | function e(n,o,a,s){if(this.onDisconnect=a,this.urlFn=s,this.outstanding...
function r (line 20) | function r(e){d=e}
function t (line 20) | function t(e,n,r,i){this.connId=e,this.keepaliveTimer=null,this.frames=n...
function e (line 20) | function e(){}
function e (line 20) | function e(t){this.Vn=new r.IndexedFilter(t.getIndex()),this.me=t.getInd...
function r (line 20) | function r(t){var n=t.INTERNAL.registerService("database",function(e,t,n...
function e (line 20) | function e(e){this.Hn=e,this.Gn="firebase:"}
function e (line 20) | function e(){this.Yn={},this.isInMemoryStorage=!0}
function e (line 20) | function e(e,t){this.committed=e,this.snapshot=t}
function e (line 20) | function e(e,t,n){this.Xn=e,this.zn=t,this.Jn=n}
function e (line 20) | function e(e,t,n){this.$n=e,this.zn=t,this.Jn=n}
function e (line 20) | function e(e,t,n,r){this.eventType=e,this.eventRegistration=t,this.snaps...
function e (line 20) | function e(e,t,n){this.eventRegistration=e,this.error=t,this.path=n}
function e (line 20) | function e(e){this.Zn=e,this.er=u.ImmutableTree.Empty,this.tr=new _.Writ...
function e (line 20) | function e(e,t,n){this.path=e,this.affectedTree=t,this.revert=n,this.typ...
function e (line 20) | function e(e,t){this.source=e,this.path=t,this.type=i.OperationType.LIST...
function e (line 20) | function e(e,t,n){this.source=e,this.path=t,this.children=n,this.type=r....
function e (line 20) | function e(e,t){this.mr=e,this.Cr=[];var n=this.mr.getQueryParams(),l=ne...
function e (line 20) | function e(e,t){this.viewCache=e,this.changes=t}
function e (line 20) | function e(e){this.Sr=e}
function e (line 20) | function e(){this.kr={}}
function e (line 20) | function e(){}
function e (line 20) | function e(e,t,n){void 0===n&&(n=null),this.jr=e,this.Nr=t,this.Vr=n}
function e (line 20) | function e(e){this.mr=e,this.me=this.mr.getQueryParams().getIndex()}
function e (line 20) | function e(){this.Br=a.CompoundWrite.Empty,this.Hr=[],this.Gr=-1}
function e (line 20) | function e(e,t){this.Jr=e,this.$r=t}
function e (line 20) | function e(e){this.$r=e}
function e (line 20) | function e(){this.ei=r.ChildrenNode.EMPTY_NODE}
function e (line 20) | function e(e){this.ti=e}
function e (line 20) | function e(){this.ni={}}
function e (line 20) | function e(e,t){this.Z=t,this.ri={},this.G=new o.StatsListener(e);var n=...
function e (line 20) | function e(){this.oi=[],this.ai=0}
function e (line 20) | function e(e){this.Oe=e,this.ui=[]}
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(){var t,n,r=e.call(this,["visible"])||this;return"undefined"!...
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(){var t=e.call(this,["online"])||this;return t.li=!0,"undefin...
function e (line 20) | function e(e){this.hi(e)}
function e (line 20) | function e(e){this.Ut=e,this.pendingResponses=[],this.currentResponseNum...
function r (line 20) | function r(){this.constructor=t}
function t (line 20) | function t(t,n,r){var i=e.call(this)||this;return i.H=t,i.ee=n,i.Ke=r,i....
function e (line 20) | function e(){this.fi=!1,this._i=!1,this.yi=!1,this.vi=!1,this.gi=!1,this...
function e (line 20) | function e(e){this.Ii=new r.RangedFilter(e),this.me=e.getIndex(),this.mi...
function e (line 20) | function e(){this.children={},this.childCount=0,this.value=null}
function e (line 20) | function e(e,t,n){void 0===e&&(e=""),void 0===t&&(t=null),void 0===n&&(n...
function n (line 27) | function n(e){var t=new Uint8Array(e);return window.btoa(String.fromChar...
function o (line 27) | function o(e){var t=function(e){return self&&"ServiceWorkerGlobalScope"i...
function e (line 27) | function e(){this.e=new s.ErrorFactory("messaging","Messaging",u.map),th...
function e (line 27) | function e(e){var t=this;if(this.e=new s.ErrorFactory("messaging","Messa...
function n (line 27) | function n(){this.constructor=t}
function t (line 27) | function t(t){var r=e.call(this,t)||this;return r.d=null,r.f=Object(s.cr...
function n (line 27) | function n(){this.constructor=t}
function t (line 27) | function t(t){var r=e.call(this,t)||this;return self.addEventListener("p...
function r (line 34) | function r(t){return"storage/"+t}
function o (line 34) | function o(){return new te(ee.UNKNOWN,"An unknown error occurred, please...
function i (line 34) | function i(t){return new te(ee.OBJECT_NOT_FOUND,"Object '"+t+"' does not...
function a (line 34) | function a(t){return new te(ee.QUOTA_EXCEEDED,"Quota for bucket '"+t+"' ...
function s (line 34) | function s(){return new te(ee.UNAUTHENTICATED,"User is not authenticated...
function u (line 34) | function u(t){return new te(ee.UNAUTHORIZED,"User does not have permissi...
function c (line 34) | function c(){return new te(ee.RETRY_LIMIT_EXCEEDED,"Max retry time for o...
function l (line 34) | function l(){return new te(ee.CANCELED,"User canceled the upload/downloa...
function h (line 34) | function h(t){return new te(ee.INVALID_URL,"Invalid URL '"+t+"'.")}
function p (line 34) | function p(t){return new te(ee.INVALID_DEFAULT_BUCKET,"Invalid default b...
function f (line 34) | function f(){return new te(ee.CANNOT_SLICE_BLOB,"Cannot slice blob for u...
function d (line 34) | function d(){return new te(ee.SERVER_FILE_WRONG_SIZE,"Server recorded in...
function _ (line 34) | function _(){return new te(ee.NO_DOWNLOAD_URL,"The given file does not h...
function v (line 34) | function v(t,e,n){return new te(ee.INVALID_ARGUMENT,"Invalid argument in...
function b (line 34) | function b(t,e,n,r){var o,i;return t===e?(o=t,i=1===t?"argument":"argume...
function m (line 34) | function m(){return new te(ee.APP_DELETED,"The Firebase app was deleted.")}
function g (line 34) | function g(t){return new te(ee.INVALID_ROOT_OPERATION,"The operation '"+...
function y (line 34) | function y(t,e){return new te(ee.INVALID_FORMAT,"String does not match f...
function R (line 34) | function R(t){throw new te(ee.INTERNAL_ERROR,"Internal error: "+t)}
function E (line 34) | function E(t){switch(t){case ne.RAW:case ne.BASE64:case ne.BASE64URL:cas...
function w (line 34) | function w(t,e){switch(t){case ne.RAW:return new re(U(e));case ne.BASE64...
function U (line 34) | function U(t){for(var e=[],n=0;n<t.length;n++){var r=t.charCodeAt(n);if(...
function T (line 34) | function T(t){var e;try{e=decodeURIComponent(t)}catch(t){throw y(ne.DATA...
function A (line 34) | function A(t,e){switch(t){case ne.BASE64:var n=-1!==e.indexOf("-"),r=-1!...
function N (line 34) | function N(t){var e=new oe(t);return e.base64?A(ne.BASE64,e.rest):T(e.re...
function O (line 34) | function O(t){return new oe(t).contentType}
function C (line 34) | function C(t,e){return!!(t.length>=e.length)&&t.substring(t.length-e.len...
function S (line 34) | function S(t){switch(t){case ae.RUNNING:case ae.PAUSING:case ae.CANCELIN...
function k (line 34) | function k(t,e){return Object.prototype.hasOwnProperty.call(t,e)}
function I (line 34) | function I(t,e){for(var n in t)k(t,n)&&e(n,t[n])}
function L (line 34) | function L(t){if(null==t)return{};var e={};return I(t,function(t,n){e[t]...
function P (line 34) | function P(t){return new Promise(t)}
function x (line 34) | function x(t){return Promise.resolve(t)}
function D (line 34) | function D(t){return Promise.reject(t)}
function M (line 34) | function M(t){return null!=t}
function W (line 34) | function W(t){return void 0!==t}
function B (line 34) | function B(t){return"function"==typeof t}
function G (line 34) | function G(t){return"object"==typeof t}
function j (line 34) | function j(t){return G(t)&&null!==t}
function q (line 34) | function q(t){return G(t)&&!Array.isArray(t)}
function F (line 34) | function F(t){return"string"==typeof t||t instanceof String}
function H (line 34) | function H(t){return"number"==typeof t||t instanceof Number}
function z (line 34) | function z(t){return X()&&t instanceof Blob}
function X (line 34) | function X(){return"undefined"!=typeof Blob}
function V (line 34) | function V(t){var e;try{e=JSON.parse(t)}catch(t){return null}return q(e)...
function K (line 34) | function K(t){if(0==t.length)return null;var e=t.lastIndexOf("/");return...
function Z (line 34) | function Z(t,e){var n=e.split("/").filter(function(t){return t.length>0}...
function J (line 34) | function J(t){var e=t.lastIndexOf("/",t.length-2);return-1===e?t:t.slice...
function Q (line 34) | function Q(t){return Vt+Zt+t}
function Y (line 34) | function Y(t){return Kt+Zt+t}
function $ (line 34) | function $(t){return Vt+Jt+t}
function tt (line 34) | function tt(t){var e=encodeURIComponent,n="?";return I(t,function(t,r){v...
function et (line 34) | function et(t,e){return e}
function nt (line 34) | function nt(t){return!F(t)||t.length<2?t:(t=t,J(t))}
function rt (line 34) | function rt(){function t(t,e){return nt(e)}function e(t,e){return M(e)?+...
function ot (line 34) | function ot(t,e){function n(){var n=t.bucket,r=t.fullPath,o=new le(n,r);...
function it (line 34) | function it(t,e,n){var r={};r.type="file";for(var o=n.length,i=0;i<o;i++...
function at (line 34) | function at(t,e,n){var r=V(e);return null===r?null:it(t,r,n)}
function st (line 34) | function st(t,e){for(var n={},r=e.length,o=0;o<r;o++){var i=e[o];i.writa...
function ut (line 34) | function ut(t){if(!t||!G(t))throw"Expected Metadata object.";for(var e i...
function ct (line 34) | function ct(t,e,n){for(var r=e.length,o=e.length,i=0;i<e.length;i++)if(e...
function lt (line 34) | function lt(t,e){return function(n){t(n),e(n)}}
function ht (line 34) | function ht(t,e){function n(t){if(!F(t))throw"Expected string."}var r;re...
function pt (line 34) | function pt(){function t(t){if(!(t instanceof Uint8Array||t instanceof A...
function ft (line 34) | function ft(t){return new fe(ut,t)}
function dt (line 34) | function dt(){function t(t){if(!(H(t)&&t>=0))throw"Expected a number 0 o...
function _t (line 34) | function _t(t,e){function n(e){if(!(null===e||M(e)&&e instanceof Object)...
function vt (line 34) | function vt(t){function e(t){if(null!==t&&!B(t))throw"Expected a Functio...
function bt (line 34) | function bt(){return"undefined"!=typeof BlobBuilder?BlobBuilder:"undefin...
function mt (line 34) | function mt(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];...
function gt (line 34) | function gt(t,e,n){return t.webkitSlice?t.webkitSlice(e,n):t.mozSlice?t....
function yt (line 34) | function yt(t,e){return-1!==t.indexOf(e)}
function Rt (line 34) | function Rt(t){return Array.prototype.slice.call(t)}
function Et (line 34) | function Et(t,e){var n=t.indexOf(e);-1!==n&&t.splice(n,1)}
function wt (line 34) | function wt(t){if(!t)throw o()}
function Ut (line 34) | function Ut(t,e){function n(n,r){var o=at(t,r,e);return wt(null!==o),o}r...
function Tt (line 34) | function Tt(t){function e(e,n){var r;return r=401===e.getStatus()?s():40...
function At (line 34) | function At(t){function e(e,r){var o=n(e,r);return 404===e.getStatus()&&...
function Nt (line 34) | function Nt(t,e,n){var r=e.fullServerUrl(),o=Q(r),i=t.maxOperationRetryT...
function Ot (line 34) | function Ot(t,e,n,r){var o=e.fullServerUrl(),i=Q(o),a=st(n,r),s={"Conten...
function Ct (line 34) | function Ct(t,e){function n(t,e){}var r=e.fullServerUrl(),o=Q(r),i=t.max...
function St (line 34) | function St(t,e){return t&&t.contentType||e&&e.type()||"application/octe...
function kt (line 34) | function kt(t,e,n){var r=L(n);return r.fullPath=t.path,r.size=e.size(),r...
function It (line 34) | function It(t,e,n,r,o){var i=e.bucketOnlyServerUrl(),a={"X-Goog-Upload-P...
function Lt (line 34) | function Lt(t,e){var n;try{n=t.getResponseHeader("X-Goog-Upload-Status")...
function Pt (line 34) | function Pt(t,e,n,r,o){function i(t,e){Lt(t);var n;try{n=t.getResponseHe...
function xt (line 34) | function xt(t,e,n,r){function o(t,e){var n,o=Lt(t,["active","final"]);tr...
function Dt (line 34) | function Dt(t,e,n,r,o,i,a,s){function u(t,n){var o,a=Lt(t,["active","fin...
function Mt (line 34) | function Mt(t){return function(){for(var e=[],n=0;n<arguments.length;n++...
function Wt (line 34) | function Wt(t,e,n){function r(){return 2===h}function o(){p||(p=!0,e.app...
function Bt (line 34) | function Bt(t){t(!1)}
function Gt (line 34) | function Gt(t,e){null!==e&&e.length>0&&(t.Authorization="Firebase "+e)}
function jt (line 34) | function jt(t){var e=void 0!==Xt.default?Xt.default.SDK_VERSION:"AppMana...
function qt (line 34) | function qt(t,e,n){var r=tt(t.urlParams),o=t.url+r,i=L(t.headers);return...
function Ft (line 34) | function Ft(t,e,n){return new Ae(t,new ce,n)}
function Ht (line 34) | function Ht(t){var e={TaskState:se,TaskEvent:ie,StringFormat:ne,Storage:...
function t (line 34) | function t(t,e){this.t=r(t),this.e="Firebase Storage: "+e,this.n=null,th...
function t (line 34) | function t(t,e){this.data=t,this.contentType=e||null}
function t (line 34) | function t(t){this.base64=!1,this.contentType=null;var e=t.match(/^data:...
function t (line 34) | function t(){var t=this;this.o=!1,this.i=new XMLHttpRequest,this.a=zt.NO...
function t (line 34) | function t(){}
function t (line 34) | function t(t,e){this.bucket=t,this.u=e}
function n (line 34) | function n(t){"/"===t.path.charAt(t.path.length-1)&&(t.u=t.u.slice(0,-1))}
function r (line 34) | function r(t){t.u=decodeURIComponent(t.path)}
function t (line 34) | function t(t,e,n,r){this.server=t,this.local=e||t,this.writable=!!n,this...
function t (line 34) | function t(t,e){var n=this;this.validator=function(e){n.optional&&!W(e)|...
function t (line 34) | function t(t,e){var n=0,r="";z(t)?(this.c=t,n=t.size,r=t.type):t instanc...
function t (line 34) | function t(t,e,n,r){this.url=t,this.method=e,this.handler=n,this.timeout...
function t (line 34) | function t(t,e,n,r){this.current=t,this.total=e,this.finalized=!!n,this....
function t (line 34) | function t(t,e,n){if(B(t)||M(e)||M(n))this.next=t,this.error=e||null,thi...
function t (line 34) | function t(t,e,n,r,o,i){this.bytesTransferred=t,this.totalBytes=e,this.s...
function t (line 34) | function t(t,e,n,r,o,i){void 0===i&&(i=null);var a=this;this.p=0,this.f=...
function o (line 34) | function o(e){if(t!==ie.STATE_CHANGED)throw"Expected one of the event ty...
function i (line 34) | function i(t){try{return void c(t)}catch(t){}try{if(l(t),!(W(t.next)||W(...
function a (line 34) | function a(t){function e(e,n,o){null!==t&&ct("on",t,arguments);var i=new...
function s (line 34) | function s(t){if(null===t)throw u;i(t)}
function t (line 34) | function t(t,e){this.authWrapper=t,this.location=e instanceof le?e:le.ma...
function t (line 34) | function t(t){this.D=D(t)}
function t (line 34) | function t(){this.$={},this.tt=$t}
function e (line 34) | function e(){delete r.$[n]}
function t (line 34) | function t(e,n,r,o,i){if(this.et=null,this.nt=!1,this.rt=e,null!==this.r...
function t (line 34) | function t(t,e,n,r,o,i,a,s,u,c,l){this.pt=null,this.ft=null,this.y=null,...
function t (line 34) | function t(t,e){function r(t){var e=t.loaded,r=t.lengthComputable?t.tota...
function e (line 34) | function e(t,e){var r=n.y,i=n.R,a=e.xhr;if(e.wasSuccessCode)try{var s=n....
function t (line 34) | function t(t,e,n){this.wasSuccessCode=t,this.xhr=e,this.canceled=!!n}
function t (line 34) | function t(t,e,n){function r(t,e){return new ye(t,e)}if(this.et=null,thi...
function e (line 34) | function e(t){if(/^[A-Za-z]+:\/\//.test(t))throw"Expected child path but...
function e (line 34) | function e(t){if(!/^[A-Za-z]+:\/\//.test(t))throw"Expected full URL but ...
function t (line 34) | function t(t){this.ut=t}
FILE: lib/font-detective.js
function s (line 1) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
function Font (line 50) | function Font(name, type, style) {
FILE: lib/gif.js/gif.js
function r (line 2) | function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==...
function EventEmitter (line 2) | function EventEmitter(){this._events=this._events||{};this._maxListeners...
function g (line 2) | function g(){this.removeListener(type,g);if(!fired){fired=true;listener....
function isFunction (line 2) | function isFunction(arg){return typeof arg==="function"}
function isNumber (line 2) | function isNumber(arg){return typeof arg==="number"}
function isObject (line 2) | function isObject(arg){return typeof arg==="object"&&arg!==null}
function isUndefined (line 2) | function isUndefined(arg){return arg===void 0}
function ctor (line 2) | function ctor(){this.constructor=child}
function GIF (line 2) | function GIF(options){var base,key,value;this.running=false;this.options...
FILE: lib/gif.js/gif.worker.js
function r (line 2) | function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==...
function ByteArray (line 2) | function ByteArray(){this.page=-1;this.pages=[];this.newPage()}
function GIFEncoder (line 2) | function GIFEncoder(width,height){this.width=~~width;this.height=~~heigh...
function LZWEncoder (line 2) | function LZWEncoder(width,height,pixels,colorDepth){var initCodeSize=Mat...
function NeuQuant (line 2) | function NeuQuant(pixels,samplefac){var network;var netindex;var bias;va...
FILE: lib/imagetracer_v1.2.5.js
function ImageTracer (line 40) | function ImageTracer(){
FILE: lib/os-gui/$Window.js
function element_to_string (line 12) | function element_to_string(element) {
function find_tabstops (line 36) | function find_tabstops(container_el) {
function $Window (line 113) | function $Window(options = {}) {
function $FormWindow (line 1758) | function $FormWindow(title) {
FILE: lib/os-gui/MenuBar.js
function E (line 9) | function E(tagName, attrs) {
function uid (line 24) | function uid() {
function track_focus (line 137) | function track_focus() {
function get_new_menu_z_index (line 153) | function get_new_menu_z_index() {
function MenuBar (line 166) | function MenuBar(menus) {
FILE: lib/os-gui/os-gui.d.ts
type OSGUIWindow (line 1) | interface OSGUIWindow {
type OSGUI$Window (line 252) | type OSGUI$Window = JQuery<HTMLElement & { $window: OSGUI$Window }> & OS...
type OSGUIFormWindow (line 257) | interface OSGUIFormWindow extends OSGUIWindow {
type OSGUI$FormWindow (line 270) | type OSGUI$FormWindow = JQuery<HTMLElement & { $window: OSGUI$FormWindow...
type $WindowConstructor (line 275) | interface $WindowConstructor {
type OSGUIWindowOptions (line 289) | interface OSGUIWindowOptions {
type OSGUIIcons (line 376) | type OSGUIIcons = { [size: string]: OSGUIIcon };
type OSGUIIcon (line 377) | type OSGUIIcon = string | { src: string } | { srcset: string } | Node;
constant MENU_DIVIDER (line 379) | const MENU_DIVIDER = "MENU_DIVIDER";
type OSGUICheckbox (line 381) | interface OSGUICheckbox {
type OSGUIMenuItem (line 390) | interface OSGUIMenuItem {
type OSGUIRadioItem (line 425) | interface OSGUIRadioItem extends OSGUIMenuItem {
type OSGUIRadioGroup (line 430) | interface OSGUIRadioGroup {
type MenuBar (line 441) | interface MenuBar {
type OSGUIMenuFragment (line 450) | type OSGUIMenuFragment = OSGUIMenuItem | OSGUIRadioGroup | typeof MENU_D...
type OSGUITopLevelMenus (line 452) | type OSGUITopLevelMenus = Record<string, OSGUIMenuFragment[]>;
type MenuBarConstructor (line 454) | interface MenuBarConstructor {
type AccessKeys (line 463) | interface AccessKeys {
type CSSProps (line 486) | type CSSProps = Record<string, string> | CSSStyleDeclaration;
type Window (line 545) | interface Window {
FILE: lib/os-gui/parse-theme.js
function parseINIString (line 6) | function parseINIString(data) {
function renderThemeGraphics (line 48) | function renderThemeGraphics(cssProperties) {
function getThemeCSSProperties (line 216) | function getThemeCSSProperties(element) {
function inheritTheme (line 273) | function inheritTheme(target, source) {
function parseThemeFileString (line 311) | function parseThemeFileString(themeIni) {
function applyCSSProperties (line 351) | function applyCSSProperties(cssProperties, options = {}) {
function makeThemeCSSFile (line 391) | function makeThemeCSSFile(cssProperties) {
function makeBlackToInsetFilter (line 408) | function makeBlackToInsetFilter() {
FILE: lib/pdf.js/build/pdf.js
class BaseCanvasFactory (line 62) | class BaseCanvasFactory {
method constructor (line 63) | constructor() {
method create (line 69) | create(width, height) {
method reset (line 73) | reset(canvasAndContext, width, height) {
method destroy (line 86) | destroy(canvasAndContext) {
class DOMCanvasFactory (line 101) | class DOMCanvasFactory extends BaseCanvasFactory {
method constructor (line 102) | constructor({
method create (line 109) | create(width, height) {
class BaseCMapReaderFactory (line 129) | class BaseCMapReaderFactory {
method constructor (line 130) | constructor({
method fetch (line 142) | async fetch({
method _fetchData (line 160) | _fetchData(url, compressionType) {
class DOMCMapReaderFactory (line 168) | class DOMCMapReaderFactory extends BaseCMapReaderFactory {
method _fetchData (line 169) | _fetchData(url, compressionType) {
class DOMSVGFactory (line 233) | class DOMSVGFactory {
method create (line 234) | create(width, height) {
method createElement (line 245) | createElement(type) {
class PageViewport (line 254) | class PageViewport {
method constructor (line 255) | constructor({
method clone (line 335) | clone({
method convertToViewportPoint (line 352) | convertToViewportPoint(x, y) {
method convertToViewportRectangle (line 356) | convertToViewportRectangle(rect) {
method convertToPdfPoint (line 364) | convertToPdfPoint(x, y) {
class RenderingCancelledException (line 372) | class RenderingCancelledException extends _util.BaseException {
method constructor (line 373) | constructor(msg, type) {
function addLinkAttributes (line 390) | function addLinkAttributes(link, {
function isDataScheme (line 437) | function isDataScheme(url) {
function isPdfFile (line 448) | function isPdfFile(filename) {
function getFilenameFromUrl (line 452) | function getFilenameFromUrl(url) {
function getPdfFilenameFromUrl (line 459) | function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") {
class StatTimer (line 487) | class StatTimer {
method constructor (line 488) | constructor() {
method time (line 493) | time(name) {
method timeEnd (line 501) | timeEnd(name) {
method toString (line 514) | toString() {
function isFetchSupported (line 538) | function isFetchSupported() {
function isValidFetchUrl (line 542) | function isValidFetchUrl(url, baseUrl) {
function loadScript (line 553) | function loadScript(src, removeScriptElement = false) {
function deprecated (line 574) | function deprecated(details) {
class PDFDateString (line 580) | class PDFDateString {
method toDateObject (line 581) | static toDateObject(input) {
function setVerbosityLevel (line 993) | function setVerbosityLevel(level) {
function getVerbosityLevel (line 999) | function getVerbosityLevel() {
function info (line 1003) | function info(msg) {
function warn (line 1009) | function warn(msg) {
function unreachable (line 1015) | function unreachable(msg) {
function assert (line 1019) | function assert(cond, msg) {
function isSameOrigin (line 1025) | function isSameOrigin(baseUrl, otherUrl) {
function _isValidProtocol (line 1042) | function _isValidProtocol(url) {
function createValidAbsoluteUrl (line 1060) | function createValidAbsoluteUrl(url, baseUrl) {
function shadow (line 1076) | function shadow(obj, prop, value) {
function BaseException (line 1087) | function BaseException(message) {
class PasswordException (line 1103) | class PasswordException extends BaseException {
method constructor (line 1104) | constructor(msg, code) {
class UnknownErrorException (line 1113) | class UnknownErrorException extends BaseException {
method constructor (line 1114) | constructor(msg, details) {
class InvalidPDFException (line 1123) | class InvalidPDFException extends BaseException {}
class MissingPDFException (line 1127) | class MissingPDFException extends BaseException {}
class UnexpectedResponseException (line 1131) | class UnexpectedResponseException extends BaseException {
method constructor (line 1132) | constructor(msg, status) {
class FormatError (line 1141) | class FormatError extends BaseException {}
class AbortException (line 1145) | class AbortException extends BaseException {}
function removeNullCharacters (line 1150) | function removeNullCharacters(str) {
function bytesToString (line 1159) | function bytesToString(bytes) {
function stringToBytes (line 1179) | function stringToBytes(str) {
function arrayByteLength (line 1191) | function arrayByteLength(arr) {
function arraysToBytes (line 1200) | function arraysToBytes(arr) {
function string32 (line 1235) | function string32(value) {
function objectSize (line 1239) | function objectSize(obj) {
function objectFromMap (line 1243) | function objectFromMap(map) {
function isLittleEndian (line 1253) | function isLittleEndian() {
method value (line 1261) | get value() {
function isEvalSupported (line 1268) | function isEvalSupported() {
method value (line 1278) | get value() {
class Util (line 1286) | class Util {
method makeHexColor (line 1287) | static makeHexColor(r, g, b) {
method transform (line 1291) | static transform(m1, m2) {
method applyTransform (line 1295) | static applyTransform(p, m) {
method applyInverseTransform (line 1301) | static applyInverseTransform(p, m) {
method getAxialAlignedBoundingBox (line 1308) | static getAxialAlignedBoundingBox(r, m) {
method inverseTransform (line 1316) | static inverseTransform(m) {
method apply3dTransform (line 1321) | static apply3dTransform(m, v) {
method singularValueDecompose2dScale (line 1325) | static singularValueDecompose2dScale(m) {
method normalizeRect (line 1338) | static normalizeRect(rect) {
method intersect (line 1354) | static intersect(rect1, rect2) {
function stringToPDFString (line 1387) | function stringToPDFString(str) {
function escapeString (line 1409) | function escapeString(str) {
function isAscii (line 1421) | function isAscii(str) {
function stringToUTF16BEString (line 1425) | function stringToUTF16BEString(str) {
function stringToUTF8String (line 1437) | function stringToUTF8String(str) {
function utf8StringToString (line 1441) | function utf8StringToString(str) {
function isBool (line 1445) | function isBool(v) {
function isNum (line 1449) | function isNum(v) {
function isString (line 1453) | function isString(v) {
function isArrayBuffer (line 1457) | function isArrayBuffer(v) {
function isArrayEqual (line 1461) | function isArrayEqual(arr1, arr2) {
function getModificationDate (line 1475) | function getModificationDate(date = new Date()) {
function createPromiseCapability (line 1480) | function createPromiseCapability() {
function createObjectURL (line 1503) | function createObjectURL(data, contentType = "", forceDataSchema = false) {
function setPDFNetworkStreamFactory (line 1599) | function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
function getDocument (line 1603) | function getDocument(src) {
function _fetchDocument (line 1782) | function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
class PDFDocumentLoadingTask (line 1825) | class PDFDocumentLoadingTask {
method constructor (line 1826) | constructor() {
method promise (line 1837) | get promise() {
method destroy (line 1841) | destroy() {
class PDFDataRangeTransport (line 1860) | class PDFDataRangeTransport {
method constructor (line 1861) | constructor(length, initialData, progressiveDone = false, contentDispo...
method addRangeListener (line 1873) | addRangeListener(listener) {
method addProgressListener (line 1877) | addProgressListener(listener) {
method addProgressiveReadListener (line 1881) | addProgressiveReadListener(listener) {
method addProgressiveDoneListener (line 1885) | addProgressiveDoneListener(listener) {
method onDataRange (line 1889) | onDataRange(begin, chunk) {
method onDataProgress (line 1895) | onDataProgress(loaded, total) {
method onDataProgressiveRead (line 1903) | onDataProgressiveRead(chunk) {
method onDataProgressiveDone (line 1911) | onDataProgressiveDone() {
method transportReady (line 1919) | transportReady() {
method requestDataRange (line 1923) | requestDataRange(begin, end) {
method abort (line 1927) | abort() {}
class PDFDocumentProxy (line 1933) | class PDFDocumentProxy {
method constructor (line 1934) | constructor(pdfInfo, transport) {
method annotationStorage (line 1939) | get annotationStorage() {
method numPages (line 1943) | get numPages() {
method fingerprint (line 1947) | get fingerprint() {
method isPureXfa (line 1951) | get isPureXfa() {
method getPage (line 1955) | getPage(pageNumber) {
method getPageIndex (line 1959) | getPageIndex(ref) {
method getDestinations (line 1963) | getDestinations() {
method getDestination (line 1967) | getDestination(id) {
method getPageLabels (line 1971) | getPageLabels() {
method getPageLayout (line 1975) | getPageLayout() {
method getPageMode (line 1979) | getPageMode() {
method getViewerPreferences (line 1983) | getViewerPreferences() {
method getOpenAction (line 1987) | getOpenAction() {
method getAttachments (line 1991) | getAttachments() {
method getJavaScript (line 1995) | getJavaScript() {
method getJSActions (line 1999) | getJSActions() {
method getOutline (line 2003) | getOutline() {
method getOptionalContentConfig (line 2007) | getOptionalContentConfig() {
method getPermissions (line 2011) | getPermissions() {
method getMetadata (line 2015) | getMetadata() {
method getMarkInfo (line 2019) | getMarkInfo() {
method getData (line 2023) | getData() {
method getDownloadInfo (line 2027) | getDownloadInfo() {
method getStats (line 2031) | getStats() {
method cleanup (line 2035) | cleanup(keepLoadedFonts = false) {
method destroy (line 2039) | destroy() {
method loadingParams (line 2043) | get loadingParams() {
method loadingTask (line 2047) | get loadingTask() {
method saveDocument (line 2051) | saveDocument(annotationStorage) {
method getFieldObjects (line 2055) | getFieldObjects() {
method hasJSActions (line 2059) | hasJSActions() {
method getCalculationOrderIds (line 2063) | getCalculationOrderIds() {
class PDFPageProxy (line 2071) | class PDFPageProxy {
method constructor (line 2072) | constructor(pageIndex, pageInfo, transport, ownerDocument, pdfBug = fa...
method pageNumber (line 2087) | get pageNumber() {
method rotate (line 2091) | get rotate() {
method ref (line 2095) | get ref() {
method userUnit (line 2099) | get userUnit() {
method view (line 2103) | get view() {
method getViewport (line 2107) | getViewport({
method getAnnotations (line 2124) | getAnnotations({
method getJSActions (line 2135) | getJSActions() {
method getXfa (line 2139) | getXfa() {
method render (line 2143) | render({
method getOperatorList (line 2275) | getOperatorList() {
method streamTextContent (line 2321) | streamTextContent({
method getTextContent (line 2340) | getTextContent(params = {}) {
method _destroy (line 2368) | _destroy() {
method cleanup (line 2398) | cleanup(resetStats = false) {
method _tryCleanup (line 2403) | _tryCleanup(resetStats = false) {
method _startRenderPage (line 2432) | _startRenderPage(transparency, intent) {
method _renderPageChunk (line 2448) | _renderPageChunk(operatorListChunk, intentState) {
method _pumpOperatorList (line 2465) | _pumpOperatorList(args) {
method _abortOperatorList (line 2523) | _abortOperatorList({
method stats (line 2571) | get stats() {
class LoopbackPort (line 2579) | class LoopbackPort {
method constructor (line 2580) | constructor() {
method postMessage (line 2585) | postMessage(obj, transfers) {
method addEventListener (line 2671) | addEventListener(name, listener) {
method removeEventListener (line 2675) | removeEventListener(name, listener) {
method terminate (line 2681) | terminate() {
function getWorkerSrc (line 2707) | function getWorkerSrc() {
function getMainThreadWorkerMessageHandler (line 2723) | function getMainThreadWorkerMessageHandler() {
function setupFakeWorkerGlobal (line 2733) | function setupFakeWorkerGlobal() {
function createCDNWrapper (line 2760) | function createCDNWrapper(url) {
class PDFWorker (line 2765) | class PDFWorker {
method constructor (line 2766) | constructor({
method promise (line 2795) | get promise() {
method port (line 2799) | get port() {
method messageHandler (line 2803) | get messageHandler() {
method _initializeFromPort (line 2807) | _initializeFromPort(port) {
method _initialize (line 2816) | _initialize() {
method _setupFakeWorker (line 2913) | _setupFakeWorker() {
method destroy (line 2944) | destroy() {
method fromPort (line 2963) | static fromPort(params) {
method getWorkerSrc (line 2975) | static getWorkerSrc() {
class WorkerTransport (line 2986) | class WorkerTransport {
method constructor (line 2987) | constructor(messageHandler, loadingTask, networkStream, params) {
method loadingTaskSettled (line 3013) | get loadingTaskSettled() {
method destroy (line 3017) | destroy() {
method setupMessageHandler (line 3068) | setupMessageHandler() {
method _onUnsupportedFeature (line 3385) | _onUnsupportedFeature({
method getData (line 3397) | getData() {
method getPage (line 3401) | getPage(pageNumber) {
method getPageIndex (line 3427) | getPageIndex(ref) {
method getAnnotations (line 3435) | getAnnotations(pageIndex, intent) {
method saveDocument (line 3442) | saveDocument(annotationStorage) {
method getFieldObjects (line 3454) | getFieldObjects() {
method hasJSActions (line 3458) | hasJSActions() {
method getCalculationOrderIds (line 3462) | getCalculationOrderIds() {
method getDestinations (line 3466) | getDestinations() {
method getDestination (line 3470) | getDestination(id) {
method getPageLabels (line 3480) | getPageLabels() {
method getPageLayout (line 3484) | getPageLayout() {
method getPageMode (line 3488) | getPageMode() {
method getViewerPreferences (line 3492) | getViewerPreferences() {
method getOpenAction (line 3496) | getOpenAction() {
method getAttachments (line 3500) | getAttachments() {
method getJavaScript (line 3504) | getJavaScript() {
method getDocJSActions (line 3508) | getDocJSActions() {
method getPageJSActions (line 3512) | getPageJSActions(pageIndex) {
method getPageXfa (line 3518) | getPageXfa(pageIndex) {
method getOutline (line 3524) | getOutline() {
method getOptionalContentConfig (line 3528) | getOptionalContentConfig() {
method getPermissions (line 3534) | getPermissions() {
method getMetadata (line 3538) | getMetadata() {
method getMarkInfo (line 3549) | getMarkInfo() {
method getStats (line 3553) | getStats() {
method startCleanup (line 3557) | async startCleanup(keepLoadedFonts = false) {
method loadingParams (line 3587) | get loadingParams() {
class PDFObjects (line 3597) | class PDFObjects {
method constructor (line 3598) | constructor() {
method _ensureObj (line 3602) | _ensureObj(objId) {
method get (line 3614) | get(objId, callback = null) {
method has (line 3630) | has(objId) {
method resolve (line 3635) | resolve(objId, data) {
method clear (line 3643) | clear() {
class RenderTask (line 3649) | class RenderTask {
method constructor (line 3650) | constructor(internalRenderTask) {
method promise (line 3655) | get promise() {
method cancel (line 3659) | cancel() {
class InternalRenderTask (line 3668) | class InternalRenderTask {
method constructor (line 3669) | constructor({
method completed (line 3705) | get completed() {
method initializeGraphics (line 3709) | initializeGraphics({
method cancel (line 3753) | cancel(error = null) {
method operatorListChanged (line 3768) | operatorListChanged() {
method _continue (line 3788) | _continue() {
method _scheduleNext (line 3802) | _scheduleNext() {
method _next (line 3812) | async _next() {
class BaseFontLoader (line 3857) | class BaseFontLoader {
method constructor (line 3858) | constructor({
method addNativeFontFace (line 3874) | addNativeFontFace(nativeFontFace) {
method insertRule (line 3880) | insertRule(rule) {
method clear (line 3894) | clear() {
method bind (line 3906) | async bind(font) {
method _queueLoadingCallback (line 3952) | _queueLoadingCallback(callback) {
method isFontLoadingAPISupported (line 3956) | get isFontLoadingAPISupported() {
method isSyncFontLoadingSupported (line 3960) | get isSyncFontLoadingSupported() {
method _loadTestFont (line 3964) | get _loadTestFont() {
method _prepareFontLoadEvent (line 3968) | _prepareFontLoadEvent(rules, fontsToLoad, request) {
method constructor (line 3978) | constructor(params) {
method isSyncFontLoadingSupported (line 3987) | get isSyncFontLoadingSupported() {
method _queueLoadingCallback (line 4003) | _queueLoadingCallback(callback) {
method _loadTestFont (line 4025) | get _loadTestFont() {
method _prepareFontLoadEvent (line 4033) | _prepareFontLoadEvent(rules, fonts, request) {
class FontFaceObject (line 4129) | class FontFaceObject {
method constructor (line 4130) | constructor(translatedData, {
method createNativeFontFace (line 4150) | createNativeFontFace() {
method createFontFaceRule (line 4164) | createFontFaceRule() {
method getPathGenerator (line 4180) | getPathGenerator(objs, character) {
method constructor (line 4256) | constructor() {
method constructor (line 4263) | constructor() {
method create (line 4272) | create(width, height) {
method _fetchData (line 4288) | _fetchData(url, compressionType) {
class AnnotationStorage (line 4324) | class AnnotationStorage {
method constructor (line 4325) | constructor() {
method getValue (line 4332) | getValue(key, defaultValue) {
method getOrCreateValue (line 4338) | getOrCreateValue(key, defaultValue) {
method setValue (line 4350) | setValue(key, value) {
method getAll (line 4373) | getAll() {
method size (line 4377) | get size() {
method _setModified (line 4381) | _setModified() {
method resetModified (line 4391) | resetModified() {
method serializable (line 4401) | get serializable() {
function addContextCurrentTransform (line 4456) | function addContextCurrentTransform(ctx) {
function CachedCanvases (line 4572) | function CachedCanvases(canvasFactory) {
method clear (line 4597) | clear() {
function compileType3Glyph (line 4609) | function compileType3Glyph(imgData) {
function CanvasExtraState (line 4784) | function CanvasExtraState() {
function CanvasGraphics (line 4828) | function CanvasGraphics(canvasCtx, commonObjs, objs, canvasFactory, webG...
function putBinaryImageData (line 4861) | function putBinaryImageData(ctx, imgData, transferMaps = null) {
function putBinaryImageMask (line 5047) | function putBinaryImageMask(ctx, imgData) {
function copyCtxState (line 5082) | function copyCtxState(sourceCtx, destCtx) {
function resetCtxToDefault (line 5099) | function resetCtxToDefault(ctx) {
function composeSMaskBackdrop (line 5117) | function composeSMaskBackdrop(bytes, r0, g0, b0) {
function composeSMaskAlpha (line 5136) | function composeSMaskAlpha(maskData, layerData, transferMap) {
function composeSMaskLuminosity (line 5146) | function composeSMaskLuminosity(maskData, layerData, transferMap) {
function genericComposeSMask (line 5155) | function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, ...
function composeSMask (line 5185) | function composeSMask(ctx, smask, layerCtx, webGLContext) {
method beginDrawing (line 5214) | beginDrawing({
method setRenderingIntent (line 5351) | setRenderingIntent(intent) {}
method setFlatness (line 5353) | setFlatness(flatness) {}
method paintChar (line 5822) | paintChar(character, x, y, patternTransform, resetLineWidthToOne) {
method isFontSubpixelAAEnabled (line 5892) | get isFontSubpixelAAEnabled() {
method paintImageMaskXObjectRepeat (line 6414) | paintImageMaskXObjectRepeat(imgData, scaleX, skewX = 0, skewY = 0, scale...
method getSinglePixelWidth (line 6661) | getSinglePixelWidth() {
function applyBoundingBox (line 6721) | function applyBoundingBox(ctx, bbox) {
function drawTriangle (line 6765) | function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
function drawFigure (line 6892) | function drawFigure(data, figure, context) {
function createMeshCanvas (line 6926) | function createMeshCanvas(bounds, combinesScale, coords, colors, figures...
function getShadingPatternFromIR (line 7050) | function getShadingPatternFromIR(raw) {
function TilingPattern (line 7067) | function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransf...
function wrapReason (line 7226) | function wrapReason(reason) {
class MessageHandler (line 7249) | class MessageHandler {
method constructor (line 7250) | constructor(sourceName, targetName, comObj) {
method on (line 7339) | on(actionName, handler) {
method send (line 7349) | send(actionName, data, transfers) {
method sendWithPromise (line 7358) | sendWithPromise(actionName, data, transfers) {
method sendWithStream (line 7378) | sendWithStream(actionName, data, queueingStrategy, transfers) {
method _createStreamSink (line 7434) | _createStreamSink(data) {
method _processStreamMessage (line 7527) | _processStreamMessage(data) {
method _deleteStreamController (line 7673) | async _deleteStreamController(streamId) {
method _postMessage (line 7680) | _postMessage(message, transfers) {
method destroy (line 7688) | destroy() {
class Metadata (line 7709) | class Metadata {
method constructor (line 7710) | constructor({
method getRaw (line 7718) | getRaw() {
method get (line 7722) | get(name) {
method getAll (line 7726) | getAll() {
method has (line 7730) | has(name) {
class OptionalContentGroup (line 7751) | class OptionalContentGroup {
method constructor (line 7752) | constructor(name, intent) {
class OptionalContentConfig (line 7760) | class OptionalContentConfig {
method constructor (line 7761) | constructor(data) {
method isVisible (line 7794) | isVisible(group) {
method setVisibility (line 7869) | setVisibility(id, visible = true) {
method getOrder (line 7878) | getOrder() {
method getGroups (line 7890) | getGroups() {
method getGroup (line 7894) | getGroup(id) {
class PDFDataTransportStream (line 7917) | class PDFDataTransportStream {
method constructor (line 7918) | constructor(params, pdfDataRangeTransport) {
method _onReceiveData (line 7965) | _onReceiveData(args) {
method _progressiveDataLength (line 7989) | get _progressiveDataLength() {
method _onProgress (line 7993) | _onProgress(evt) {
method _onProgressiveDone (line 8014) | _onProgressiveDone() {
method _removeRangeReader (line 8022) | _removeRangeReader(reader) {
method getFullReader (line 8030) | getFullReader() {
method getRangeReader (line 8037) | getRangeReader(begin, end) {
method cancelAllRequests (line 8051) | cancelAllRequests(reason) {
class PDFDataTransportStreamReader (line 8069) | class PDFDataTransportStreamReader {
method constructor (line 8070) | constructor(stream, queuedChunks, progressiveDone = false, contentDisp...
method _enqueue (line 8087) | _enqueue(chunk) {
method headersReady (line 8106) | get headersReady() {
method filename (line 8110) | get filename() {
method isRangeSupported (line 8114) | get isRangeSupported() {
method isStreamingSupported (line 8118) | get isStreamingSupported() {
method contentLength (line 8122) | get contentLength() {
method read (line 8126) | async read() {
method cancel (line 8150) | cancel(reason) {
method progressiveDone (line 8163) | progressiveDone() {
class PDFDataTransportStreamRangeReader (line 8173) | class PDFDataTransportStreamRangeReader {
method constructor (line 8174) | constructor(stream, begin, end) {
method _enqueue (line 8184) | _enqueue(chunk) {
method isStreamingSupported (line 8214) | get isStreamingSupported() {
method read (line 8218) | async read() {
method cancel (line 8242) | cancel(reason) {
class WebGLContext (line 8272) | class WebGLContext {
method constructor (line 8273) | constructor({
method isEnabled (line 8279) | get isEnabled() {
method composeSMask (line 8289) | composeSMask({
method drawFigures (line 8297) | drawFigures({
method clear (line 8307) | clear() {
function loadShader (line 8316) | function loadShader(gl, code, shaderType) {
function createVertexShader (line 8330) | function createVertexShader(gl, code) {
function createFragmentShader (line 8334) | function createFragmentShader(gl, code) {
function createProgram (line 8338) | function createProgram(gl, shaders) {
function createTexture (line 8356) | function createTexture(gl, image, textureId) {
function generateGL (line 8370) | function generateGL() {
function initSmaskGL (line 8425) | function initSmaskGL() {
function composeSMask (line 8455) | function composeSMask(layer, mask, properties) {
function initFiguresGL (line 8524) | function initFiguresGL() {
function drawFigures (line 8545) | function drawFigures(width, height, backgroundColor, figures, context) {
method tryInitGL (line 8672) | tryInitGL() {
method cleanup (line 8684) | cleanup() {
class AnnotationElementFactory (line 8721) | class AnnotationElementFactory {
method create (line 8722) | static create(parameters) {
class AnnotationElement (line 8806) | class AnnotationElement {
method constructor (line 8807) | constructor(parameters, {
method _createContainer (line 8836) | _createContainer(ignoreBorder = false) {
method _createQuadrilaterals (line 8905) | _createQuadrilaterals(ignoreBorder = false) {
method _createPopup (line 8922) | _createPopup(trigger, data) {
method _renderQuadrilaterals (line 8951) | _renderQuadrilaterals(className) {
method render (line 8958) | render() {
class LinkAnnotationElement (line 8964) | class LinkAnnotationElement extends AnnotationElement {
method constructor (line 8965) | constructor(parameters) {
method render (line 8973) | render() {
method _bindLink (line 9010) | _bindLink(link, destination) {
method _bindNamedAction (line 9026) | _bindNamedAction(link, action) {
method _bindJSAction (line 9037) | _bindJSAction(link, data) {
class TextAnnotationElement (line 9065) | class TextAnnotationElement extends AnnotationElement {
method constructor (line 9066) | constructor(parameters) {
method render (line 9073) | render() {
class WidgetAnnotationElement (line 9095) | class WidgetAnnotationElement extends AnnotationElement {
method render (line 9096) | render() {
method _getKeyModifier (line 9104) | _getKeyModifier(event) {
method _setEventListener (line 9108) | _setEventListener(element, baseName, eventName, valueGetter) {
method _setEventListeners (line 9136) | _setEventListeners(element, names, getter) {
method _setColor (line 9144) | _setColor(event) {
class TextWidgetAnnotationElement (line 9183) | class TextWidgetAnnotationElement extends WidgetAnnotationElement {
method constructor (line 9184) | constructor(parameters) {
method render (line 9191) | render() {
method _setTextStyle (line 9425) | _setTextStyle(element) {
class CheckboxWidgetAnnotationElement (line 9446) | class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
method constructor (line 9447) | constructor(parameters) {
method render (line 9453) | render() {
class RadioButtonWidgetAnnotationElement (line 9533) | class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
method constructor (line 9534) | constructor(parameters) {
method render (line 9540) | render() {
class PushButtonWidgetAnnotationElement (line 9627) | class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
method render (line 9628) | render() {
class ChoiceWidgetAnnotationElement (line 9641) | class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
method constructor (line 9642) | constructor(parameters) {
method render (line 9648) | render() {
class PopupAnnotationElement (line 9868) | class PopupAnnotationElement extends AnnotationElement {
method constructor (line 9869) | constructor(parameters) {
method render (line 9876) | render() {
class PopupElement (line 9914) | class PopupElement {
method constructor (line 9915) | constructor(parameters) {
method render (line 9926) | render() {
method _formatContents (line 9978) | _formatContents(contents) {
method _toggle (line 9994) | _toggle() {
method _show (line 10002) | _show(pin = false) {
method _hide (line 10013) | _hide(unpin = true) {
class FreeTextAnnotationElement (line 10026) | class FreeTextAnnotationElement extends AnnotationElement {
method constructor (line 10027) | constructor(parameters) {
method render (line 10035) | render() {
class LineAnnotationElement (line 10047) | class LineAnnotationElement extends AnnotationElement {
method constructor (line 10048) | constructor(parameters) {
method render (line 10056) | render() {
class SquareAnnotationElement (line 10079) | class SquareAnnotationElement extends AnnotationElement {
method constructor (line 10080) | constructor(parameters) {
method render (line 10088) | render() {
class CircleAnnotationElement (line 10113) | class CircleAnnotationElement extends AnnotationElement {
method constructor (line 10114) | constructor(parameters) {
method render (line 10122) | render() {
class PolylineAnnotationElement (line 10147) | class PolylineAnnotationElement extends AnnotationElement {
method constructor (line 10148) | constructor(parameters) {
method render (line 10158) | render() {
class PolygonAnnotationElement (line 10188) | class PolygonAnnotationElement extends PolylineAnnotationElement {
method constructor (line 10189) | constructor(parameters) {
class CaretAnnotationElement (line 10197) | class CaretAnnotationElement extends AnnotationElement {
method constructor (line 10198) | constructor(parameters) {
method render (line 10206) | render() {
class InkAnnotationElement (line 10218) | class InkAnnotationElement extends AnnotationElement {
method constructor (line 10219) | constructor(parameters) {
method render (line 10229) | render() {
class HighlightAnnotationElement (line 10263) | class HighlightAnnotationElement extends AnnotationElement {
method constructor (line 10264) | constructor(parameters) {
method render (line 10273) | render() {
class UnderlineAnnotationElement (line 10288) | class UnderlineAnnotationElement extends AnnotationElement {
method constructor (line 10289) | constructor(parameters) {
method render (line 10298) | render() {
class SquigglyAnnotationElement (line 10313) | class SquigglyAnnotationElement extends AnnotationElement {
method constructor (line 10314) | constructor(parameters) {
method render (line 10323) | render() {
class StrikeOutAnnotationElement (line 10338) | class StrikeOutAnnotationElement extends AnnotationElement {
method constructor (line 10339) | constructor(parameters) {
method render (line 10348) | render() {
class StampAnnotationElement (line 10363) | class StampAnnotationElement extends AnnotationElement {
method constructor (line 10364) | constructor(parameters) {
method render (line 10372) | render() {
class FileAttachmentAnnotationElement (line 10384) | class FileAttachmentAnnotationElement extends AnnotationElement {
method constructor (line 10385) | constructor(parameters) {
method render (line 10403) | render() {
method _download (line 10418) | _download() {
class AnnotationLayer (line 10424) | class AnnotationLayer {
method render (line 10425) | static render(parameters) {
method update (line 10487) | static update(parameters) {
function makeColorComp (line 10518) | function makeColorComp(n) {
class ColorConverters (line 10522) | class ColorConverters {
method CMYK_G (line 10523) | static CMYK_G([c, y, m, k]) {
method G_CMYK (line 10527) | static G_CMYK([g]) {
method G_RGB (line 10531) | static G_RGB([g]) {
method G_HTML (line 10535) | static G_HTML([g]) {
method RGB_G (line 10540) | static RGB_G([r, g, b]) {
method RGB_HTML (line 10544) | static RGB_HTML([r, g, b]) {
method T_HTML (line 10551) | static T_HTML() {
method CMYK_RGB (line 10555) | static CMYK_RGB([c, y, m, k]) {
method CMYK_HTML (line 10559) | static CMYK_HTML(components) {
method RGB_CMYK (line 10563) | static RGB_CMYK([r, g, b]) {
function isAllWhitespace (line 10595) | function isAllWhitespace(str) {
function getAscent (line 10599) | function getAscent(fontFamily, ctx) {
function appendText (line 10656) | function appendText(task, geom, styles, ctx) {
function render (line 10775) | function render(task) {
function findPositiveMin (line 10800) | function findPositiveMin(ts, offset, count) {
function expand (line 10814) | function expand(task) {
function expandBounds (line 10872) | function expandBounds(width, height, boxes) {
function expandBoundsLTR (line 10915) | function expandBoundsLTR(width, bounds) {
function TextLayerRenderTask (line 11064) | function TextLayerRenderTask({
method promise (line 11103) | get promise() {
method _processItems (line 11124) | _processItems(items, styleCache) {
method _layoutText (line 11132) | _layoutText(textDiv) {
function renderTextLayer (line 11306) | function renderTextLayer(renderParameters) {
function crc32 (line 11379) | function crc32(data, start, end) {
function writePngChunk (line 11391) | function writePngChunk(type, body, data, offset) {
function adler32 (line 11413) | function adler32(data, start, end) {
function deflateSync (line 11425) | function deflateSync(literals) {
function deflateSyncUncompressed (line 11451) | function deflateSyncUncompressed(literals) {
function encode (line 11488) | function encode(imgData, kind, forceDataSchema, isMask) {
class SVGExtraState (line 11561) | class SVGExtraState {
method constructor (line 11562) | constructor() {
method clone (line 11595) | clone() {
method setCurrentPoint (line 11599) | setCurrentPoint(x, y) {
function opListToTree (line 11606) | function opListToTree(opList) {
function pf (line 11632) | function pf(value) {
function pm (line 11651) | function pm(m) {
method constructor (line 11678) | constructor(commonObjs, objs, forceDataSchema = false) {
method save (line 11699) | save() {
method restore (line 11706) | restore() {
method group (line 11713) | group(items) {
method loadDependencies (line 11719) | loadDependencies(operatorList) {
method transform (line 11740) | transform(a, b, c, d, e, f) {
method getSVG (line 11746) | getSVG(operatorList, viewport) {
method convertOpList (line 11758) | convertOpList(operatorList) {
method executeOpTree (line 11776) | executeOpTree(opTree) {
method setWordSpacing (line 11989) | setWordSpacing(wordSpacing) {
method setCharSpacing (line 11993) | setCharSpacing(charSpacing) {
method nextLine (line 11997) | nextLine() {
method setTextMatrix (line 12001) | setTextMatrix(a, b, c, d, e, f) {
method beginText (line 12017) | beginText() {
method moveText (line 12031) | moveText(x, y) {
method showText (line 12043) | showText(glyphs) {
method setLeadingMoveText (line 12174) | setLeadingMoveText(x, y) {
method addFontStyle (line 12179) | addFontStyle(fontObj) {
method setFont (line 12194) | setFont(details) {
method endText (line 12233) | endText() {
method setLineWidth (line 12243) | setLineWidth(width) {
method setLineCap (line 12249) | setLineCap(style) {
method setLineJoin (line 12253) | setLineJoin(style) {
method setMiterLimit (line 12257) | setMiterLimit(limit) {
method setStrokeAlpha (line 12261) | setStrokeAlpha(strokeAlpha) {
method setStrokeRGBColor (line 12265) | setStrokeRGBColor(r, g, b) {
method setFillAlpha (line 12269) | setFillAlpha(fillAlpha) {
method setFillRGBColor (line 12273) | setFillRGBColor(r, g, b) {
method setStrokeColorN (line 12280) | setStrokeColorN(args) {
method setFillColorN (line 12284) | setFillColorN(args) {
method shadingFill (line 12288) | shadingFill(args) {
method _makeColorN_Pattern (line 12320) | _makeColorN_Pattern(args) {
method _makeTilingPattern (line 12328) | _makeTilingPattern(args) {
method _makeShadingPattern (line 12378) | _makeShadingPattern(args) {
method setDash (line 12440) | setDash(dashArray, dashPhase) {
method constructPath (line 12445) | constructPath(ops, args) {
method endPath (line 12519) | endPath() {
method clip (line 12560) | clip(type) {
method closePath (line 12564) | closePath() {
method setLeading (line 12573) | setLeading(leading) {
method setTextRise (line 12577) | setTextRise(textRise) {
method setTextRenderingMode (line 12581) | setTextRenderingMode(textRenderingMode) {
method setHScale (line 12585) | setHScale(scale) {
method setRenderingIntent (line 12589) | setRenderingIntent(intent) {}
method setFlatness (line 12591) | setFlatness(flatness) {}
method setGState (line 12593) | setGState(states) {
method fill (line 12643) | fill() {
method stroke (line 12653) | stroke() {
method _setStrokeAttributes (line 12664) | _setStrokeAttributes(element, lineWidthScale = 1) {
method eoFill (line 12684) | eoFill() {
method fillStroke (line 12692) | fillStroke() {
method eoFillStroke (line 12697) | eoFillStroke() {
method closeStroke (line 12705) | closeStroke() {
method closeFillStroke (line 12710) | closeFillStroke() {
method closeEOFillStroke (line 12715) | closeEOFillStroke() {
method paintSolidColorImageMask (line 12720) | paintSolidColorImageMask() {
method paintImageXObject (line 12731) | paintImageXObject(objId) {
method paintInlineImageXObject (line 12742) | paintInlineImageXObject(imgData, mask) {
method paintImageMaskXObject (line 12768) | paintImageMaskXObject(imgData) {
method paintFormXObjectBegin (line 12790) | paintFormXObjectBegin(matrix, bbox) {
method paintFormXObjectEnd (line 12809) | paintFormXObjectEnd() {}
method _initialize (line 12811) | _initialize(viewport) {
method _ensureClipGroup (line 12823) | _ensureClipGroup() {
method _ensureTransformGroup (line 12834) | _ensureTransformGroup() {
class XfaLayer (line 12863) | class XfaLayer {
method setAttributes (line 12864) | static setAttributes(html, attrs) {
method render (line 12878) | static render(parameters) {
method update (line 12931) | static update(parameters) {
function parseUrl (line 12968) | function parseUrl(sourceUrl) {
class PDFNodeStream (line 12986) | class PDFNodeStream {
method constructor (line 12987) | constructor(source) {
method _progressiveDataLength (line 12997) | get _progressiveDataLength() {
method getFullReader (line 13001) | getFullReader() {
method getRangeReader (line 13007) | getRangeReader(start, end) {
method cancelAllRequests (line 13019) | cancelAllRequests(reason) {
class BaseFullReader (line 13035) | class BaseFullReader {
method constructor (line 13036) | constructor(stream) {
method headersReady (line 13059) | get headersReady() {
method filename (line 13063) | get filename() {
method contentLength (line 13067) | get contentLength() {
method isRangeSupported (line 13071) | get isRangeSupported() {
method isStreamingSupported (line 13075) | get isStreamingSupported() {
method read (line 13079) | async read() {
method cancel (line 13116) | cancel(reason) {
method _error (line 13126) | _error(reason) {
method _setReadableStream (line 13132) | _setReadableStream(readableStream) {
class BaseRangeReader (line 13158) | class BaseRangeReader {
method constructor (line 13159) | constructor(stream) {
method isStreamingSupported (line 13171) | get isStreamingSupported() {
method read (line 13175) | async read() {
method cancel (line 13211) | cancel(reason) {
method _error (line 13221) | _error(reason) {
method _setReadableStream (line 13227) | _setReadableStream(readableStream) {
function createRequestOptions (line 13249) | function createRequestOptions(parsedUrl, headers) {
class PDFNodeStreamFullReader (line 13261) | class PDFNodeStreamFullReader extends BaseFullReader {
method constructor (line 13262) | constructor(stream) {
class PDFNodeStreamRangeReader (line 13316) | class PDFNodeStreamRangeReader extends BaseRangeReader {
method constructor (line 13317) | constructor(stream, start, end) {
class PDFNodeStreamFsFullReader (line 13360) | class PDFNodeStreamFsFullReader extends BaseFullReader {
method constructor (line 13361) | constructor(stream) {
class PDFNodeStreamFsRangeReader (line 13392) | class PDFNodeStreamFsRangeReader extends BaseRangeReader {
method constructor (line 13393) | constructor(stream, start, end) {
function validateRangeRequestCapabilities (line 13429) | function validateRangeRequestCapabilities({
function extractFilenameFromHeader (line 13470) | function extractFilenameFromHeader(getResponseHeader) {
function createResponseStatusError (line 13490) | function createResponseStatusError(status, url) {
function validateResponseStatus (line 13498) | function validateResponseStatus(status) {
function getFilenameFromContentDispositionHeader (line 13513) | function getFilenameFromContentDispositionHeader(contentDisposition) {
function getArrayBuffer (line 13708) | function getArrayBuffer(xhr) {
class NetworkManager (line 13719) | class NetworkManager {
method constructor (line 13720) | constructor(url, args) {
method requestRange (line 13735) | requestRange(begin, end, listeners) {
method requestFull (line 13748) | requestFull(listeners) {
method request (line 13752) | request(args) {
method onProgress (line 13796) | onProgress(xhrId, evt) {
method onStateChange (line 13808) | onStateChange(xhrId, evt) {
method getRequestXhr (line 13870) | getRequestXhr(xhrId) {
method isPendingRequest (line 13874) | isPendingRequest(xhrId) {
method abortRequest (line 13878) | abortRequest(xhrId) {
class PDFNetworkStream (line 13886) | class PDFNetworkStream {
method constructor (line 13887) | constructor(source) {
method _onRangeRequestReaderClosed (line 13898) | _onRangeRequestReaderClosed(reader) {
method getFullReader (line 13906) | getFullReader() {
method getRangeReader (line 13912) | getRangeReader(begin, end) {
method cancelAllRequests (line 13921) | cancelAllRequests(reason) {
class PDFNetworkStreamFullRequestReader (line 13937) | class PDFNetworkStreamFullRequestReader {
method constructor (line 13938) | constructor(manager, source) {
method _onHeadersReceived (line 13967) | _onHeadersReceived() {
method _onDone (line 14000) | _onDone(args) {
method _onError (line 14030) | _onError(status) {
method _onProgress (line 14045) | _onProgress(data) {
method filename (line 14054) | get filename() {
method isRangeSupported (line 14058) | get isRangeSupported() {
method isStreamingSupported (line 14062) | get isStreamingSupported() {
method contentLength (line 14066) | get contentLength() {
method headersReady (line 14070) | get headersReady() {
method read (line 14074) | async read() {
method cancel (line 14102) | cancel(reason) {
class PDFNetworkStreamRangeRequestReader (line 14125) | class PDFNetworkStreamRangeRequestReader {
method constructor (line 14126) | constructor(manager, begin, end) {
method _close (line 14140) | _close() {
method _onDone (line 14146) | _onDone(data) {
method _onProgress (line 14174) | _onProgress(evt) {
method isStreamingSupported (line 14182) | get isStreamingSupported() {
method read (line 14186) | async read() {
method cancel (line 14210) | cancel(reason) {
function createFetchOptions (line 14248) | function createFetchOptions(headers, withCredentials, abortController) {
function createHeaders (line 14259) | function createHeaders(httpHeaders) {
class PDFFetchStream (line 14275) | class PDFFetchStream {
method constructor (line 14276) | constructor(source) {
method _progressiveDataLength (line 14284) | get _progressiveDataLength() {
method getFullReader (line 14288) | getFullReader() {
method getRangeReader (line 14294) | getRangeReader(begin, end) {
method cancelAllRequests (line 14306) | cancelAllRequests(reason) {
class PDFFetchStreamReader (line 14322) | class PDFFetchStreamReader {
method constructor (line 14323) | constructor(stream) {
method headersReady (line 14380) | get headersReady() {
method filename (line 14384) | get filename() {
method contentLength (line 14388) | get contentLength() {
method isRangeSupported (line 14392) | get isRangeSupported() {
method isStreamingSupported (line 14396) | get isStreamingSupported() {
method read (line 14400) | async read() {
method cancel (line 14430) | cancel(reason) {
class PDFFetchStreamRangeReader (line 14442) | class PDFFetchStreamRangeReader {
method constructor (line 14443) | constructor(stream, begin, end) {
method isStreamingSupported (line 14479) | get isStreamingSupported() {
method read (line 14483) | async read() {
method cancel (line 14512) | cancel(reason) {
function __w_pdfjs_require__ (line 14531) | function __w_pdfjs_require__(moduleId) {
FILE: lib/pdf.js/build/pdf.sandbox.js
function A (line 40) | function A(a){var c=b["_"+a];c||w("Assertion failed: Cannot call unknown...
function B (line 40) | function B(a,c,d,e){var f={string:function(l){var p=0;if(null!==l&&void ...
function ba (line 40) | function ba(a,c,d){var e=c+d;for(d=c;a[d]&&!(d>=e);)++d;if(16<d-c&&a.sub...
function H (line 40) | function H(a){return a?ba(E,a,void 0):"";}
function D (line 40) | function D(a,c,d,e){if(0<e){e=d+e-1;for(var f=0;f<a.length;++f){var g=a....
function ca (line 40) | function ca(a){for(var c=0,d=0;d<a.length;++d){var e=a.charCodeAt(d);552...
function da (line 40) | function da(a){var c=ca(a)+1,d=K(c);d&&D(a,F,d,c);return d;}
function ja (line 40) | function ja(){var a=b.preRun.shift();ea.unshift(a);}
function w (line 40) | function w(a){if(b.onAbort)b.onAbort(a);u(a);y=!0;a=new WebAssembly.Runt...
function T (line 40) | function T(a){return String.prototype.startsWith?a.startsWith("data:appl...
function la (line 40) | function la(){try{if(v)return new Uint8Array(v);var a=U;if(T(a))try{var ...
function na (line 40) | function na(){return v||"function"!==typeof fetch?Promise.resolve().then...
function V (line 40) | function V(a){for(;0<a.length;){var c=a.shift();if("function"==typeof c)...
function oa (line 40) | function oa(a){var c=ca(a)+1,d=K(c);D(a,E,d,c);return d;}
function pa (line 40) | function pa(){}
function ra (line 40) | function ra(){function a(k){return(k=k.toTimeString().match(/\(([A-Za-z ...
function a (line 40) | function a(f){b.asm=f.exports;P=b.asm.m;Q--;b.monitorRunDependencies&&b....
function c (line 40) | function c(f){a(f.instance);}
function d (line 40) | function d(f){return na().then(function(g){return WebAssembly.instantiat...
function Z (line 40) | function Z(){function a(){if(!Y&&(Y=!0,b.calledRun=!0,!y)){V(fa);V(ha);h...
class SandboxSupportBase (line 48) | class SandboxSupportBase {
method constructor (line 49) | constructor(win) {
method destroy (line 55) | destroy() {
method exportValueToSandbox (line 61) | exportValueToSandbox(val) {
method importValueFromSandbox (line 65) | importValueFromSandbox(val) {
method createErrorForSandbox (line 69) | createErrorForSandbox(errorMessage) {
method callSandboxFunction (line 73) | callSandboxFunction(name, args) {
method createSandboxExternals (line 82) | createSandboxExternals() {
function __w_pdfjs_require__ (line 173) | function __w_pdfjs_require__(moduleId) {
function _interopRequireDefault (line 209) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
class SandboxSupport (line 215) | class SandboxSupport extends _pdfSandboxExternal.SandboxSupportBase {
method exportValueToSandbox (line 216) | exportValueToSandbox(val) {
method importValueFromSandbox (line 220) | importValueFromSandbox(val) {
method createErrorForSandbox (line 224) | createErrorForSandbox(errorMessage) {
class Sandbox (line 230) | class Sandbox {
method constructor (line 231) | constructor(win, module) {
method create (line 238) | create(data) {
method dispatchEvent (line 269) | dispatchEvent(event) {
method dumpMemoryUse (line 273) | dumpMemoryUse() {
method nukeSandbox (line 279) | nukeSandbox() {
method evalForTesting (line 290) | evalForTesting(code, key) {
function QuickJSSandbox (line 302) | function QuickJSSandbox() {
FILE: lib/pdf.js/build/pdf.worker.js
class WorkerTask (line 63) | class WorkerTask {
method constructor (line 64) | constructor(name) {
method finished (line 70) | get finished() {
method finish (line 74) | finish() {
method terminate (line 78) | terminate() {
method ensureNotTerminated (line 82) | ensureNotTerminated() {
class WorkerMessageHandler (line 92) | class WorkerMessageHandler {
method setup (line 93) | static setup(handler, port) {
method createDocumentHandler (line 121) | static createDocumentHandler(docParams, port) {
method initializeFromPort (line 677) | static initializeFromPort(port) {
function isMessagePort (line 687) | function isMessagePort(maybePort) {
function setVerbosityLevel (line 1060) | function setVerbosityLevel(level) {
function getVerbosityLevel (line 1066) | function getVerbosityLevel() {
function info (line 1070) | function info(msg) {
function warn (line 1076) | function warn(msg) {
function unreachable (line 1082) | function unreachable(msg) {
function assert (line 1086) | function assert(cond, msg) {
function isSameOrigin (line 1092) | function isSameOrigin(baseUrl, otherUrl) {
function _isValidProtocol (line 1109) | function _isValidProtocol(url) {
function createValidAbsoluteUrl (line 1127) | function createValidAbsoluteUrl(url, baseUrl) {
function shadow (line 1143) | function shadow(obj, prop, value) {
function BaseException (line 1154) | function BaseException(message) {
class PasswordException (line 1170) | class PasswordException extends BaseException {
method constructor (line 1171) | constructor(msg, code) {
class UnknownErrorException (line 1180) | class UnknownErrorException extends BaseException {
method constructor (line 1181) | constructor(msg, details) {
class InvalidPDFException (line 1190) | class InvalidPDFException extends BaseException {}
class MissingPDFException (line 1194) | class MissingPDFException extends BaseException {}
class UnexpectedResponseException (line 1198) | class UnexpectedResponseException extends BaseException {
method constructor (line 1199) | constructor(msg, status) {
class FormatError (line 1208) | class FormatError extends BaseException {}
class AbortException (line 1212) | class AbortException extends BaseException {}
function removeNullCharacters (line 1217) | function removeNullCharacters(str) {
function bytesToString (line 1226) | function bytesToString(bytes) {
function stringToBytes (line 1246) | function stringToBytes(str) {
function arrayByteLength (line 1258) | function arrayByteLength(arr) {
function arraysToBytes (line 1267) | function arraysToBytes(arr) {
function string32 (line 1302) | function string32(value) {
function objectSize (line 1306) | function objectSize(obj) {
function objectFromMap (line 1310) | function objectFromMap(map) {
function isLittleEndian (line 1320) | function isLittleEndian() {
method value (line 1328) | get value() {
function isEvalSupported (line 1335) | function isEvalSupported() {
method value (line 1345) | get value() {
class Util (line 1353) | class Util {
method makeHexColor (line 1354) | static makeHexColor(r, g, b) {
method transform (line 1358) | static transform(m1, m2) {
method applyTransform (line 1362) | static applyTransform(p, m) {
method applyInverseTransform (line 1368) | static applyInverseTransform(p, m) {
method getAxialAlignedBoundingBox (line 1375) | static getAxialAlignedBoundingBox(r, m) {
method inverseTransform (line 1383) | static inverseTransform(m) {
method apply3dTransform (line 1388) | static apply3dTransform(m, v) {
method singularValueDecompose2dScale (line 1392) | static singularValueDecompose2dScale(m) {
method normalizeRect (line 1405) | static normalizeRect(rect) {
method intersect (line 1421) | static intersect(rect1, rect2) {
function stringToPDFString (line 1454) | function stringToPDFString(str) {
function escapeString (line 1476) | function escapeString(str) {
function isAscii (line 1488) | function isAscii(str) {
function stringToUTF16BEString (line 1492) | function stringToUTF16BEString(str) {
function stringToUTF8String (line 1504) | function stringToUTF8String(str) {
function utf8StringToString (line 1508) | function utf8StringToString(str) {
function isBool (line 1512) | function isBool(v) {
function isNum (line 1516) | function isNum(v) {
function isString (line 1520) | function isString(v) {
function isArrayBuffer (line 1524) | function isArrayBuffer(v) {
function isArrayEqual (line 1528) | function isArrayEqual(arr1, arr2) {
function getModificationDate (line 1542) | function getModificationDate(date = new Date()) {
function createPromiseCapability (line 1547) | function createPromiseCapability() {
function createObjectURL (line 1570) | function createObjectURL(data, contentType = "", forceDataSchema = false) {
function Name (line 1644) | function Name(name) {
function Cmd (line 1667) | function Cmd(cmd) {
function Dict (line 1692) | function Dict(xref) {
method size (line 1705) | get size() {
method get (line 1709) | get(key1, key2, key3) {
method getAsync (line 1727) | async getAsync(key1, key2, key3) {
method getArray (line 1745) | getArray(key1, key2, key3) {
function Ref (line 1876) | function Ref(num, gen) {
class RefSet (line 1906) | class RefSet {
method constructor (line 1907) | constructor(parent = null) {
method has (line 1911) | has(ref) {
method put (line 1915) | put(ref) {
method remove (line 1919) | remove(ref) {
method forEach (line 1923) | forEach(callback) {
method clear (line 1929) | clear() {
class RefSetCache (line 1937) | class RefSetCache {
method constructor (line 1938) | constructor() {
method size (line 1942) | get size() {
method get (line 1946) | get(ref) {
method has (line 1950) | has(ref) {
method put (line 1954) | put(ref, obj) {
method putAlias (line 1958) | putAlias(ref, aliasRef) {
method forEach (line 1962) | forEach(callback) {
method clear (line 1968) | clear() {
function isEOF (line 1976) | function isEOF(v) {
function isName (line 1980) | function isName(v, name) {
function isCmd (line 1984) | function isCmd(v, cmd) {
function isDict (line 1988) | function isDict(v, type) {
function isRef (line 1992) | function isRef(v) {
function isRefsEqual (line 1996) | function isRefsEqual(v1, v2) {
function isStream (line 2000) | function isStream(v) {
function clearPrimitiveCaches (line 2004) | function clearPrimitiveCaches() {
function parseDocBaseUrl (line 2033) | function parseDocBaseUrl(url) {
class BasePdfManager (line 2047) | class BasePdfManager {
method constructor (line 2048) | constructor() {
method docId (line 2054) | get docId() {
method password (line 2058) | get password() {
method docBaseUrl (line 2062) | get docBaseUrl() {
method onLoadedStream (line 2066) | onLoadedStream() {
method ensureDoc (line 2070) | ensureDoc(prop, args) {
method ensureXRef (line 2074) | ensureXRef(prop, args) {
method ensureCatalog (line 2078) | ensureCatalog(prop, args) {
method getPage (line 2082) | getPage(pageIndex) {
method fontFallback (line 2086) | fontFallback(id, handler) {
method cleanup (line 2090) | cleanup(manuallyTriggered = false) {
method ensure (line 2094) | async ensure(obj, prop, args) {
method requestRange (line 2098) | requestRange(begin, end) {
method requestLoadedStream (line 2102) | requestLoadedStream() {
method sendProgressiveData (line 2106) | sendProgressiveData(chunk) {
method updatePassword (line 2110) | updatePassword(password) {
method terminate (line 2114) | terminate(reason) {
class LocalPdfManager (line 2120) | class LocalPdfManager extends BasePdfManager {
method constructor (line 2121) | constructor(docId, data, password, evaluatorOptions, enableXfa, docBas...
method ensure (line 2133) | async ensure(obj, prop, args) {
method requestRange (line 2143) | requestRange(begin, end) {
method requestLoadedStream (line 2147) | requestLoadedStream() {}
method onLoadedStream (line 2149) | onLoadedStream() {
method terminate (line 2153) | terminate(reason) {}
class NetworkPdfManager (line 2159) | class NetworkPdfManager extends BasePdfManager {
method constructor (line 2160) | constructor(docId, pdfNetworkStream, args, evaluatorOptions, enableXfa...
method ensure (line 2177) | async ensure(obj, prop, args) {
method requestRange (line 2196) | requestRange(begin, end) {
method requestLoadedStream (line 2200) | requestLoadedStream() {
method sendProgressiveData (line 2204) | sendProgressiveData(chunk) {
method onLoadedStream (line 2210) | onLoadedStream() {
method terminate (line 2214) | terminate(reason) {
class ChunkedStream (line 2237) | class ChunkedStream {
method constructor (line 2238) | constructor(length, chunkSize, manager) {
method getMissingChunks (line 2251) | getMissingChunks() {
method getBaseStreams (line 2263) | getBaseStreams() {
method numChunksLoaded (line 2267) | get numChunksLoaded() {
method allChunksLoaded (line 2271) | allChunksLoaded() {
method onReceiveData (line 2275) | onReceiveData(begin, chunk) {
method onReceiveProgressiveData (line 2297) | onReceiveProgressiveData(data) {
method ensureByte (line 2310) | ensureByte(pos) {
method ensureRange (line 2328) | ensureRange(begin, end) {
method nextEmptyChunk (line 2348) | nextEmptyChunk(beginChunk) {
method hasChunk (line 2362) | hasChunk(chunk) {
method length (line 2366) | get length() {
method isEmpty (line 2370) | get isEmpty() {
method getByte (line 2374) | getByte() {
method getUint16 (line 2388) | getUint16() {
method getInt32 (line 2399) | getInt32() {
method getBytes (line 2407) | getBytes(length, forceClamped = false) {
method peekByte (line 2436) | peekByte() {
method peekBytes (line 2446) | peekBytes(length, forceClamped = false) {
method getByteRange (line 2452) | getByteRange(begin, end) {
method skip (line 2468) | skip(n) {
method reset (line 2476) | reset() {
method moveStart (line 2480) | moveStart() {
method makeSubStream (line 2484) | makeSubStream(start, length, dict) {
class ChunkedStreamManager (line 2533) | class ChunkedStreamManager {
method constructor (line 2534) | constructor(pdfNetworkStream, args) {
method onLoadedStream (line 2550) | onLoadedStream() {
method sendRequest (line 2554) | sendRequest(begin, end) {
method requestAllChunks (line 2603) | requestAllChunks() {
method _requestChunks (line 2611) | _requestChunks(chunks) {
method getStream (line 2666) | getStream() {
method requestRange (line 2670) | requestRange(begin, end) {
method requestRanges (line 2683) | requestRanges(ranges = []) {
method groupChunks (line 2703) | groupChunks(chunks) {
method onProgress (line 2736) | onProgress(args) {
method onReceiveData (line 2743) | onReceiveData(args) {
method onError (line 2820) | onError(err) {
method getBeginChunk (line 2824) | getBeginChunk(begin) {
method getEndChunk (line 2828) | getEndChunk(end) {
method abort (line 2832) | abort(reason) {
function getLookupTableFactory (line 2876) | function getLookupTableFactory(initializer) {
function getArrayLookupTableFactory (line 2889) | function getArrayLookupTableFactory(initializer) {
class MissingDataException (line 2908) | class MissingDataException extends _util.BaseException {
method constructor (line 2909) | constructor(begin, end) {
class XRefEntryException (line 2919) | class XRefEntryException extends _util.BaseException {}
class XRefParseException (line 2923) | class XRefParseException extends _util.BaseException {}
function getInheritableProperty (line 2927) | function getInheritableProperty({
function toRomanNumerals (line 2963) | function toRomanNumerals(number, lowerCase = false) {
function log2 (line 2984) | function log2(x) {
function readInt8 (line 2992) | function readInt8(data, offset) {
function readUint16 (line 2996) | function readUint16(data, offset) {
function readUint32 (line 3000) | function readUint32(data, offset) {
function isWhiteSpace (line 3004) | function isWhiteSpace(ch) {
function parseXFAPath (line 3008) | function parseXFAPath(path) {
function escapePDFName (line 3027) | function escapePDFName(str) {
function _collectJS (line 3055) | function _collectJS(entry, xref, list, parents) {
function collectActions (line 3102) | function collectActions(xref, dict, eventType) {
function encodeToXmlString (line 3161) | function encodeToXmlString(str) {
function isAnnotationRenderable (line 3241) | function isAnnotationRenderable(annotation, intent) {
class Page (line 3245) | class Page {
method constructor (line 3246) | constructor({
method _getInheritableProperty (line 3282) | _getInheritableProperty(key, getArray = false) {
method content (line 3304) | get content() {
method resources (line 3308) | get resources() {
method _getBoundingBox (line 3312) | _getBoundingBox(name) {
method mediaBox (line 3334) | get mediaBox() {
method cropBox (line 3338) | get cropBox() {
method userUnit (line 3342) | get userUnit() {
method view (line 3352) | get view() {
method rotate (line 3374) | get rotate() {
method getContentStream (line 3388) | getContentStream() {
method xfaData (line 3410) | get xfaData() {
method save (line 3418) | save(handler, task, annotationStorage) {
method loadResources (line 3447) | loadResources(keys) {
method getOperatorList (line 3458) | getOperatorList({
method extractTextContent (line 3530) | extractTextContent({
method getAnnotationsData (line 3562) | getAnnotationsData(intent) {
method annotations (line 3576) | get annotations() {
method _parsedAnnotations (line 3582) | get _parsedAnnotations() {
method jsActions (line 3600) | get jsActions() {
function find (line 3615) | function find(stream, signature, limit = 1024, backwards = false) {
class PDFDocument (line 3664) | class PDFDocument {
method constructor (line 3665) | constructor(pdfManager, arg) {
method parse (line 3704) | parse(recoveryMode) {
method linearization (line 3713) | get linearization() {
method startXRef (line 3729) | get startXRef() {
method checkHeader (line 3782) | checkHeader() {
method parseStartXRef (line 3808) | parseStartXRef() {
method numPages (line 3812) | get numPages() {
method _hasOnlyDocumentSignatures (line 3822) | _hasOnlyDocumentSignatures(fields, recursionDepth = 0) {
method xfaData (line 3852) | get xfaData() {
method xfaFactory (line 3917) | get xfaFactory() {
method isPureXfa (line 3926) | get isPureXfa() {
method formInfo (line 3930) | get formInfo() {
method documentInfo (line 3964) | get documentInfo() {
method fingerprint (line 4036) | get fingerprint() {
method _getLinearizationPage (line 4056) | _getLinearizationPage(pageIndex) {
method getPage (line 4080) | getPage(pageIndex) {
method checkFirstPage (line 4124) | checkFirstPage() {
method fontFallback (line 4134) | fontFallback(id, handler) {
method cleanup (line 4138) | async cleanup(manuallyTriggered = false) {
method _collectFieldObjects (line 4142) | _collectFieldObjects(name, fieldRef, promises) {
method fieldObjects (line 4173) | get fieldObjects() {
method hasJSActions (line 4200) | get hasJSActions() {
method calculationOrderIds (line 4206) | get calculationOrderIds() {
function fetchDestination (line 4259) | function fetchDestination(dest) {
class Catalog (line 4263) | class Catalog {
method constructor (line 4264) | constructor(pdfManager, xref) {
method version (line 4280) | get version() {
method collection (line 4290) | get collection() {
method acroForm (line 4310) | get acroForm() {
method metadata (line 4330) | get metadata() {
method markInfo (line 4365) | get markInfo() {
method _readMarkInfo (line 4381) | _readMarkInfo() {
method toplevelPagesDict (line 4411) | get toplevelPagesDict() {
method documentOutline (line 4421) | get documentOutline() {
method _readDocumentOutline (line 4437) | _readDocumentOutline() {
method permissions (li
Copy disabled (too large)
Download .json
Condensed preview — 2535 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (15,969K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 47,
"preview": "custom: [\"https://www.paypal.me/IsaiahOdhner\"]\n"
},
{
"path": ".gitignore",
"chars": 220,
"preview": "\n# cypress-image-snapshot visual diffs\n__diff_output__\n\n# cypress-image-snapshot images of the whole cypress UI\n*(failed"
},
{
"path": ".vscode/extensions.json",
"chars": 98,
"preview": "{\n\t\"recommendations\": [\n\t\t\"streetsidesoftware.code-spell-checker\",\n\t\t\"dbaeumer.vscode-eslint\"\n\t]\n}"
},
{
"path": ".vscode/launch.json",
"chars": 1709,
"preview": "{\n\t// Use IntelliSense to learn about possible attributes.\n\t// Hover to view descriptions of existing attributes.\n\t// Fo"
},
{
"path": ".vscode/run-command-on-all-files.ahk",
"chars": 4324,
"preview": "; This script runs on AutoHotkey v2.\n;\n; I tried the VS Code extension \"Command on All Files\" first: https://marketplace"
},
{
"path": ".vscode/settings.json",
"chars": 3138,
"preview": "{\n\t// This hides files from the file tree as well as search results.\n\t\"files.exclude\": {\n\t\t\"**/node_modules\": true,\n\t\t\"*"
},
{
"path": "CHANGELOG.md",
"chars": 2394,
"preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changel"
},
{
"path": "CNAME",
"chars": 11,
"preview": "jspaint.app"
},
{
"path": "CONTRIBUTING.md",
"chars": 2625,
"preview": "# Contributing\n\n## Pull Requests\n\nLet me know before you work on something by opening an issue or commenting on an exist"
},
{
"path": "LICENSE.txt",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2022 Isaiah Odhner\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 46996,
"preview": "\n# [ JS Paint](https://jspaint.app)\n\nA pixel-perfect web-based MS Paint remake and more... [T"
},
{
"path": "TODO.md",
"chars": 9717,
"preview": "\n#  JS Paint Todo\n\n### Help\n\n* Link-esque things\n\t* Popups (I'd probably make the text within"
},
{
"path": "about.html",
"chars": 48804,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>JS Paint — MS Paint online</title>\n\n\t<!-- <meta"
},
{
"path": "browserconfig.xml",
"chars": 317,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"images/icons/ms-icon-70"
},
{
"path": "cspell.json",
"chars": 4210,
"preview": "{\n\t\"ignorePaths\": [\n\t\t\".history\", // VS Code \"Local History\" extension\n\t\t\"node_modules\",\n\t\t\"lib\",\n\t\t\"out\", // Electron F"
},
{
"path": "cypress/cypress-image-snapshot-viewer.js",
"chars": 2839,
"preview": "// ==UserScript==\n// @name Cypress Image Snapshot Viewer\n// @namespace https://github.com/1j01/\n// @version "
},
{
"path": "cypress/fixtures/example.json",
"chars": 155,
"preview": "{\n \"name\": \"Using fixtures to represent data\",\n \"email\": \"hello@cypress.io\",\n \"body\": \"Fixtures are a great way to mo"
},
{
"path": "cypress/integration/tool-tests.spec.js",
"chars": 7229,
"preview": "/// <reference types=\"Cypress\" />\n\ncontext(\"tool tests\", () => {\n\t// @TODO: make rounded tools render consistently acros"
},
{
"path": "cypress/integration/visual-tests.spec.js",
"chars": 13048,
"preview": "/// <reference types=\"Cypress\" />\n\ncontext(\"visual tests\", () => {\n\n\t// These tests are not really cross-platform or eve"
},
{
"path": "cypress/plugins/index.js",
"chars": 380,
"preview": "// This function is called when a project is opened or re-opened (e.g. due to\n// the project's config changing)\n\nconst {"
},
{
"path": "cypress/support/commands.js",
"chars": 380,
"preview": "import { addMatchImageSnapshotCommand } from \"cypress-image-snapshot/command\";\naddMatchImageSnapshotCommand({\n\tfailureTh"
},
{
"path": "cypress/support/index.js",
"chars": 218,
"preview": "// ***********************************************************\n// This support/index.js is processed and\n// loaded autom"
},
{
"path": "cypress.json",
"chars": 82,
"preview": "{\n\t\"projectId\": \"6im7v7\",\n\t\"baseUrl\": \"http://localhost:11822\",\n\t\"video\": false\n}\n"
},
{
"path": "discord-activity/.gitignore",
"chars": 50,
"preview": "node_modules\n*.pem\n*.log\n.DS_Store\nbuild\ndist\n.env"
},
{
"path": "discord-activity/README.md",
"chars": 2347,
"preview": "# Discord Embedded App Starter\n\nThis repo is a minimal starter-project. Getting an embedded app running in Discord can b"
},
{
"path": "discord-activity/package.json",
"chars": 632,
"preview": "{\n \"name\": \"discord-activity-starter\",\n \"private\": true,\n \"version\": \"0.1.0\",\n \"description\": \"A minimal starter pro"
},
{
"path": "discord-activity/packages/server/environment.d.ts",
"chars": 214,
"preview": "declare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tVITE_CLIENT_ID: string;\n\t\t\tCLIENT_SECRET: string;\n\t\t\tNO"
},
{
"path": "discord-activity/packages/server/package.json",
"chars": 760,
"preview": "{\n \"name\": \"server\",\n \"version\": \"0.1.0\",\n \"description\": \"The app server\",\n \"main\": \"index.js\",\n \"scripts\": {\n "
},
{
"path": "discord-activity/packages/server/src/app.ts",
"chars": 4169,
"preview": "import bodyParser from \"body-parser\";\nimport dotenv from \"dotenv\";\nimport express, { Application, Request, Response } fr"
},
{
"path": "discord-activity/packages/server/src/shared/hello.ts",
"chars": 83,
"preview": "export function hello() {\n\tconsole.log(\"hello from the server's shared folder\");\n}\n"
},
{
"path": "discord-activity/packages/server/src/utils.ts",
"chars": 1170,
"preview": "export function sleep(ms: number) {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * This function e"
},
{
"path": "discord-activity/packages/server/tsconfig.json",
"chars": 296,
"preview": "{\n\t\"compilerOptions\": {\n\t\t\"outDir\": \"dist\",\n\t\t\"target\": \"es6\",\n\t\t\"module\": \"commonjs\",\n\t\t\"strict\": true,\n\t\t\"esModuleInte"
},
{
"path": "eslint.config.mjs",
"chars": 13085,
"preview": "import js from \"@eslint/js\";\nimport stylistic from \"@stylistic/eslint-plugin\";\nimport globals from \"globals\";\n\n/** @type"
},
{
"path": "forge.config.js",
"chars": 4022,
"preview": "const sharedDebRpmOptions = {\n\tname: \"jspaint\",\n\tproductName: \"JS Paint\",\n\tproductDescription: \"MS Paint clone with extr"
},
{
"path": "help/coUA.css",
"chars": 2549,
"preview": "/* Originally: Cascading Style Sheet for IE4.01 last updated 1-28-98 */\n\n/* for scrollbars and selection color */\n@impor"
},
{
"path": "help/default.html",
"chars": 1111,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Welcome to Help</title>\n\t<link href=\"n"
},
{
"path": "help/memcopy.html",
"chars": 1622,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Legal Information</title>\n\t<link href="
},
{
"path": "help/mspaint.hhc",
"chars": 6627,
"preview": "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n<HTML>\n<HEAD>\n<meta name=\"GENERATOR\" content=\"Microsoft® HTML Help Wo"
},
{
"path": "help/mspaint.hhk",
"chars": 82588,
"preview": "<HTML>\n<HEAD>\n<!-- Sitemap 1.0 -->\n</HEAD>\n<BODY>\n<OBJECT type=\"text/site properties\">\n <param name=\"FrameN"
},
{
"path": "help/nobgcolor.css",
"chars": 4319,
"preview": "/* Originally: Cascading Style Sheet for IE4 build 1008+ */\n\n/* for scrollbars and selection color */\n@import \"../lib/os"
},
{
"path": "help/online_support.htm",
"chars": 1626,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Technical Support Online</title>\n\t<link href=\"nobgcolor.cs"
},
{
"path": "help/paint_airbrush.html",
"chars": 909,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To create an airbrush effect</title>\n\t"
},
{
"path": "help/paint_blackwhite.html",
"chars": 682,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To use black and white instead of colo"
},
{
"path": "help/paint_brush.html",
"chars": 886,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To paint with a brush</title>\n\t<link h"
},
{
"path": "help/paint_change_color.html",
"chars": 1326,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To change the color of an existing lin"
},
{
"path": "help/paint_change_size.html",
"chars": 1110,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To change the size of your picture</ti"
},
{
"path": "help/paint_clear_image.html",
"chars": 1118,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To clear an entire image</title>\n\t<met"
},
{
"path": "help/paint_color_box.html",
"chars": 567,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To show or hide the color box</title>\n"
},
{
"path": "help/paint_curves.html",
"chars": 1108,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw a curve</title>\n\t<link href=\"c"
},
{
"path": "help/paint_custom_colors.html",
"chars": 810,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To create custom colors</title>\n\t<link"
},
{
"path": "help/paint_cutout_copy_move.html",
"chars": 1546,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To copy and paste part of a picture</t"
},
{
"path": "help/paint_cutout_save.html",
"chars": 743,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To save part of a picture into another"
},
{
"path": "help/paint_cutout_select.html",
"chars": 764,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To select part of a picture</title>\n\t<"
},
{
"path": "help/paint_enlarge_area.html",
"chars": 1198,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To enlarge the size of the viewing are"
},
{
"path": "help/paint_erase_large.html",
"chars": 1337,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To erase a large area</title>\n\t<meta c"
},
{
"path": "help/paint_erase_small.html",
"chars": 1633,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To erase a small area</title>\n\t<meta c"
},
{
"path": "help/paint_fill.html",
"chars": 1149,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To fill an area or object with color</"
},
{
"path": "help/paint_flip_picture.html",
"chars": 1618,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To flip or rotate a picture or object<"
},
{
"path": "help/paint_freeform_lines.html",
"chars": 847,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw a free-form line</title>\n\t<lin"
},
{
"path": "help/paint_grid.html",
"chars": 780,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To display gridlines</title>\n\t<link hr"
},
{
"path": "help/paint_insert_file.html",
"chars": 691,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To insert a bitmap into the current pi"
},
{
"path": "help/paint_invert.html",
"chars": 521,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To invert all the colors in a picture<"
},
{
"path": "help/paint_lines.html",
"chars": 919,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw a straight line</title>\n\t<link"
},
{
"path": "help/paint_not_in_color_box.html",
"chars": 1272,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To copy color from one area or object "
},
{
"path": "help/paint_ovals.html",
"chars": 1146,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw an ellipse or circle</title>\n\t"
},
{
"path": "help/paint_polygons.html",
"chars": 1086,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw a polygon</title>\n\t<link href="
},
{
"path": "help/paint_print.html",
"chars": 629,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To print a picture</title>\n\t<link href"
},
{
"path": "help/paint_rectangles.html",
"chars": 1332,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To draw a rectangle or square</title>\n"
},
{
"path": "help/paint_set_default_colors.html",
"chars": 799,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To set the default foreground and back"
},
{
"path": "help/paint_skew_picture.html",
"chars": 1640,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To stretch or skew an item</title>\n\t<l"
},
{
"path": "help/paint_text.html",
"chars": 1940,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To type and format text</title>\n\t<link"
},
{
"path": "help/paint_toolbox.html",
"chars": 560,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To show or hide the toolbox</title>\n\t<"
},
{
"path": "help/paint_trans_opaque.html",
"chars": 626,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To specify transparent or opaque drawi"
},
{
"path": "help/paint_undo.html",
"chars": 934,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To undo changes</title>\n\t<meta content"
},
{
"path": "help/paint_wallpaper.html",
"chars": 1486,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To use a picture as the desktop backgr"
},
{
"path": "help/paint_zoom.html",
"chars": 942,
"preview": "<!DOCTYPE html>\n<html dir=\"ltr\" lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>To zoom in or out of a picture</title>"
},
{
"path": "help/prettify-html.ahk",
"chars": 1629,
"preview": "; AutoHotkey script for formatting HTML with DirtyMarkup\n; They actually have an API, but I decided to go this route ins"
},
{
"path": "help/vaporwave.js",
"chars": 1868,
"preview": "\nconst clouds_img = document.createElement(\"img\");\nclouds_img.src = \"clouds.jpg\";\nconst mask_img = document.createElemen"
},
{
"path": "index.html",
"chars": 71822,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>JS Paint</title>\n\n\t<!-- This should mirror CSP "
},
{
"path": "jsconfig.json",
"chars": 283,
"preview": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ES2022\",\n\t\t\"module\": \"ES2022\",\n\t\t\"moduleResolution\": \"node\", // Fixes error TS2792:"
},
{
"path": "lib/98.css/98.custom-build.css",
"chars": 22805,
"preview": "/*! 98.css custom build - https://github.com/jdan/98.css */\n/**\n * 98.css\n * Copyright (c) 2020 Jordan Scales <thatjdani"
},
{
"path": "lib/98.css/98.custom-build.rtl.css",
"chars": 22559,
"preview": "/*! 98.css custom build - https://github.com/jdan/98.css */\n/**\n * 98.css\n * Copyright (c) 2020 Jordan Scales <thatjdani"
},
{
"path": "lib/98.css/98.custom-src.css",
"chars": 17211,
"preview": "/**\n * 98.css\n * Copyright (c) 2020 Jordan Scales <thatjdanisso.cool>\n * https://github.com/jdan/98.css/blob/main/LICENS"
},
{
"path": "lib/98.css/modified-build.js",
"chars": 2161,
"preview": "#!/usr/bin/env node\nconst dedent = require(\"dedent\");\nconst ejs = require(\"ejs\");\nconst fs = require(\"fs\");\nconst glob ="
},
{
"path": "lib/FileSaver.js",
"chars": 6132,
"preview": "(function (global, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], factory);\n } else if ("
},
{
"path": "lib/UPNG.js",
"chars": 43401,
"preview": "\nvar UPNG = {};\n\n\t\n\nUPNG.toRGBA8 = function(out)\n{\n\tvar w = out.width, h = out.height;\n\tif(out.tabs.acTL==null) return ["
},
{
"path": "lib/UTIF.js",
"chars": 75414,
"preview": "\n\n/* eslint-disable */\n\n;(function(){\nvar UTIF = {};\n\n// Make available for import by `require()`\nif (typeof module == \""
},
{
"path": "lib/anypalette-0.6.0.js",
"chars": 378594,
"preview": "// This library is PATCHED to expose format objects for LoadingErrors.\n// See \"__PATCHED_LIB_TO_ADD_THIS__format\" below."
},
{
"path": "lib/bmp.js",
"chars": 21980,
"preview": "/**\n * Based on: https://github.com/shaozilee/bmp-js/blob/db2c466ca1869ddc09e4b2143404eb03ecd490db/lib/encoder.js\n * @au"
},
{
"path": "lib/discord-embedded-app-sdk-v1.2.0-bundled-with-skypack.js",
"chars": 288218,
"preview": "var global$1 = typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefine"
},
{
"path": "lib/firebase.js",
"chars": 396272,
"preview": "/*!\n * @license Firebase v4.9.0\n * Build: rev-a586a7f\n * Terms: https://firebase.google.com/terms/\n */\nvar firebase=func"
},
{
"path": "lib/font-detective.js",
"chars": 9011,
"preview": "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0)"
},
{
"path": "lib/gif.js/gif.js",
"chars": 13543,
"preview": "// gif.js @ https://github.com/jnordberg/gif.js/tree/92d27a02841339e202c75150dcf6fe5f4fa42ec5\n(function(f){if(typeof exp"
},
{
"path": "lib/gif.js/gif.worker.js",
"chars": 16732,
"preview": "// gif.worker.js @ https://github.com/jnordberg/gif.js/tree/92d27a02841339e202c75150dcf6fe5f4fa42ec5\n(function(){functio"
},
{
"path": "lib/imagetracer_v1.2.5.js",
"chars": 46477,
"preview": "/*\n\timagetracer.js version 1.2.5\n\tSimple raster image tracer and vectorizer written in JavaScript.\n\tandras@jankovics.net"
},
{
"path": "lib/os-gui/$Window.js",
"chars": 66431,
"preview": "/*eslint-disable*/\n((exports) => {\n\n// TODO: E\\(\"([a-z]+)\"\\) -> \"<$1>\" or get rid of jQuery as a dependency\n\nconst E = d"
},
{
"path": "lib/os-gui/MenuBar.js",
"chars": 47235,
"preview": "((exports) => {\n\n/**\n * @template {keyof HTMLElementTagNameMap} K\n * @param {K} tagName\n * @param {Record<string, string"
},
{
"path": "lib/os-gui/build/blue.css",
"chars": 6251,
"preview": "/* Source: https://www.deviantart.com/tpenguinltg/art/Blue-525167751 */\n/* License: https://creativecommons.org/licenses"
},
{
"path": "lib/os-gui/build/layout.css",
"chars": 2558,
"preview": ".menus,\n.menu-popup,\n.os-window,\n.os-window .window-titlebar,\n.os-window .window-title {\n\tcursor: default;\n\t-webkit-user"
},
{
"path": "lib/os-gui/build/layout.rtl.css",
"chars": 2518,
"preview": ".menus,\n.menu-popup,\n.os-window,\n.os-window .window-titlebar,\n.os-window .window-title {\n\tcursor: default;\n\t-webkit-user"
},
{
"path": "lib/os-gui/build/peggys-pastels.css",
"chars": 6289,
"preview": "/* Source: https://www.deviantart.com/tpenguinltg/art/Peggy-s-Pastels-505540096 */\n/* License: https://creativecommons.o"
},
{
"path": "lib/os-gui/build/windows-98.css",
"chars": 56038,
"preview": ":root {\n\t/* These resources are generated. */\n\t/* JS: makeThemeCSSFile(renderThemeGraphics(getComputedStyle(document.doc"
},
{
"path": "lib/os-gui/build/windows-default.css",
"chars": 6286,
"preview": ":root {\n\t/* These resources are generated. */\n\t/* JS: makeThemeCSSFile(renderThemeGraphics(getComputedStyle(document.doc"
},
{
"path": "lib/os-gui/os-gui.d.ts",
"chars": 19899,
"preview": "interface OSGUIWindow {\n\t/**\n\t * Sets the title, or if `text` isn't passed, returns the current title of the window.\n\t *"
},
{
"path": "lib/os-gui/parse-theme.js",
"chars": 15170,
"preview": "/**\n * @param {string} data \n * @returns {Record<string, string | Record<string, string>>}\n * @private\n */\nfunction pars"
},
{
"path": "lib/os-gui.patch",
"chars": 1915,
"preview": "diff --git a/lib/os-gui/$Window.js b/lib/os-gui/$Window.js\nindex 7c785c54..bb776126 100644\n--- a/lib/os-gui/$Window.js\n+"
},
{
"path": "lib/pdf.js/LICENSE",
"chars": 10174,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "lib/pdf.js/build/pdf.js",
"chars": 406323,
"preview": "/**\n * @licstart The following is the entire license notice for the\n * Javascript code in this page\n *\n * Copyright 2021"
},
{
"path": "lib/pdf.js/build/pdf.sandbox.js",
"chars": 631194,
"preview": "/**\n * @licstart The following is the entire license notice for the\n * Javascript code in this page\n *\n * Copyright 2021"
},
{
"path": "lib/pdf.js/build/pdf.worker.js",
"chars": 1619624,
"preview": "/**\n * @licstart The following is the entire license notice for the\n * Javascript code in this page\n *\n * Copyright 2021"
},
{
"path": "lib/pdf.js/web/cmaps/CNS2-V.bcmap",
"chars": 91,
"preview": "\u0003RCopyright 1990-2009 Adobe Systems Incorporated.\nAll rights reserved.\nSee ./LICENSE\u0006CNS2-H"
},
{
"path": "lib/pdf.js/web/cmaps/ETenms-B5-H.bcmap",
"chars": 99,
"preview": "\u0002RCopyright 1990-2009 Adobe Systems Incorporated.\nAll rights reserved.\nSee ./LICENSE\tETen-B5-H`\u0001 ^\u0001"
},
{
"path": "lib/pdf.js/web/cmaps/GB-H.bcmap",
"chars": 356,
"preview": "\u0002RCopyright 1990-2009 Adobe Systems Incorporated.\nAll rights reserved.\nSee ./LICENSE\u0001\u0001!!]aX!!]`21>\u0002\tp\u0002\u000bz$]\u0006\"Rd-U7*\u0017\r\b4%+"
},
{
"path": "lib/pdf.js/web/cmaps/LICENSE",
"chars": 2080,
"preview": "%%Copyright: -----------------------------------------------------------\n%%Copyright: Copyright 1990-2009 Adobe Systems "
},
{
"path": "lib/pdf.js/web/debugger.js",
"chars": 18655,
"preview": "/* Copyright 2012 Mozilla Foundation\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
},
{
"path": "lib/pdf.js/web/locale/ach/viewer.properties",
"chars": 8654,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/af/viewer.properties",
"chars": 7503,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/an/viewer.properties",
"chars": 11808,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ar/viewer.properties",
"chars": 10998,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ast/viewer.properties",
"chars": 6602,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/az/viewer.properties",
"chars": 11323,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/be/viewer.properties",
"chars": 11719,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/bg/viewer.properties",
"chars": 11244,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/bn/viewer.properties",
"chars": 10848,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/bo/viewer.properties",
"chars": 10730,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/br/viewer.properties",
"chars": 11710,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/brx/viewer.properties",
"chars": 9235,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/bs/viewer.properties",
"chars": 8831,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ca/viewer.properties",
"chars": 11895,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/cak/viewer.properties",
"chars": 12050,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ckb/viewer.properties",
"chars": 10714,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/cs/viewer.properties",
"chars": 11506,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/cy/viewer.properties",
"chars": 11492,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/da/viewer.properties",
"chars": 11427,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/de/viewer.properties",
"chars": 12011,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/dsb/viewer.properties",
"chars": 11668,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/el/viewer.properties",
"chars": 11983,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/en-CA/viewer.properties",
"chars": 11209,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/en-GB/viewer.properties",
"chars": 11203,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/en-US/viewer.properties",
"chars": 10991,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/eo/viewer.properties",
"chars": 11554,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/es-AR/viewer.properties",
"chars": 11678,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/es-CL/viewer.properties",
"chars": 11872,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/es-ES/viewer.properties",
"chars": 11905,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/es-MX/viewer.properties",
"chars": 11699,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/et/viewer.properties",
"chars": 10971,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/eu/viewer.properties",
"chars": 11827,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/fa/viewer.properties",
"chars": 9694,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ff/viewer.properties",
"chars": 10669,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/fi/viewer.properties",
"chars": 11551,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/fr/viewer.properties",
"chars": 12066,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/fy-NL/viewer.properties",
"chars": 11517,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ga-IE/viewer.properties",
"chars": 7837,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/gd/viewer.properties",
"chars": 11728,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/gl/viewer.properties",
"chars": 11971,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/gn/viewer.properties",
"chars": 11670,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/gu-IN/viewer.properties",
"chars": 10789,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/he/viewer.properties",
"chars": 10952,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hi-IN/viewer.properties",
"chars": 10931,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hr/viewer.properties",
"chars": 11844,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hsb/viewer.properties",
"chars": 11704,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hu/viewer.properties",
"chars": 11773,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hy-AM/viewer.properties",
"chars": 11309,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/hye/viewer.properties",
"chars": 11787,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ia/viewer.properties",
"chars": 11909,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/id/viewer.properties",
"chars": 11588,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/is/viewer.properties",
"chars": 10457,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/it/viewer.properties",
"chars": 8717,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "lib/pdf.js/web/locale/ja/viewer.properties",
"chars": 10140,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ka/viewer.properties",
"chars": 11540,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/kab/viewer.properties",
"chars": 11471,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/kk/viewer.properties",
"chars": 11636,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/km/viewer.properties",
"chars": 9628,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/kn/viewer.properties",
"chars": 8138,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ko/viewer.properties",
"chars": 10026,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/lij/viewer.properties",
"chars": 11077,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/lo/viewer.properties",
"chars": 6428,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/locale.properties",
"chars": 4358,
"preview": "[ach]\n@import url(ach/viewer.properties)\n\n[af]\n@import url(af/viewer.properties)\n\n[an]\n@import url(an/viewer.properties)"
},
{
"path": "lib/pdf.js/web/locale/lt/viewer.properties",
"chars": 11840,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ltg/viewer.properties",
"chars": 9559,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/lv/viewer.properties",
"chars": 10845,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/meh/viewer.properties",
"chars": 5237,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/mk/viewer.properties",
"chars": 6224,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/mr/viewer.properties",
"chars": 10574,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ms/viewer.properties",
"chars": 10853,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/my/viewer.properties",
"chars": 8731,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/nb-NO/viewer.properties",
"chars": 11281,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ne-NP/viewer.properties",
"chars": 7689,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/nl/viewer.properties",
"chars": 11772,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/nn-NO/viewer.properties",
"chars": 11256,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/oc/viewer.properties",
"chars": 11972,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/pa-IN/viewer.properties",
"chars": 11072,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/pl/viewer.properties",
"chars": 11837,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/pt-BR/viewer.properties",
"chars": 11784,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/pt-PT/viewer.properties",
"chars": 11810,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/rm/viewer.properties",
"chars": 12159,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ro/viewer.properties",
"chars": 11497,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/ru/viewer.properties",
"chars": 11777,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/scn/viewer.properties",
"chars": 4731,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
},
{
"path": "lib/pdf.js/web/locale/si/viewer.properties",
"chars": 8971,
"preview": "# Copyright 2012 Mozilla Foundation\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not us"
}
]
// ... and 2335 more files (download for full content)
About this extraction
This page contains the full source code of the 1j01/jspaint GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2535 files (14.4 MB), approximately 3.8M tokens, and a symbol index with 8103 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.