aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2025-02-17 23:44:07 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-02-17 23:44:07 +0100
commite30801b1d356cf6a7998601433b0c881d6546dcb (patch)
treed6794f490a8301b5357159443d02baa74e0a05de
downloadoide2java-e30801b1d356cf6a7998601433b0c881d6546dcb.tar.gz
oide2java-e30801b1d356cf6a7998601433b0c881d6546dcb.zip
add initial prototype
-rw-r--r--oide2java.html261
1 files changed, 261 insertions, 0 deletions
diff --git a/oide2java.html b/oide2java.html
new file mode 100644
index 0000000..5971dfd
--- /dev/null
+++ b/oide2java.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Convert online-ide projects to java</title>
+ <meta charset="utf8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="author" content="Florian Fischer">
+
+ <style>
+ :root {
+ /* define applied colors */
+ --bg: #fdfdfd;
+ --fg: #1a1a1a;
+ --link-color: #0000EE;
+ }
+ @media (prefers-color-scheme: dark) {
+ /* change apllied colors to the dark gruvbox pallet
+ * https://github.com/morhetz/gruvbox
+ */
+ :root {
+ --bg: #282828; /* dark bg */
+ --fg: #ebdbb2; /* dark fg */
+ --link-color: #d79921; /* yellow */
+ }
+ }
+
+ html {
+ line-height: 1.5;
+ font-family: Georgia, serif;
+ font-size: 20px;
+ color: var(--fg);
+ background-color: var(--bg);
+ }
+
+ body {
+ margin: 0 auto;
+ max-width: 36em;
+ padding-left: 50px;
+ padding-right: 50px;
+ padding-top: 50px;
+ padding-bottom: 50px;
+ hyphens: auto;
+ word-wrap: break-word;
+ text-rendering: optimizeLegibility;
+ font-kerning: normal;
+ }
+
+ footer {
+ position:absolute;
+ bottom: 0;
+ }
+
+ a {
+ color: var(--link-color);
+ }
+
+ a:visited {
+ color: var(--link-color);
+ }
+
+ @media (max-width: 600px) {
+ body {
+ font-size: 0.9em;
+ padding: 1em;
+ }
+ }
+ </style>
+
+ <script language="javascript" type="text/javascript">
+ /* Zip class put into public domain by Spiderpoison
+ https://stackoverflow.com/questions/8608724/how-to-zip-files-using-javascript
+ */
+ class Zip {
+
+ constructor(name) {
+ this.name = name;
+ this.zip = new Array();
+ this.file = new Array();
+ }
+
+ dec2bin=(dec,size)=>dec.toString(2).padStart(size,'0');
+ str2dec=str=>Array.from(new TextEncoder().encode(str));
+ str2hex=str=>[...new TextEncoder().encode(str)].map(x=>x.toString(16).padStart(2,'0'));
+ hex2buf=hex=>new Uint8Array(hex.split(' ').map(x=>parseInt(x,16)));
+ bin2hex=bin=>(parseInt(bin.slice(8),2).toString(16).padStart(2,'0')+' '+parseInt(bin.slice(0,8),2).toString(16).padStart(2,'0'));
+
+ reverse=hex=>{
+ let hexArray=new Array();
+ for(let i=0;i<hex.length;i=i+2)hexArray[i]=hex[i]+''+hex[i+1];
+ return hexArray.filter((a)=>a).reverse().join(' ');
+ }
+
+ crc32=r=>{
+ for(var a,o=[],c=0;c<256;c++){
+ a=c;
+ for(var f=0;f<8;f++)a=1&a?3988292384^a>>>1:a>>>1;
+ o[c]=a;
+ }
+ for(var n=-1,t=0;t<r.length;t++)n=n>>>8^o[255&(n^r[t])];
+ return this.reverse(((-1^n)>>>0).toString(16).padStart(8,'0'));
+ }
+
+ fecth2zip(filesArray,folder=''){
+ filesArray.forEach(fileUrl=>{
+ let resp;
+ fetch(fileUrl).then(response=>{
+ resp=response;
+ return response.arrayBuffer();
+ }).then(blob=>{
+ new Response(blob).arrayBuffer().then(buffer=>{
+ console.log(`File: ${fileUrl} load`);
+ let uint=[...new Uint8Array(buffer)];
+ uint.modTime=resp.headers.get('Last-Modified');
+ uint.fileUrl=`${this.name}/${folder}${fileUrl}`;
+ this.zip[fileUrl]=uint;
+ });
+ });
+ });
+ }
+
+ str2zip(name,str,folder){
+ let uint=[...new Uint8Array(this.str2dec(str))];
+ uint.name=name;
+ uint.modTime=new Date();
+ uint.fileUrl=`${this.name}/${folder}${name}`;
+ this.zip[uint.fileUrl]=uint;
+ }
+
+ files2zip(files,folder){
+ for(let i=0;i<files.length;i++){
+ files[i].arrayBuffer().then(data=>{
+ let uint=[...new Uint8Array(data)];
+ uint.name=files[i].name;
+ uint.modTime=files[i].lastModifiedDate;
+ uint.fileUrl=`${this.name}/${folder}${files[i].name}`;
+ this.zip[uint.fileUrl]=uint;
+ });
+ }
+ }
+
+ makeZip(){
+ let count=0;
+ let fileHeader='';
+ let centralDirectoryFileHeader='';
+ let directoryInit=0;
+ let offSetLocalHeader='00 00 00 00';
+ let zip=this.zip;
+ for(const name in zip){
+ let modTime=(()=>{
+ const lastMod=new Date(zip[name].modTime);
+ const hour=this.dec2bin(lastMod.getHours(),5);
+ const minutes=this.dec2bin(lastMod.getMinutes(),6);
+ const seconds=this.dec2bin(Math.round(lastMod.getSeconds()/2),5);
+ const year=this.dec2bin(lastMod.getFullYear()-1980,7);
+ const month=this.dec2bin(lastMod.getMonth()+1,4);
+ const day=this.dec2bin(lastMod.getDate(),5);
+ return this.bin2hex(`${hour}${minutes}${seconds}`)+' '+this.bin2hex(`${year}${month}${day}`);
+ })();
+ let crc=this.crc32(zip[name]);
+ let size=this.reverse(parseInt(zip[name].length).toString(16).padStart(8,'0'));
+ let nameFile=this.str2hex(zip[name].fileUrl).join(' ');
+ let nameSize=this.reverse(zip[name].fileUrl.length.toString(16).padStart(4,'0'));
+ let fileHeader=`50 4B 03 04 14 00 00 00 00 00 ${modTime} ${crc} ${size} ${size} ${nameSize} 00 00 ${nameFile}`;
+ let fileHeaderBuffer=this.hex2buf(fileHeader);
+ directoryInit=directoryInit+fileHeaderBuffer.length+zip[name].length;
+ centralDirectoryFileHeader=`${centralDirectoryFileHeader}50 4B 01 02 14 00 14 00 00 00 00 00 ${modTime} ${crc} ${size} ${size} ${nameSize} 00 00 00 00 00 00 01 00 20 00 00 00 ${offSetLocalHeader} ${nameFile} `;
+ offSetLocalHeader=this.reverse(directoryInit.toString(16).padStart(8,'0'));
+ this.file.push(fileHeaderBuffer,new Uint8Array(zip[name]));
+ count++;
+ }
+ centralDirectoryFileHeader=centralDirectoryFileHeader.trim();
+ let entries=this.reverse(count.toString(16).padStart(4,'0'));
+ let dirSize=this.reverse(centralDirectoryFileHeader.split(' ').length.toString(16).padStart(8,'0'));
+ let dirInit=this.reverse(directoryInit.toString(16).padStart(8,'0'));
+ let centralDirectory=`50 4b 05 06 00 00 00 00 ${entries} ${entries} ${dirSize} ${dirInit} 00 00`;
+ this.file.push(this.hex2buf(centralDirectoryFileHeader),this.hex2buf(centralDirectory));
+ let a = document.createElement('a');
+ a.href = URL.createObjectURL(new Blob([...this.file],{type:'application/octet-stream'}));
+ a.download = `${this.name}.zip`;
+ a.click();
+ }
+ }
+ </script>
+
+ <script language="javascript" type="text/javascript">
+ /*
+ @licstart The following is the entire license notice for the
+ JavaScript code in this page.
+
+ Copyright (C) 2025 Florian Fischer
+
+ The JavaScript code in this page is free software: you can
+ redistribute it and/or modify it under the terms of the GNU
+ General Public License (GNU GPL) as published by the Free Software
+ Foundation, either version 3 of the License, or any later version.
+ The code is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
+
+ As additional permission under GNU GPL version 3 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU GPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ @licend The above is the entire license notice
+ for the JavaScript code in this page.
+ */
+
+ function convertCode(oideCode) {
+ // TODO: Use a better regex
+ // let printlnRegex = /^(\s*)(println)/g
+ let printlnRegex = /println/g
+ javaCode = oideCode.replace(printlnRegex, "System.out.println");
+
+ // TODO: Warn about long
+
+ // TODO: Implement Online-IDE convenience conversion
+
+ // TODO: move code outside of a class into a main method
+ return javaCode;
+ }
+
+ function oide2java(workspace) {
+ let z = new Zip(workspace.name);
+ for (let module of workspace.modules) {
+ let moduleCode = convertCode(module.text);
+ z.str2zip(module.name + ".java", moduleCode, "");
+ }
+ z.makeZip();
+ }
+
+ function convertWorkspaceFile() {
+ let workspaceFile = document.getElementById("json").files[0];
+ let reader = new FileReader();
+ reader.readAsText(workspaceFile);
+
+ reader.onload = function() {
+ oide2java(JSON.parse(reader.result));
+ };
+ }
+ </script>
+</head>
+
+<body>
+<h2>Convert an Online-IDE workspace to java code</h2>
+<p><i>The conversation is done by your browser and no data is transfered to or otherwise processed by a third party.</i></p>
+<div>
+<form>
+ Online-IDE workspace:
+ <input id="json" type="file" />
+ <input id="convert_button" value="convert" type="button" onclick="convertWorkspaceFile();" />
+ </code>
+</form>
+</div>
+<footer>
+<p xmlns:cc="http://creativecommons.org/ns#">Diese Seite von <span property="cc:attributionName">Florian Fischer</span> ist unter folgender Lizenz veröffentlicht: <a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg?ref=chooser-v1" alt=""></a></p>
+</footer>
+
+</body>
+</html>