├── lib ├── svg2ass.wasm ├── languages.html ├── worker.js ├── main.css ├── Makefile ├── main.js ├── example.svg ├── svg2ass.js └── plume-all.css ├── README.md ├── index.html └── pt-br.html /lib/svg2ass.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qgustavor/svg2ass-gui/HEAD/lib/svg2ass.wasm -------------------------------------------------------------------------------- /lib/languages.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | English version 8 | 9 | 10 | Versão em português 11 | 12 | -------------------------------------------------------------------------------- /lib/worker.js: -------------------------------------------------------------------------------- 1 | /* eslint-env worker */ 2 | // This worker is just a small wrapper around the Emscripten output 3 | self.addEventListener('message', runProgram) 4 | 5 | function runProgram (evt) { 6 | const input = evt.data 7 | const Module = self.Module = {} 8 | Module.arguments = input.argv.concat('file.svg') 9 | 10 | const stderr = [] 11 | const stdout = [] 12 | Module.printErr = e => stderr.push(e) 13 | Module.print = e => stdout.push(e) 14 | 15 | Module.preRun = () => { 16 | Module.FS_createDataFile('/', 'file.svg', input.data, true, true) 17 | } 18 | 19 | Module.onExit = status => { 20 | self.postMessage({ status, stderr, stdout }) 21 | self.close() 22 | } 23 | 24 | importScripts('svg2ass.js') 25 | // eslint-disable-next-line no-undef 26 | noExitRuntime = false 27 | } 28 | -------------------------------------------------------------------------------- /lib/main.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --pm-font-family-primary: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", sans-serif; 3 | --pm-font-family-secondary: var(--pm-font-family-primary); 4 | --pm-primary-color: #DF6300; 5 | --pm-secondary-color: #0A6DA4; 6 | --pm-app-base-font-size: 1rem; 7 | --pm-label-margin-bottom: 0; 8 | --pm-form-field-margin-bottom: 0; 9 | } 10 | 11 | .app, .pm-ground { 12 | margin: 1em 0.5em; 13 | } 14 | 15 | label { 16 | margin-left: 1em; 17 | } 18 | 19 | .split { 20 | display: grid; 21 | grid-column-gap: 1em; 22 | } 23 | .s2 { grid-template-columns: repeat(2, 1fr); } 24 | .s3 { grid-template-columns: repeat(3, 1fr); } 25 | .s4 { grid-template-columns: repeat(4, 1fr); } 26 | 27 | .pull-right { 28 | float: right; 29 | } 30 | 31 | .languages img { 32 | vertical-align: middle; 33 | } 34 | 35 | .inline-block { 36 | display: inline-block; 37 | } 38 | 39 | @media (max-width:768px) { 40 | .split { 41 | display: block 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | ##################################### 2 | ## 3 | ## Project: svg2ass 4 | ## File: Makefile 5 | ## Created: 2014-10-23 6 | ## Author: Urban Wallasch 7 | ## Modified to use emcc instead of gcc 8 | ## 9 | 10 | CC := emcc 11 | INCS = 12 | CFLAGS = $(INCS) 13 | CFLAGSX = 14 | LD = emcc 15 | LIBS = 16 | LDFLAGS = --closure 1 -O3 -s FORCE_FILESYSTEM=1 17 | CP = cp 18 | RM = rm -f 19 | SH = sh 20 | VERGEN = $(SH) version.sh 21 | 22 | PRJ = svg2ass 23 | SRC = $(wildcard *.c) 24 | OBJ = $(SRC:%.c=%.o) 25 | BIN = $(PRJ).js 26 | BIN_WA = $(PRJ).wasm 27 | DEP = $(PRJ).dep 28 | VER_IN = version.in 29 | VER_H = version.h 30 | 31 | .PHONY: all release debug clean gen dep 32 | 33 | all: release 34 | 35 | release: CFLAGS += -O3 -DNDEBUG 36 | release: TAG = -rls 37 | release: gen dep $(BIN) 38 | 39 | debug: CFLAGS += -O0 -DDEBUG -g3 40 | debug: TAG = -dbg 41 | debug: gen dep $(BIN) 42 | 43 | gen: 44 | -@$(CP) $(VER_IN) $(VER_H) 2> /dev/null 45 | -$(VERGEN) $(VER_IN) $(VER_H) $(TAG) 46 | 47 | dep: 48 | $(CC) -MM $(SRC) > $(DEP) 49 | 50 | -include $(DEP) 51 | 52 | $(BIN): $(OBJ) 53 | $(LD) $(OBJ) -o $(BIN) $(LDFLAGS) 54 | 55 | %.o: %.c 56 | $(CC) -c $< -o $@ $(CFLAGS) $(CFLAGSX) 57 | 58 | clean: 59 | -${RM} $(OBJ) $(BIN) $(BIN_WA) $(DEP) 2> /dev/null 60 | 61 | 62 | ## EOF 63 | ##################################### 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svg2ass-gui 2 | 3 | A Web GUI for [irrwahn/svg2ass](https://github.com/irrwahn/svg2ass). Check it here: [https://qgustavor.github.io/svg2ass-gui/](https://qgustavor.github.io/svg2ass-gui/) 4 | 5 | Compiled to WASM using [Emscripten](https://emscripten.org/). Uses [SVGO](https://github.com/svg/svgo) to improve compatibility and to compress results. 6 | 7 | ## Licenses 8 | 9 | This project includes code from: 10 | 11 | * [irrwahn/svg2ass](https://github.com/irrwahn/svg2ass): [BSD 3-Clause License](https://github.com/irrwahn/svg2ass/blob/53be678a5be24d690b421bce5f1e345ae960077c/LICENSE) 12 | * [Emscripten](https://emscripten.org/): [MIT/Expat Licence](https://github.com/emscripten-core/emsdk/blob/7e3c0461444bc2b3ad33b32fe89867d626e0f9f5/LICENSE) 13 | * [SVGO](https://github.com/svg/svgo/): [MIT License](https://github.com/svg/svgo/blob/59876d894ba758814a224cffe26566104018130d/LICENSE) 14 | * [Plume CSS](https://github.com/felippe-regazio/plume-css/): [GNU GENERAL PUBLIC LICENSE](https://github.com/felippe-regazio/plume-css/blob/5e34d804ca52e6dffe4a486a8442b16f9fe5022f/LICENSE) 15 | 16 | Please open a issue or send a pull request if there is any issue regarding licensing. 17 | 18 | ## Translations 19 | 20 | If you wish to translate this tool to your language then fork this repository, create a copy of index.html with your language code, translate messages, replace the language code in ``, add your language to `lib\languages.html`, then finally send a pull request. 21 | 22 | ## Privacy 23 | 24 | This tool was made with one of the goals being making it easier for companies like Crunchyroll to do proper typesetting in their works. As far as I know, it looks like this tool was been used at least once by Crunchyroll staff, but I don't have any official info on that. Anyway, here is some privacy stuff just so enterprise folks can feel more safe knowing that their precious NDA-protected data is safe with this tool: 25 | 26 | Data is converted in browser and is not send to any servers. Application data is fetched from GitHub servers which receive usual request info related to fetching any webpage. 27 | 28 | If required this project can be cloned and hosted in any web server. All source-code specific to this project is meant to be safe, respect user privacy and allow to be audited. Both `lib/svg2ass.js` and `lib/svg2ass.wasm` were compiled using Emscripten, so their code are not readable, but those can be still verified by doing the same build steps: 29 | 30 | 1. Install make (if it's not already installed); 31 | 1. Install [Emscripten](https://emscripten.org/); 32 | 1. Clone [qgustavor/svg2ass](https://github.com/qgustavor/svg2ass); 33 | 1. Replace the contents of `Makefile` with those of `lib/Makefile`; 34 | 1. Run `make`. 35 | 36 | The qgustavor's fork of svg2ass is used as it adds support to short form hex colors and alpha (colors with alpha are parsed, but, at the moment, the alpha is ignored), which fixes an issue which was reported by one user of this tool. 37 | 38 | Flags, used to identify languages, come from [catamphetamine/country-flag-icons](https://github.com/catamphetamine/country-flag-icons/) and are also loaded from GitHub servers. Those are released under [MIT License](https://github.com/catamphetamine/country-flag-icons/blob/d9bdf1180eb5c50ad5ebd6514f19c84857ba55f6/LICENSE). 39 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | svg2ass-gui 5 | 6 | 7 | 8 | 9 |
10 |

svg2ass-gui

11 |

A Web GUI for svg2ass.

12 |
13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 |
33 |
34 | 35 | Open file 36 | 37 | 38 | 39 | 40 |
41 |
42 | 43 |
44 |
45 |
46 | 47 | 48 |
49 |
50 | 51 | 52 |
53 |
54 | 55 | 56 |
57 |
58 |
59 |
60 | 61 | 62 |
63 |
64 | 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 |
76 |
77 | 78 | 85 |
86 |
87 | 88 | 94 |
95 |
96 | 97 | 101 |
102 |
103 |

For more info about the above settings read svg2ass help.

104 |
105 | 106 |
107 | 108 |

109 | 110 | 111 |
112 | 113 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /pt-br.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | svg2ass-gui 5 | 6 | 7 | 8 | 9 |
10 |

svg2ass-gui

11 |

Uma interface web para o svg2ass.

12 |
13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 |
33 |
34 | 35 | Abrir arquivo 36 | 37 | 38 | 39 | 40 |
41 |
42 | 43 |
44 |
45 |
46 | 47 | 48 |
49 |
50 | 51 | 52 |
53 |
54 | 55 | 56 |
57 |
58 |
59 |
60 | 61 | 62 |
63 |
64 | 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 |
76 |
77 | 78 | 85 |
86 |
87 | 88 | 94 |
95 |
96 | 97 | 101 |
102 |
103 |

Para mais informações sobre as opções acima leia a ajuda do svg2ass.

104 |
105 | 106 |
107 | 108 |

109 | 110 | 111 |
112 | 113 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | const dataInput = document.getElementById('dataInput') 2 | const dataOutput = document.getElementById('dataOutput') 3 | const convertBtn = document.getElementById('convertBtn') 4 | const advancedBtn = document.getElementById('advancedBtn') 5 | const openFileBtn = document.getElementById('openFile') 6 | const openFileMsg = document.getElementById('openFileMsg') 7 | const advancedPanel = document.getElementById('advancedPanel') 8 | const startTime = document.getElementById('startTime') 9 | const endTime = document.getElementById('endTime') 10 | const actorEl = document.getElementById('actor') 11 | const styleEl = document.getElementById('style') 12 | const layerEl = document.getElementById('layer') 13 | const epsilonEl = document.getElementById('epsilon') 14 | const precisionEl = document.getElementById('precision') 15 | const arclineEl = document.getElementById('arcline') 16 | const svgoEl = document.getElementById('svgo') 17 | const scaleEl = document.getElementById('scale') 18 | const posEl = document.getElementById('pos') 19 | const messages = JSON.parse(document.getElementById('messages').textContent) 20 | const languagesEl = document.getElementsByClassName('languages')[0] 21 | 22 | const getSettings = (precision, svgo) => { 23 | const extraSettings = [ 24 | { 25 | name: 'convertPathData', 26 | active: precision !== -1, 27 | params: { 28 | applyTransforms: true, 29 | applyTransformsStroked: true, 30 | makeArcs: { 31 | threshold: 2.5, 32 | tolerance: 0.5 33 | }, 34 | straightCurves: true, 35 | lineShorthands: true, 36 | // Needs to be disabled 37 | curveSmoothShorthands: false, 38 | floatPrecision: precision, 39 | transformPrecision: 5, 40 | removeUseless: true, 41 | collapseRepeated: true, 42 | utilizeAbsolute: true, 43 | leadingZero: true, 44 | negativeExtraSpace: true, 45 | noSpaceAfterFlags: false, 46 | forceAbsolutePath: false 47 | } 48 | }, 49 | { 50 | name: 'cleanupNumericValues', 51 | active: precision !== -1, 52 | params: { floatPrecision: precision } 53 | }, 54 | { 55 | name: 'cleanupListOfValues', 56 | active: precision !== -1, 57 | params: { floatPrecision: precision } 58 | }, 59 | // Required for compatibility 60 | { name: 'convertStyleToAttrs', active: true }, 61 | { name: 'inlineStyles', active: true, params: { onlyMatchedOnce: false } }, 62 | { name: 'convertColors', active: false }, 63 | { name: 'minifyStyles', active: false } 64 | ] 65 | if (precision === -1) { 66 | // Disable all default settings except by those required for compatibility 67 | return svgo.extendDefaultPlugins([ 68 | ...svgo.extendDefaultPlugins([]).map(e => ({ ...e, active: false })), 69 | ...extraSettings 70 | ]) 71 | } 72 | return svgo.extendDefaultPlugins(extraSettings) 73 | } 74 | const svgoSettings = [ 75 | // Just compatibility settings 76 | -1, 77 | // Small compression 78 | 3, 79 | // Medium compression 80 | 1, 81 | // Strong compression 82 | 0 83 | ] 84 | 85 | let clickWillCopy = false 86 | async function runProgram (data) { 87 | const svgoLevel = Number(svgoEl.value) 88 | if (svgoLevel) { 89 | const svgo = await import('./svgo.browser.js') 90 | const settings = { 91 | plugins: getSettings(svgoSettings[svgoLevel - 1], svgo) 92 | } 93 | const result = svgo.optimize(data, settings) 94 | // Only replace data if svgo returns something 95 | if (result.data) data = result.data 96 | } 97 | const worker = new window.Worker('lib/worker.js') 98 | worker.addEventListener('message', evt => { 99 | const data = evt.data 100 | if (data.status === 0) { 101 | dataOutput.value = evt.data.stdout.join('\r\n') 102 | if (Number(posEl.value)) { 103 | dataOutput.value = dataOutput.value.replaceAll(',,{', ',,{\\pos(0,0)') 104 | } 105 | clickWillCopy = true 106 | } else { 107 | dataOutput.value = evt.data.stderr.join('\r\n') 108 | dataOutput.parentNode.setAttribute('data-pm-error', messages.convertionError) 109 | } 110 | }) 111 | dataOutput.parentNode.removeAttribute('data-pm-error', '') 112 | const argv = [ 113 | '-e', epsilonEl.value, 114 | '-f', precisionEl.value, 115 | '-L', layerEl.value, 116 | '-S', startTime.value, 117 | '-E', endTime.value, 118 | '-A', actorEl.value, 119 | '-T', styleEl.value, 120 | '-z', arclineEl.value, 121 | '-s', scaleEl.value 122 | ] 123 | worker.postMessage({ data, argv }) 124 | } 125 | 126 | function runExample () { 127 | // The example is a SVG outlined version of the original Brazilian Portuguese 128 | // translation of the text in the first Kimokoi episode at 12:19. 129 | window.fetch('lib/example.svg').then(e => e.text()).then(e => { 130 | startTime.value = '0:12:19.00' 131 | endTime.value = '0:12:21.26' 132 | dataInput.value = e 133 | runProgram(e) 134 | }) 135 | } 136 | 137 | convertBtn.addEventListener('click', evt => { 138 | evt.preventDefault() 139 | const data = dataInput.value 140 | dataOutput.parentNode.removeAttribute('data-pm-success') 141 | if (data) { 142 | runProgram(data) 143 | } else { 144 | // Loads an example if the button is clicked without any data 145 | runExample() 146 | } 147 | }) 148 | 149 | dataOutput.addEventListener('focus', evt => { 150 | if (!clickWillCopy) return 151 | clickWillCopy = false 152 | evt.preventDefault() 153 | dataOutput.selectionStart = 0 154 | dataOutput.selectionEnd = dataOutput.value.length 155 | const copyResult = document.execCommand('copy') 156 | if (copyResult) { 157 | dataOutput.parentNode.setAttribute('data-pm-success', messages.copied) 158 | } else { 159 | dataOutput.parentNode.setAttribute('data-pm-success', messages.copy) 160 | } 161 | }) 162 | 163 | advancedBtn.addEventListener('click', evt => { 164 | evt.preventDefault() 165 | advancedPanel.classList.toggle('pm-is-hidden') 166 | }) 167 | 168 | let lastOpenFileMsg = openFileMsg.textContent 169 | openFileBtn.addEventListener('change', evt => { 170 | evt.preventDefault() 171 | const file = openFileBtn.files[0] 172 | if (!file) return 173 | if (leaveTimeout) clearTimeout(leaveTimeout) 174 | openFileMsg.textContent = lastOpenFileMsg = file.name 175 | const reader = new window.Response(file) 176 | reader.text().then(e => { 177 | dataInput.value = e 178 | runProgram(e) 179 | }) 180 | }) 181 | 182 | document.documentElement.addEventListener('dragover', evt => { 183 | evt.preventDefault() 184 | openFileMsg.textContent = messages.dropHere 185 | if (leaveTimeout) clearTimeout(leaveTimeout) 186 | }) 187 | 188 | let leaveTimeout 189 | document.documentElement.addEventListener('dragleave', evt => { 190 | evt.preventDefault() 191 | if (leaveTimeout) clearTimeout(leaveTimeout) 192 | leaveTimeout = setTimeout(resetOpenFileMsg, 250) 193 | }) 194 | 195 | function resetOpenFileMsg () { 196 | leaveTimeout = null 197 | openFileMsg.textContent = lastOpenFileMsg 198 | } 199 | 200 | document.documentElement.addEventListener('paste', pasteHandler) 201 | 202 | function pasteHandler (evt) { 203 | const file = evt.clipboardData.files[0] 204 | if (!file) return 205 | openFileMsg.textContent = file.name 206 | const reader = new window.Response(file) 207 | reader.text().then(e => { 208 | dataInput.value = e 209 | runProgram(e) 210 | }) 211 | } 212 | 213 | window.fetch('lib/languages.html').then(e => e.text()).then(e => { 214 | languagesEl.innerHTML = e 215 | const currentLanguage = document.documentElement.lang 216 | for (const anchor of languagesEl.children) { 217 | if (anchor.dataset.lang === currentLanguage) { 218 | anchor.remove() 219 | } 220 | } 221 | }) 222 | -------------------------------------------------------------------------------- /lib/example.svg: -------------------------------------------------------------------------------- 1 | Example SVG -------------------------------------------------------------------------------- /lib/svg2ass.js: -------------------------------------------------------------------------------- 1 | 2 | var f;f||(f=typeof Module !== 'undefined' ? Module : {});var aa=Object.assign({},f),ba=[],ca="./this.program",da=(a,b)=>{throw b;},ea="object"==typeof window,h="function"==typeof importScripts,fa="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,m="",w,z,ha; 3 | if(fa){var fs=require("fs"),ia=require("path");m=h?ia.dirname(m)+"/":__dirname+"/";w=(a,b)=>{a=a.startsWith("file://")?new URL(a):ia.normalize(a);return fs.readFileSync(a,b?void 0:"utf8")};ha=a=>{a=w(a,!0);a.buffer||(a=new Uint8Array(a));return a};z=(a,b,c)=>{a=a.startsWith("file://")?new URL(a):ia.normalize(a);fs.readFile(a,function(d,e){d?c(d):b(e.buffer)})};1{if(noExitRuntime)throw process.exitCode=a,b;b instanceof ja||B("exiting due to exception: "+b);process.exit(a)};f.inspect=function(){return"[Emscripten Module object]"}}else if(ea||h)h?m=self.location.href:"undefined"!=typeof document&&document.currentScript&&(m=document.currentScript.src),m=0!==m.indexOf("blob:")?m.substr(0,m.replace(/[?#].*/,"").lastIndexOf("/")+1):"",w=a=>{var b=new XMLHttpRequest; 5 | b.open("GET",a,!1);b.send(null);return b.responseText},h&&(ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),z=(a,b,c)=>{var d=new XMLHttpRequest;d.open("GET",a,!0);d.responseType="arraybuffer";d.onload=()=>{200==d.status||0==d.status&&d.response?b(d.response):c()};d.onerror=c;d.send(null)};var ka=f.print||console.log.bind(console),B=f.printErr||console.warn.bind(console);Object.assign(f,aa);aa=null;f.arguments&&(ba=f.arguments); 6 | f.thisProgram&&(ca=f.thisProgram);f.quit&&(da=f.quit);var C;f.wasmBinary&&(C=f.wasmBinary);var noExitRuntime=f.noExitRuntime||!0;"object"!=typeof WebAssembly&&E("no native wasm support detected");var la,ma=!1,na="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0; 7 | function F(a,b){for(var c=b+NaN,d=b;a[d]&&!(d>=c);)++d;if(16e?c+=String.fromCharCode(e):(e-=65536,c+=String.fromCharCode(55296|e>>10,56320|e&1023))}}else c+=String.fromCharCode(e)}return c} 8 | function oa(a,b,c,d){if(!(0=k){var r=a.charCodeAt(++g);k=65536+((k&1023)<<10)|r&1023}if(127>=k){if(c>=d)break;b[c++]=k}else{if(2047>=k){if(c+1>=d)break;b[c++]=192|k>>6}else{if(65535>=k){if(c+2>=d)break;b[c++]=224|k>>12}else{if(c+3>=d)break;b[c++]=240|k>>18;b[c++]=128|k>>12&63}b[c++]=128|k>>6&63}b[c++]=128|k&63}}b[c]=0;return c-e} 9 | function pa(a){for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b}var G,qa,ra,H,I,sa=[],ta=[],ua=[],va=[];function wa(){var a=f.preRun.shift();sa.unshift(a)}var J=0,xa=null,L=null;function ya(){J++;f.monitorRunDependencies&&f.monitorRunDependencies(J)}function za(){J--;f.monitorRunDependencies&&f.monitorRunDependencies(J);if(0==J&&(null!==xa&&(clearInterval(xa),xa=null),L)){var a=L;L=null;a()}} 10 | function E(a){if(f.onAbort)f.onAbort(a);a="Aborted("+a+")";B(a);ma=!0;throw new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");}function Aa(){return M.startsWith("data:application/octet-stream;base64,")}var M;M="svg2ass.wasm";if(!Aa()){var Ba=M;M=f.locateFile?f.locateFile(Ba,m):m+Ba}function Ca(){var a=M;try{if(a==M&&C)return new Uint8Array(C);if(ha)return ha(a);throw"both async and sync fetching of the wasm failed";}catch(b){E(b)}} 11 | function Da(){if(!C&&(ea||h)){if("function"==typeof fetch&&!M.startsWith("file://"))return fetch(M,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+M+"'";return a.arrayBuffer()}).catch(function(){return Ca()});if(z)return new Promise(function(a,b){z(M,function(c){a(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return Ca()})}var N,Ea; 12 | function ja(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}function Fa(a){for(;0{for(var c=0,d=a.length-1;0<=d;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},O=a=>{var b="/"===a.charAt(0),c="/"===a.substr(-1);(a=Ga(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},Ha=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1);a=b[0];b=b[1];if(!a&&!b)return".";b&&(b=b.substr(0,b.length-1));return a+b},Ia=a=>{if("/"=== 14 | a)return"/";a=O(a);a=a.replace(/\/$/,"");var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)};function Ja(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(fa)try{var b=require("crypto");return()=>b.randomBytes(1)[0]}catch(c){}return()=>E("randomDevice")} 15 | function Ka(){for(var a="",b=!1,c=arguments.length-1;-1<=c&&!b;c--){b=0<=c?arguments[c]:"/";if("string"!=typeof b)throw new TypeError("Arguments to path.resolve must be strings");if(!b)return"";a=b+"/"+a;b="/"===b.charAt(0)}a=Ga(a.split("/").filter(d=>!!d),!b).join("/");return(b?"/":"")+a||"."}function La(a){var b=Array(pa(a)+1);a=oa(a,b,0,b.length);b.length=a;return b}var Ma=[];function Na(a,b){Ma[a]={input:[],output:[],J:b};Oa(a,Pa)} 16 | var Pa={open:function(a){var b=Ma[a.node.rdev];if(!b)throw new P(43);a.tty=b;a.seekable=!1},close:function(a){a.tty.J.fsync(a.tty)},fsync:function(a){a.tty.J.fsync(a.tty)},read:function(a,b,c,d){if(!a.tty||!a.tty.J.Y)throw new P(60);for(var e=0,g=0;g=b||(b=Math.max(b,c*(1048576>c?2:1.125)>>>0),0!=c&&(b=Math.max(b,256)),c=a.o,a.o=new Uint8Array(b), 21 | 0=a.node.v)return 0;a=Math.min(a.node.v-e,d);if(8b)throw new P(28);return b},T:function(a,b,c){Q.W(a.node,b+c);a.node.v=Math.max(a.node.v,b+c)},P:function(a,b,c,d,e){if(32768!==(a.node.mode&61440))throw new P(43);a=a.node.o;if(e&2||a.buffer!==G.buffer){if(0{e||E('Loading data file "'+a+'" failed (no arrayBuffer).');b(new Uint8Array(e));d&&za(d)},()=>{if(c)c();else throw'Loading data file "'+a+'" failed.';});d&&ya(d)} 27 | var Wa=null,Xa={},Ya=[],Za=1,S=null,$a=!0,P=null,Ua={},T=(a,b={})=>{a=Ka(a);if(!a)return{path:"",node:null};b=Object.assign({X:!0,S:0},b);if(8!!k);for(var c=Wa,d="/",e=0;e{for(var b;;){if(a===a.parent)return a= 28 | a.C.aa,b?"/"!==a[a.length-1]?a+"/"+b:a+b:a;b=b?a.name+"/"+b:a.name;a=a.parent}},bb=(a,b)=>{for(var c=0,d=0;d>>0)%S.length},R=(a,b)=>{var c;if(c=(c=cb(a,"x"))?c:a.s.lookup?0:2)throw new P(c,a);for(c=S[bb(a.id,b)];c;c=c.I){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.s.lookup(a,b)},Ta=(a,b,c,d)=>{a=new db(a,b,c,d);b=bb(a.parent.id,a.name);a.I=S[b];return S[b]=a},eb={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090},fb=a=>{var b=["r","w", 29 | "rw"][a&3];a&512&&(b+="w");return b},cb=(a,b)=>{if($a)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0},gb=(a,b)=>{try{return R(a,b),20}catch(c){}return cb(a,"wx")},hb=(a=0)=>{for(;4096>=a;a++)if(!Ya[a])return a;throw new P(33);},jb=(a,b)=>{ib||(ib=function(){this.D={}},ib.prototype={},Object.defineProperties(ib.prototype,{object:{get:function(){return this.node},set:function(c){this.node=c}},flags:{get:function(){return this.D.flags}, 30 | set:function(c){this.D.flags=c}},position:{get:function(){return this.D.position},set:function(c){this.D.position=c}}}));a=Object.assign(new ib,a);b=hb(b);a.fd=b;return Ya[b]=a},Sa={open:a=>{a.u=Xa[a.node.rdev].u;a.u.open&&a.u.open(a)},H:()=>{throw new P(70);}},Oa=(a,b)=>{Xa[a]={u:b}},kb=(a,b)=>{var c="/"===b,d=!b;if(c&&Wa)throw new P(10);if(!c&&!d){var e=T(b,{X:!1});b=e.path;e=e.node;if(e.K)throw new P(10);if(16384!==(e.mode&61440))throw new P(54);}b={type:a,ra:{},aa:b,ja:[]};a=a.C(b);a.C=b;b.root= 31 | a;c?Wa=a:e&&(e.K=b,e.C&&e.C.ja.push(b))},V=(a,b,c)=>{var d=T(a,{parent:!0}).node;a=Ia(a);if(!a||"."===a||".."===a)throw new P(28);var e=gb(d,a);if(e)throw new P(e);if(!d.s.L)throw new P(63);return d.s.L(d,a,b,c)},lb=(a,b,c)=>{"undefined"==typeof c&&(c=b,b=438);return V(a,b|8192,c)},mb=(a,b)=>{if(!Ka(a))throw new P(44);var c=T(b,{parent:!0}).node;if(!c)throw new P(44);b=Ia(b);var d=gb(c,b);if(d)throw new P(d);if(!c.s.symlink)throw new P(63);c.s.symlink(c,b,a)},nb=a=>{var b=T(a,{parent:!0}).node;if(!b)throw new P(44); 32 | var c=Ia(a);a=R(b,c);a:{try{var d=R(b,c)}catch(g){d=g.F;break a}var e=cb(b,"wx");d=e?e:16384===(d.mode&61440)?31:0}if(d)throw new P(d);if(!b.s.unlink)throw new P(63);if(a.K)throw new P(10);b.s.unlink(b,c);b=bb(a.parent.id,a.name);if(S[b]===a)S[b]=a.I;else for(b=S[b];b;){if(b.I===a){b.I=a.I;break}b=b.I}},ab=a=>{a=T(a).node;if(!a)throw new P(44);if(!a.s.readlink)throw new P(28);return Ka(U(a.parent),a.s.readlink(a))},ob=(a,b)=>{a="string"==typeof a?T(a,{M:!0}).node:a;if(!a.s.A)throw new P(63);a.s.A(a, 33 | {mode:b&4095|a.mode&-4096,timestamp:Date.now()})},qb=(a,b,c)=>{if(""===a)throw new P(44);if("string"==typeof b){var d=eb[b];if("undefined"==typeof d)throw Error("Unknown file open mode: "+b);b=d}c=b&64?("undefined"==typeof c?438:c)&4095|32768:0;if("object"==typeof a)var e=a;else{a=O(a);try{e=T(a,{M:!(b&131072)}).node}catch(g){}}d=!1;if(b&64)if(e){if(b&128)throw new P(20);}else e=V(a,c,0),d=!0;if(!e)throw new P(44);8192===(e.mode&61440)&&(b&=-513);if(b&65536&&16384!==(e.mode&61440))throw new P(54); 34 | if(!d&&(c=e?40960===(e.mode&61440)?32:16384===(e.mode&61440)&&("r"!==fb(b)||b&512)?31:cb(e,fb(b)):44))throw new P(c);if(b&512&&!d){c=e;c="string"==typeof c?T(c,{M:!0}).node:c;if(!c.s.A)throw new P(63);if(16384===(c.mode&61440))throw new P(31);if(32768!==(c.mode&61440))throw new P(28);if(d=cb(c,"w"))throw new P(d);c.s.A(c,{size:0,timestamp:Date.now()})}b&=-131713;e=jb({node:e,path:U(e),flags:b,seekable:!0,position:0,u:e.u,na:[],error:!1});e.u.open&&e.u.open(e);!f.logReadFiles||b&1||(pb||(pb={}),a in 35 | pb||(pb[a]=1));return e},rb=a=>{if(null===a.fd)throw new P(8);a.N&&(a.N=null);try{a.u.close&&a.u.close(a)}catch(b){throw b;}finally{Ya[a.fd]=null}a.fd=null},sb=(a,b,c)=>{if(null===a.fd)throw new P(8);if(!a.seekable||!a.u.H)throw new P(70);if(0!=c&&1!=c&&2!=c)throw new P(28);a.position=a.u.H(a,b,c);a.na=[]},tb=(a,b,c,d,e,g)=>{if(0>d||0>e)throw new P(28);if(null===a.fd)throw new P(8);if(0===(a.flags&2097155))throw new P(8);if(16384===(a.node.mode&61440))throw new P(31);if(!a.u.write)throw new P(28); 36 | a.seekable&&a.flags&1024&&sb(a,0,2);var k="undefined"!=typeof e;if(!k)e=a.position;else if(!a.seekable)throw new P(70);b=a.u.write(a,b,c,d,e,g);k||(a.position+=b);return b},ub=()=>{P||(P=function(a,b){this.node=b;this.ma=function(c){this.F=c};this.ma(a);this.message="FS error"},P.prototype=Error(),P.prototype.constructor=P,[44].forEach(a=>{Ua[a]=new P(a);Ua[a].stack=""}))},vb,wb=(a,b)=>{var c=0;a&&(c|=365);b&&(c|=146);return c},xb=(a,b)=>{a="string"==typeof a?a:U(a);for(b= 37 | b.split("/").reverse();b.length;){var c=b.pop();if(c){var d=O(a+"/"+c);try{V(d,16895,0)}catch(e){}a=d}}return d},yb=(a,b,c,d)=>{a=O(("string"==typeof a?a:U(a))+"/"+b);c=wb(c,d);return V(a,(void 0!==c?c:438)&4095|32768,0)},zb=(a,b,c,d,e,g)=>{var k=b;a&&(a="string"==typeof a?a:U(a),k=b?O(a+"/"+b):a);a=wb(d,e);k=V(k,(void 0!==a?a:438)&4095|32768,0);if(c){if("string"==typeof c){b=Array(c.length);d=0;for(e=c.length;d{a=O(("string"==typeof a?a:U(a))+"/"+b);b=wb(!!c,!!d);W.$||(W.$=64);var e=W.$++<<8|0;Oa(e,{open:g=>{g.seekable=!1},close:()=>{d&&d.buffer&&d.buffer.length&&d(10)},read:(g,k,r,q)=>{for(var n=0,l=0;l{for(var n=0;n{if(!(a.ha||a.ia||a.link||a.o)){if("undefined"!=typeof XMLHttpRequest)throw Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");if(w)try{a.o=La(w(a.url)),a.v=a.o.length}catch(b){throw new P(29);}else throw Error("Cannot load without read() or XMLHttpRequest.");}},Bb=(a,b,c,d,e)=>{function g(){this.O=!1;this.D=[]}g.prototype.get= 40 | function(l){if(!(l>this.length-1||0>l)){var p=l%this.chunkSize;return this.Z(l/this.chunkSize|0)[p]}};g.prototype.la=function(l){this.Z=l};g.prototype.U=function(){var l=new XMLHttpRequest;l.open("HEAD",c,!1);l.send(null);if(!(200<=l.status&&300>l.status||304===l.status))throw Error("Couldn't load "+c+". Status: "+l.status);var p=Number(l.getResponseHeader("Content-length")),v,x=(v=l.getResponseHeader("Accept-Ranges"))&&"bytes"===v;l=(v=l.getResponseHeader("Content-Encoding"))&&"gzip"===v;var u=1048576; 41 | x||(u=p);var t=this;t.la(A=>{var K=A*u,D=(A+1)*u-1;D=Math.min(D,p-1);if("undefined"==typeof t.D[A]){var Kb=t.D;if(K>D)throw Error("invalid range ("+K+", "+D+") or no bytes requested!");if(D>p-1)throw Error("only "+p+" bytes available! programmer error!");var y=new XMLHttpRequest;y.open("GET",c,!1);p!==u&&y.setRequestHeader("Range","bytes="+K+"-"+D);y.responseType="arraybuffer";y.overrideMimeType&&y.overrideMimeType("text/plain; charset=x-user-defined");y.send(null);if(!(200<=y.status&&300>y.status|| 42 | 304===y.status))throw Error("Couldn't load "+c+". Status: "+y.status);K=void 0!==y.response?new Uint8Array(y.response||[]):La(y.responseText||"");Kb[A]=K}if("undefined"==typeof t.D[A])throw Error("doXHR failed!");return t.D[A]});if(l||!p)u=p=1,u=p=this.Z(0).length,ka("LazyFiles on gzip forces download of the whole file when length is accessed");this.ea=p;this.da=u;this.O=!0};if("undefined"!=typeof XMLHttpRequest){if(!h)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"; 43 | var k=new g;Object.defineProperties(k,{length:{get:function(){this.O||this.U();return this.ea}},chunkSize:{get:function(){this.O||this.U();return this.da}}});var r=void 0}else r=c,k=void 0;var q=yb(a,b,d,e);k?q.o=k:r&&(q.o=null,q.url=r);Object.defineProperties(q,{v:{get:function(){return this.o.length}}});var n={};Object.keys(q.u).forEach(l=>{var p=q.u[l];n[l]=function(){Ab(q);return p.apply(null,arguments)}});n.read=(l,p,v,x,u)=>{Ab(q);l=l.node.o;if(u>=l.length)p=0;else{x=Math.min(l.length-u,x); 44 | if(l.slice)for(var t=0;t{Ab(q);E();throw new P(48);};q.u=n;return q},Db=(a,b,c,d,e,g,k,r,q,n)=>{function l(x){function u(t){n&&n();r||zb(a,b,t,d,e,q);g&&g();za(v)}Cb.qa(x,p,u,()=>{k&&k();za(v)})||u(x)}var p=b?Ka(O(a+"/"+b)):a,v="cp "+p;ya(v);"string"==typeof c?Va(c,x=>l(x),k):l(c)},X={},ib,pb,Eb=void 0;function Y(){Eb+=4;return H[Eb-4>>2]}function Z(a){a=Ya[a];if(!a)throw new P(8);return a} 45 | function Fb(a){if(!noExitRuntime){if(f.onExit)f.onExit(a);ma=!0}da(a,new ja(a))}function db(a,b,c,d){a||(a=this);this.parent=a;this.C=a.C;this.K=null;this.id=Za++;this.name=b;this.mode=c;this.s={};this.u={};this.rdev=d} 46 | Object.defineProperties(db.prototype,{read:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}},ia:{get:function(){return 16384===(this.mode&61440)}},ha:{get:function(){return 8192===(this.mode&61440)}}});ub();S=Array(4096);kb(Q,"/");V("/tmp",16895,0);V("/home",16895,0);V("/home/web_user",16895,0); 47 | (()=>{V("/dev",16895,0);Oa(259,{read:()=>0,write:(b,c,d,e)=>e});lb("/dev/null",259);Na(1280,Qa);Na(1536,Ra);lb("/dev/tty",1280);lb("/dev/tty1",1536);var a=Ja();W("/dev","random",a);W("/dev","urandom",a);V("/dev/shm",16895,0);V("/dev/shm/tmp",16895,0)})(); 48 | (()=>{V("/proc",16895,0);var a=V("/proc/self",16895,0);V("/proc/self/fd",16895,0);kb({C:()=>{var b=Ta(a,"fd",16895,73);b.s={lookup:(c,d)=>{var e=Ya[+d];if(!e)throw new P(8);c={parent:null,C:{aa:"fake"},s:{readlink:()=>e.path}};return c.parent=c}};return b}},"/proc/self/fd")})();var Cb;f.FS_createPath=xb;f.FS_createDataFile=zb;f.FS_createPreloadedFile=Db;f.FS_unlink=nb;f.FS_createLazyFile=Bb;f.FS_createDevice=W; 49 | var Hb={d:function(a,b,c){Eb=c;try{var d=Z(a);switch(b){case 0:var e=Y();return 0>e?-28:jb(d,e).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return e=Y(),d.flags|=e,0;case 5:return e=Y(),ra[e+0>>1]=2,0;case 6:case 7:return 0;case 16:case 8:return-28;case 9:return H[Gb()>>2]=28,-1;default:return-28}}catch(g){if("undefined"==typeof X||!(g instanceof P))throw g;return-g.F}},h:function(a,b,c){Eb=c;try{var d=Z(a);switch(b){case 21509:case 21505:return d.tty?0:-59;case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:return d.tty? 50 | 0:-59;case 21519:if(!d.tty)return-59;var e=Y();return H[e>>2]=0;case 21520:return d.tty?-28:-59;case 21531:a=e=Y();if(!d.u.ga)throw new P(59);return d.u.ga(d,b,a);case 21523:return d.tty?0:-59;case 21524:return d.tty?0:-59;default:return-28}}catch(g){if("undefined"==typeof X||!(g instanceof P))throw g;return-g.F}},i:function(a,b,c,d){Eb=d;try{b=b?F(qa,b):"";var e=b;if("/"===e.charAt(0))b=e;else{var g=-100===a?"/":Z(a).path;if(0==e.length)throw new P(44);b=O(g+"/"+e)}var k=d?Y():0;return qb(b,c,k).fd}catch(r){if("undefined"== 51 | typeof X||!(r instanceof P))throw r;return-r.F}},j:function(a,b,c){qa.copyWithin(a,b,b+c)},f:function(){E("OOM")},a:Fb,b:function(a){try{var b=Z(a);rb(b);return 0}catch(c){if("undefined"==typeof X||!(c instanceof P))throw c;return c.F}},g:function(a,b,c,d){try{a:{var e=Z(a);a=b;for(var g,k=b=0;k>2],q=I[a+4>>2];a+=8;var n=e,l=r,p=q,v=g,x=G;if(0>p||0>v)throw new P(28);if(null===n.fd)throw new P(8);if(1===(n.flags&2097155))throw new P(8);if(16384===(n.node.mode&61440))throw new P(31); 52 | if(!n.u.read)throw new P(28);var u="undefined"!=typeof v;if(!u)v=n.position;else if(!n.seekable)throw new P(70);var t=n.u.read(n,x,l,p,v);u||(n.position+=t);var A=t;if(0>A){var K=-1;break a}b+=A;if(A>2]=K;return 0}catch(D){if("undefined"==typeof X||!(D instanceof P))throw D;return D.F}},e:function(a,b,c,d,e){try{b=c+2097152>>>0<4194305-!!b?(b>>>0)+4294967296*c:NaN;if(isNaN(b))return 61;var g=Z(a);sb(g,b,d);Ea=[g.position>>>0,(N=g.position,1<=+Math.abs(N)? 53 | 0>>0:~~+Math.ceil((N-+(~~N>>>0))/4294967296)>>>0:0)];H[e>>2]=Ea[0];H[e+4>>2]=Ea[1];g.N&&0===b&&0===d&&(g.N=null);return 0}catch(k){if("undefined"==typeof X||!(k instanceof P))throw k;return k.F}},c:function(a,b,c,d){try{a:{var e=Z(a);a=b;for(var g,k=b=0;k>2],q=I[a+4>>2];a+=8;var n=tb(e,G,r,q,g);if(0>n){var l=-1;break a}b+=n;"undefined"!==typeof g&&(g+=n)}l=b}I[d>>2]=l;return 0}catch(p){if("undefined"==typeof X||!(p instanceof 54 | P))throw p;return p.F}}}; 55 | (function(){function a(e){f.asm=e.exports;la=f.asm.k;e=la.buffer;f.HEAP8=G=new Int8Array(e);f.HEAP16=ra=new Int16Array(e);f.HEAP32=H=new Int32Array(e);f.HEAPU8=qa=new Uint8Array(e);f.HEAPU16=new Uint16Array(e);f.HEAPU32=I=new Uint32Array(e);f.HEAPF32=new Float32Array(e);f.HEAPF64=new Float64Array(e);ta.unshift(f.asm.l);za("wasm-instantiate")}function b(e){a(e.instance)}function c(e){return Da().then(function(g){return WebAssembly.instantiate(g,d)}).then(function(g){return g}).then(e,function(g){B("failed to asynchronously prepare wasm: "+ 56 | g);E(g)})}var d={a:Hb};ya("wasm-instantiate");if(f.instantiateWasm)try{return f.instantiateWasm(d,a)}catch(e){return B("Module.instantiateWasm callback failed with error: "+e),!1}(function(){return C||"function"!=typeof WebAssembly.instantiateStreaming||Aa()||M.startsWith("file://")||fa||"function"!=typeof fetch?c(b):fetch(M,{credentials:"same-origin"}).then(function(e){return WebAssembly.instantiateStreaming(e,d).then(b,function(g){B("wasm streaming compile failed: "+g);B("falling back to ArrayBuffer instantiation"); 57 | return c(b)})})})();return{}})();f.___wasm_call_ctors=function(){return(f.___wasm_call_ctors=f.asm.l).apply(null,arguments)};f._main=function(){return(f._main=f.asm.m).apply(null,arguments)};var Gb=f.___errno_location=function(){return(Gb=f.___errno_location=f.asm.n).apply(null,arguments)},Ib=f.stackAlloc=function(){return(Ib=f.stackAlloc=f.asm.p).apply(null,arguments)};f.addRunDependency=ya;f.removeRunDependency=za;f.FS_createPath=xb;f.FS_createDataFile=zb;f.FS_createPreloadedFile=Db; 58 | f.FS_createLazyFile=Bb;f.FS_createDevice=W;f.FS_unlink=nb;var Jb;L=function Lb(){Jb||Mb();Jb||(L=Lb)};function Nb(a){var b=f._main;a=a||[];a.unshift(ca);var c=a.length,d=Ib(4*(c+1)),e=d>>2;a.forEach(k=>{var r=H,q=e++,n=pa(k)+1,l=Ib(n);oa(k,G,l,n);r[q]=l});H[e]=0;try{var g=b(c,d);Fb(g,!0)}catch(k){k instanceof ja||"unwind"==k||da(1,k)}} 59 | function Mb(){function a(){if(!Jb&&(Jb=!0,f.calledRun=!0,!ma)){f.noFSInit||vb||(vb=!0,ub(),f.stdin=f.stdin,f.stdout=f.stdout,f.stderr=f.stderr,f.stdin?W("/dev","stdin",f.stdin):mb("/dev/tty","/dev/stdin"),f.stdout?W("/dev","stdout",null,f.stdout):mb("/dev/tty","/dev/stdout"),f.stderr?W("/dev","stderr",null,f.stderr):mb("/dev/tty1","/dev/stderr"),qb("/dev/stdin",0),qb("/dev/stdout",1),qb("/dev/stderr",1));$a=!1;Fa(ta);Fa(ua);if(f.onRuntimeInitialized)f.onRuntimeInitialized();Ob&&Nb(b);if(f.postRun)for("function"== 60 | typeof f.postRun&&(f.postRun=[f.postRun]);f.postRun.length;){var c=f.postRun.shift();va.unshift(c)}Fa(va)}}var b=b||ba;if(!(0