diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..e98d284
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,11 @@
+*Short introduction of your problem.*
+
+__Input code:__
+```vb
+/* The code your entered in the input textarea */
+```
+
+__Output code:__
+```arduino
+/* The code outputted by the script, or 'none' if no script outputted */
+```
diff --git a/Dckuino.js b/Dckuino.js
deleted file mode 100644
index c511379..0000000
--- a/Dckuino.js
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Dckuino.js, an open source project licenced under MIT License
- */
-
-/* jshint esversion: 6 */
-/* jshint laxbreak: true */
-
-var commandMap = { // Key that can be typed
- ESCAPE:'KEY_ESC',
- ESC:'KEY_ESC',
- GUI:'KEY_LEFT_GUI',
- WINDOWS:'KEY_LEFT_GUI',
- COMMAND:'KEY_LEFT_GUI',
- MENU:'229',
- APP:'229',
- END:'KEY_END',
- SPACE:'\' \'',
- TAB:'KEY_TAB',
- PRINTSCREEN:'206',
- ENTER:'KEY_RETURN',
- RETURN:'KEY_RETURN',
- UPARROW:'KEY_UP_ARROW',
- DOWNARROW:'KEY_DOWN_ARROW',
- LEFTARROW:'KEY_LEFT_ARROW',
- RIGHTARROW:'KEY_RIGHT_ARROW',
- UP:'KEY_UP_ARROW',
- DOWN:'KEY_DOWN_ARROW',
- LEFT:'KEY_LEFT_ARROW',
- RIGHT:'KEY_RIGHT_ARROW',
- CAPSLOCK:'KEY_CAPS_LOCK',
- DELETE:'KEY_DELETE',
- DEL:'KEY_DELETE',
- F1:'KEY_F1',
- F2:'KEY_F2',
- F3:'KEY_F3',
- F4:'KEY_F4',
- F5:'KEY_F5',
- F6:'KEY_F6',
- F7:'KEY_F7',
- F8:'KEY_F8',
- F9:'KEY_F9',
- F10:'KEY_F10',
- F11:'KEY_F11',
- F12:'KEY_F12',
- PAGEUP:'KEY_PAGE_UP',
- PAGEDOWN:'KEY_PAGE_DOWN'
-};
-
-var comboMap = { // Key that can only be used in combos
- ALT:'KEY_LEFT_ALT',
- SHIFT:'KEY_LEFT_SHIFT',
- CTRL:'KEY_LEFT_CTRL',
- CONTROL:'KEY_LEFT_CTRL'
-};
-
-var keyMap = { // Normal keys
- a:'a',
- b:'b',
- c:'c',
- d:'d',
- e:'e',
- f:'f',
- g:'g',
- h:'h',
- i:'i',
- j:'j',
- k:'k',
- l:'l',
- m:'m',
- n:'n',
- o:'o',
- p:'p',
- q:'q',
- r:'r',
- s:'s',
- t:'t',
- u:'u',
- v:'v',
- w:'w',
- x:'x',
- y:'y',
- z:'z'
-};
-
-class Dckuinojs {
- constructor() {
- this.keyMap = keyMap;
- this.commandMap = commandMap;
- this.comboMap = comboMap;
- }
-
- toArduino(inputCode)
- {
- // Check if the parameter is empty or undefined
- if (inputCode === '' || inputCode === undefined)
- {
- console.error('Error: No ducky script was entered !');
- return false;
- } // Parsing
-
- var parsedDucky = this._parse(inputCode);
- if (parsedDucky === '' || parsedDucky === undefined)
- {
- return false;
- } // Returning the total uploadable script
-
- return '/*\n'
- + ' * Generated with <3 by Dckuino.js, an open source project !\n'
- + ' */\n\n'
- + '#include "Keyboard.h"\n\n'
- + 'void typeKey(uint8_t key)\n'
- + '{\n'
- + ' Keyboard.press(key);\n'
- + ' delay(50);\n'
- + ' Keyboard.release(key);\n'
- + '}\n\n'
- + '/* Init function */\n'
- + 'void setup()\n'
- + '{\n'
- + ' // Begining the Keyboard stream\n'
- + ' Keyboard.begin();\n\n'
- + ' // Wait 500ms\n'
- + ' delay(500);\n'
- + '\n' + parsedDucky
- + ' // Ending stream\n'
- + ' Keyboard.end();\n'
- + '}\n\n'
- + '/* Unused endless loop */\n'
- + 'void loop() {}';
- }
-
- // The parsing function
- _parse(toParse)
- {
- // Init chronometer
- var timerStart = Date.now();
-
- // Preset all used vars
- var parsedScript = '';
- var lastLines;
- var lastCount;
- var parsedOut = '';
-
- var commandKnown = false;
- var releaseAll = false;
- var noNewline = false;
- var noDelay = false;
- var nextNoDelay = false;
-
- var wordArray;
- var wordOne;
-
- // Init default delay
- var defaultDelay = 0;
-
- // Trim whitespaces
- toParse = toParse.replace(/^ +| +$/gm, '');
-
- // Remove all *ugly* tabs
- toParse = toParse.replace(/\t/g, '');
-
- // Cut the input in lines
- var lineArray = toParse.split('\n');
-
- // Loop every line
- for (var i = 0; i < lineArray.length; i++)
- {
- // Line empty, skip
- if (lineArray[i] === '' || lineArray[i] === '\n')
- {
- console.log('Info: Skipped line ' + (i + 1) + ', because was empty.');
- continue;
- }
-
- // Outputs, for REPLAY/REPEAT COMMANDS
- if (parsedOut !== undefined && parsedOut !== '')
- {
- lastLines = parsedOut;
- lastCount = ((lastLines.split('\n')).length + 1);
- }
-
- // Reset line buffer
- parsedOut = '';
-
- // Set to unknown command by default
- commandKnown = false;
-
- // releaseAll & noNewline & noDelay; *Line Modifiers*
- releaseAll = false;
- noNewline = false;
- noDelay = nextNoDelay;
- nextNoDelay = false;
-
- // Cut every line in words & store the first word in a var
- wordArray = lineArray[i].split(' ');
- wordOne = wordArray[0];
-
- // Parse commands
- switch(wordOne){
- case "STRING":
- wordArray.shift();
-
- var textString = wordArray.join(' ');
-
- // Replace all '"' by '\"' and all '\' by '\\'
- textString = textString.split('\\').join('\\\\').split('"').join('\\"');
- if (textString !== '')
- {
- parsedOut = ' Keyboard.print(F("' + textString + '"));\n';
- commandKnown = true;
- } else {
- console.error('Error: at line: ' + (i + 1) + ', STRING needs a text');
- return;
- }
- break;
- case "DELAY":
- wordArray.shift();
-
- if(wordArray[0] === undefined || wordArray[0] === '') {
- console.error('Error: at line: ' + (i + 1) + ', DELAY needs a time');
- return;
- }
-
- if (! isNaN(wordArray[0]))
- {
- parsedOut = ' delay(' + wordArray[0] + ');\n';
- commandKnown = true; noDelay = true; nextNoDelay = true;
- } else {
- console.error('Error: at line: ' + (i + 1) + ', DELAY only acceptes numbers');
- return;
- }
- break;
- case "DEFAULT_DELAY":
- wordArray.shift();
-
- if(wordArray[0] === undefined || wordArray[0] === '') {
- console.error('Error: at line: ' + (i + 1) + ', DEFAULT_DELAY needs a time');
- return;
- }
-
- if (! isNaN(wordArray[0]))
- {
- defaultDelay = wordArray[0];
- commandKnown = true; noNewline = true; noDelay = true;
- } else {
- console.error('Error: at line: ' + (i + 1) + ', DEFAULT_DELAY only acceptes numbers');
- return;
- }
- break;
- case "TYPE":
- wordArray.shift();
-
- if(wordArray[0] === undefined || wordArray[0] === '') {
- console.error('Error: at line: ' + (i + 1) + ', TYPE needs a key');
- return;
- }
-
- if (keyMap[wordArray[0]] !== undefined)
- {
- commandKnown = true;
- // Replace the DuckyScript key by the Arduino key name
- parsedOut = ' typeKey(\'' + keyMap[wordArray[0]] + '\');\n';
- } else {
- console.error('Error: Unknown letter \'' + wordArray[0] +'\' at line: ' + (i + 1));
- return;
- }
- break;
- case "REM":
- wordArray.shift();
-
- // Placing the comment to arduino code
- if (wordArray.length > 0)
- {
- commandKnown = true; noDelay= true;
- parsedOut = ' // ' + wordArray.join(' ');
- if (i == (lineArray.length - 1))
- parsedOut += '\n';
- } else {
- console.error('Error: at line: ' + (i + 1) + ', REM needs a comment');
- return;
- }
- break;
- case "REPEAT":
- case "REPLAY":
- wordArray.shift();
-
- if (wordArray[0] === undefined || wordArray[0] === '') {
- console.error('Error: at line: ' + (i + 1) + ', REPEAT/REPLAY needs a loop count');
- return;
- }
-
- if (lastLines === undefined)
- {
- console.error('Error: at line: ' + (i + 1) + ', nothing to repeat, this is the first line.');
- return;
- }
-
- if (! isNaN(wordArray[0]))
- {
- // Remove the lines we just created
- var linesTmp = parsedScript.split('\n');
- linesTmp.splice(-lastCount, lastCount);
-
- if (linesTmp.join('\n') === '')
- parsedScript = linesTmp.join('\n');
- else {
- parsedScript = linesTmp.join('\n') + '\n';
- }
-
- // Add two spaces at Begining
- lastLines = lastLines.replace(/^ /gm,' ');
-
- // Replace them
- parsedOut = ' for(int i = 0; i < ' + wordArray[0] + '; i++) {\n';
- parsedOut += lastLines;
- parsedOut += ' }\n';
-
- commandKnown = true; noDelay = true;
- } else {
- console.error('Error: at line: ' + (i + 1) + ', REPEAT/REPLAY only acceptes numbers');
- return;
- }
- break;
- default:
- if (wordArray.length == 1)
- {
- if (comboMap[wordArray[0]] !== undefined)
- {
- commandKnown = true;
-
- parsedOut = ' typeKey(' + comboMap[wordArray[0]] + ');\n';
- }else if (commandMap[wordArray[0]] !== undefined) {
- commandKnown = true;
-
- parsedOut = ' typeKey(' + commandMap[wordArray[0]] + ');\n';
- }else {
- commandKnown = false;
- break;
- }
- wordArray.shift();
- }
- while (wordArray.length){
- if (comboMap[wordArray[0]] !== undefined)
- {
- commandKnown = true;
- releaseAll = true;
-
- parsedOut += ' Keyboard.press(' + comboMap[wordArray[0]] + ');\n';
- }else if (commandMap[wordArray[0]] !== undefined) {
- commandKnown = true;
- releaseAll = true;
-
- parsedOut += ' Keyboard.press(' + commandMap[wordArray[0]] + ');\n';
- }else if (keyMap[wordArray[0]] !== undefined) {
- commandKnown = true;
- releaseAll = true;
-
- parsedOut += ' Keyboard.press(\'' + keyMap[wordArray[0]] + '\');\n';
- }else {
- commandKnown = false;
- break;
- }
- wordArray.shift();
- }
- }
-
- if (!commandKnown)
- {
- console.error('Error: Unknown command or key \'' + wordArray[0] + '\' at line: ' + (i + 1) + '.');
- return;
- }
-
- // If we need to release keys, we do
- if (releaseAll)
- parsedOut += ' Keyboard.releaseAll();\n';
-
- // If there is a default delay add it
- if (defaultDelay > 0 && !noDelay)
- parsedOut = ' delay(' + defaultDelay + ');\n\n' + parsedOut;
-
- parsedScript += parsedOut; // Add what we parsed
-
- if (!noNewline)
- parsedScript += '\n'; // Add new line
- }
-
- var timerEnd = Date.now();
- var timePassed = new Date(timerEnd - timerStart);
-
- console.log('Done parsed ' + (lineArray.length) + ' lines in ' + timePassed.getMilliseconds() + 'ms');
- return parsedScript;
- }
-}
diff --git a/Duckuino.js b/Duckuino.js
new file mode 100644
index 0000000..fc7b703
--- /dev/null
+++ b/Duckuino.js
@@ -0,0 +1,243 @@
+/**
+ * Duckuino, an open source project licenced under MIT License
+ * GitHub repo can be found at the following link:
+ * - https://github.com/Nurrl/Duckuino
+ */
+
+/* jshint esversion: 6 */
+
+/* Function to request files */
+function getFile(sUrl) {
+ /* Init request */
+ var oReq = new XMLHttpRequest();
+
+ /* Sending request */
+ oReq.open("get", sUrl, false);
+ oReq.overrideMimeType("text/plain");
+ oReq.send(null);
+
+ /* Getting response */
+ if (oReq.readyState == 4 && (oReq.status == 200 || oReq.status === 0)) {
+ return oReq.responseText;
+ } else {
+ return undefined;
+ }
+}
+
+class Duckuino {
+ constructor() {}
+
+ listModules() {
+ /* List all modules in the moduleList file */
+ if (!this.moduleArray) {
+ this.moduleArray = getFile("modules/modules").split('\n');
+ this.moduleArray.pop();
+ }
+
+ /* Return the list */
+ return this.moduleArray;
+ }
+
+ loadModule(moduleName) {
+ /* Check if module exists */
+ if (this.listModules().indexOf(moduleName) == -1) {
+ console.error("Error: This module doesn't exist !");
+
+ /* Module is not loaded */
+ this.loadedModule = undefined;
+ } else {
+ /* Load module *//* jshint evil:true */
+ this.loadedModule = eval(getFile("modules/" + moduleName + ".js"));
+ }
+ }
+
+ /* TO-DO: getModuleInfos() {} */
+
+ compileCode(compileStr) {
+ /* Init timer */
+ var timerStart = window.performance.now();
+
+ /* Check if module loaded */
+ if (this.loadedModule === undefined) {
+ return {
+ compiledCode: undefined,
+ compileTime: -1,
+
+ returnCode: 9,
+ returnMessage: "Error: No module loaded !",
+ errorList: this.errorList
+ };
+ }
+
+ /* Check if code is empty */
+ if (compileStr === undefined || compileStr === "") {
+ return {
+ compiledCode: undefined,
+ compileTime: -1,
+
+ returnCode: 9,
+ returnMessage: "Error: No input was entered !",
+ errorList: this.errorList
+ };
+ }
+
+ /* Trim whitespaces and tabs */
+ compileStr = compileStr.replace(/^ +| +$/gm, '');
+ compileStr = compileStr.replace(/\t/g, '');
+
+ /* Errors */
+ this.errorList = [];
+
+ /* Preset all used vars */
+ this.dataStorage = new Object();
+ this.compiledCode = '';
+
+ var commandKnown;
+ var lineStr;
+ var lastLine = ''; var lastLineCount = 0;
+
+ /* Cut the input in lines */
+ var lineArray = compileStr.split('\n');
+
+ /* Loop every line */
+ for (var i = 0; i < lineArray.length; i++)
+ {
+ /* Line empty, skip */
+ if (lineArray[i] === '' || lineArray[i] === '\n')
+ continue;
+
+ /* Reset vars */
+ commandKnown = false;
+ lineStr = '';
+
+ /* Split lines in words */
+ var argList = lineArray[i].split(' ');
+ var argOne = argList[0];
+
+ /* Parse commands */
+ if (this.loadedModule.functionMap[argOne] !== undefined) {
+ var µ = new Object({
+ keyMap: this.loadedModule.keyMap,
+ /**
+ * Pushes the error to the global error list.
+ */
+ throwError: function(thisPtr, currentLine) {
+ return function(errorMessage) {
+ thisPtr.errorList.push({
+ errorMessage: errorMessage,
+ errorLine: currentLine
+ });
+ };
+ }(this, (i + 1)),
+ /**
+ * This one is to get the lastLine, and in the same way trim
+ * it from from the current compiledCode, this is a workaround for
+ * the REPLAY command.
+ */
+ trimLast: function(thisPtr, lastLine, lastLineCount) {
+ return function() {
+ var tmpVar = thisPtr.compiledCode.split('\n');
+
+ tmpVar.splice(-lastLineCount, lastLineCount - 1);
+ thisPtr.compiledCode = tmpVar.join('\n');
+
+ return lastLine;
+ };
+ }(this, lastLine, lastLineCount),
+ /**
+ * Those two function are used to store persistent data, i.e:
+ * Default Delay.
+ */
+ setData: function(thisPtr) {
+ return function(dataName, dataValue) {
+ thisPtr.dataStorage[dataName] = dataValue;
+ };
+ }(this),
+ getData: function(thisPtr) {
+ return function(dataName) {
+ return thisPtr.dataStorage[dataName];
+ };
+ }(this),
+ });
+
+ /* Execute the function and add the returned string to the current string */
+ lineStr += this.loadedModule.functionMap[argOne](argList, µ);
+
+ /* Post process the line */
+ lineStr = this.loadedModule.postLine(lineStr, µ);
+ } else { /* Parse keystokes */
+ var strokeArray = Array();
+
+ for(var y = 0; y < argList.length; y++) {
+
+ if(this.loadedModule.commandMap[argList[y]] !== undefined) {
+ /* Push key to Array */
+ strokeArray.push(this.loadedModule.commandMap[argList[y]]);
+ } else if(this.loadedModule.comboMap[argList[y]] !== undefined) {
+ /* Push key to Array */
+ strokeArray.push(this.loadedModule.comboMap[argList[y]]);
+ } else if(this.loadedModule.keyMap[argList[y]] !== undefined && y != 0) {
+ /* Push key to Array */
+ strokeArray.push('"' + this.loadedModule.keyMap[argList[y]] + '"');
+ } else {
+ /* If command unknown, throw error */
+ this.errorList.push({
+ errorMessage: "Unknown command or key: '" + argList[y] + "'",
+ errorLine: (i + 1)
+ });
+ }
+ }
+
+ /* Transform key array to string */
+ lineStr += this.loadedModule.computeKeys(strokeArray);
+ }
+
+ /* Calculate line count */
+ lastLineCount = lineStr.split('\n').length;
+
+ /* Append this compiled line to global output */
+ lastLine = lineStr;
+ this.compiledCode += lineStr;
+ }
+
+ /* Stop timer */
+ var timerEnd = window.performance.now();
+ var timeElapsed = (timerEnd - timerStart).toFixed(2);
+
+ /* Return error if error and code if not */
+ if (this.errorList.length > 0) {
+ /* Return error(s) */
+ return {
+ compiledCode: undefined,
+ compileTime: -1,
+
+ returnCode: 1,
+ returnMessage: function(errorList) {
+ var errorString;
+
+ if(errorList.length > 1) {
+ errorString = "The compiler returned some errors:\n";
+ } else {
+ errorString = "The compiler returned an error:\n";
+ }
+
+ errorList.forEach(function(errorObj) {
+ errorString += "Line " + errorObj.errorLine + " -> " + errorObj.errorMessage + "\n";
+ });
+
+ return errorString;
+ }(this.errorList),
+ errorList: this.errorList
+ };
+ } else {
+ /* Return the compiled code */
+ return {
+ compiledCode: this.loadedModule.getFinalCode(this.compiledCode),
+ compileTime: timeElapsed,
+
+ returnCode: 0,
+ returnMessage: "Info: Code successfully parsed in " + timeElapsed + "ms !"
+ };
+ }
+ }
+}
diff --git a/LICENSE b/LICENSE
index 00c0027..21ae38f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2017 Nurrl
+Copyright (c) 2016-2017 Nurrl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 07257e0..5b5e1a2 100644
--- a/README.md
+++ b/README.md
@@ -1,77 +1,27 @@
-# Duckuino
+# Duckuino ![release](https://img.shields.io/github/release/Nurrl/Duckuino/all.svg)
Simple DuckyScript to Arduino converter.
If you need to perform mouse emulation then use [d4n5h's Duckuino](https://github.com/d4n5h/Duckuino).
*NOTE: If you are on linux, you might use the Arduino IDE from the website, not from apt, because the apt repo is not up to date.*
-# Live version:
+### Warning: Release note
+This release is an unstable version, for now some things may or may not work, please [*open an issue*](https://github.com/Nurrl/Duckuino/issues/new) if you find a bug.
+
+*The stable version will be released in few days, maybe :D*
+## Live version:
https://nurrl.github.io/Duckuino/
-# Why Duckuino ?
-You can compile duckyscript to arduino code directly through the [live](https://nurrl.github.io/Duckuino/ "Duckuino Live") version, or reuse Dckuino.js
for standalone use :
+## Why Duckuino ?
+You can compile **Duckyscript** to **Arduino** code directly through the [live](https://nurrl.github.io/Duckuino/ "Duckuino Live") version, or reuse Duckuino.js
for standalone use :
```javascript
-// Create the instance
-Duck = new Dckuinojs();
-
-var DuckyScript = "CTRL ALT t\n"
-+ "DELAY 1000\n"
-+ "STRING gedit\n"
-+ "ENTER\n"
-+ "DELAY 1000\n"
-+ "STRING Hello World !"
-
-var ArduinoCode = Duck.toArduino(DuckyScript);
-
-console.log(ArduinoCode);
+/* Need to fill */
```
Output:
```c
-/*
- * Generated with <3 by Dckuino.js, an open source project !
- */
-
-#include
-
-void typeKey(int key)
-{
- Keyboard.press(key);
- delay(50);
- Keyboard.release(key);
-}
-
-// Init function
-void setup()
-{
- // Begining the stream
- Keyboard.begin();
-
- // Waiting 500ms for init
- delay(500);
-
- Keyboard.press(KEY_LEFT_CTRL);
- Keyboard.press(KEY_LEFT_ALT);
- Keyboard.press(116);
- Keyboard.releaseAll();
-
- delay(1000);
-
- Keyboard.print("gedit");
-
- typeKey(KEY_RETURN);
-
- delay(1000);
-
- Keyboard.print("Hello World !");
- // Ending stream
- Keyboard.end();
-}
-
-// Unused
-void loop() {}
+/* Need to fill */
```
# Members
- [Plazmaz](https://github.com/Plazmaz)
- [Nurrl](https://github.com/Nurrl)
-
diff --git a/assets/css/style.css b/assets/css/style.css
index d3c7682..7c4e0fd 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -10,135 +10,211 @@ html, body {
font-family: Lato, sans-serif;
font-size: 16px;
- /* Scroll */
+ /* Disable Scroll */
overflow: hidden;
- /* Background */
- background: #333333;
-
/* Size */
height: 100%; width: 100%;
}
-menu {
+/* Background blured image */
+body::before {
/* Position */
- position: relative;
- top: 0;
+ position: absolute;
+ top: 0; left: 0;
- /* Color */
- background: #f6f6f6;
+ /* Size */
+ height: 100%; width: 100%;
- /* Size and spacing */
- margin: 0; padding: 0;
- width: 100%; height: 48px;
+ /* Background */
+ background-size: cover;
+ background-image: url(../imgs/background.jpg);
+ background-repeat: no-repeat;
+ background-position: center;
+
+ /* Misc */
+ /*filter: blur(1px);*/
+ content: "";
+ z-index: -1;
+}
- /* Prepare underligning */
- padding-bottom: 2px;
+/* Text */
+h1 {
+ margin: 0;
+}
+h6 {
+ margin: 0;
+ opacity: .7;
+}
- /* Text style overrride */
- font-size: 16px;
+/* Textareas */
+textarea {
+ width: 100%; height: 50vh;
+ border: none; border-radius: 4px;
+ padding: 8px;
- /* Overflow */
- overflow: hidden;
+ box-sizing: border-box;
+ resize: none;
}
-menu .left {float: left;}
-menu .right {float: right;}
-menu a {
- /* Position */
- display: block;
- padding: 0 16px;
- /* Height */
- height: 48px;
+/* Buttons */
+button {
+ /* Style */
+ color: black;
+ cursor: pointer;
+ background-color: white;
+ border: 1px solid white;
+
+ /* Size */
+ width: 128px;
+ height: 32px;
- /* Text styling */
- text-decoration: none;
- text-align: center;
- line-height: 48px;
- color: #333333;
+ /* Animation */
+ transition: .2s;
}
-menu a.hoverable:hover {
- /* On hover */
- background: #eeeeee;
- box-shadow: 0 2px 0 0 #333333;
+button:not(:disabled):hover {
+ /* Style */
+ background-color: transparent;
+ color: white;
- /* Cursor style */
- cursor: pointer;
+ /* Animation */
+ transition: .2s;
}
+button:disabled {
+ /* Style */
+ color: white;
+ background-color: transparent;
-.inout-wrapper {
- position: relative;
- margin: 16px;
+ /* Back pattern */
+ background-size: 32px 32px;
+ background-image: linear-gradient(135deg, rgba(255, 255, 255, 1) 25%, transparent 25%,
+ transparent 50%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 1) 75%,
+ transparent 75%, transparent);
+
+ cursor: default;
- width: 100%; height: calc(100% - 38px - 50px - 48px); /* 100% - console - menu - margin */
+ /* Opacity */
+ opacity: .5;
}
-.inout {
- border: 1px solid #f6f6f6;
- border-radius: 3px;
- background: #f6f6f6;
- color: #333333;
+/* Top bar */
+.menu {
+ position: absolute;
+ top: 0;
- resize: none;
+ width: 100%;
+}
+.menu a {
+ float: right;
+ margin: 16px;
+
+ text-transform: uppercase;
+ text-decoration: none;
+ color: white;
- padding: 2px;
- width: calc(50% - 16px - 8px);
- height: 100%;
+ transition: .2s;
+}
+.menu a:hover {
+ transition: .2s;
+ color: black;
}
-.inout .duckyscript {float: left;}
-.inout .arduino {float: right;}
-.console {
- border: 1px solid #f6f6f6;
- border-radius: 3px;
+/* Page organization */
+.group {
+ /* Size */
+ width: 100%; height: 100%;
- background: #f6f6f6;
- color: #333333;
+ /* Center parts */
+ display: flex;
+}
- overflow: hidden;
- resize: none;
-
+.part {
+ /* Position */
+ margin: 0 1.5%; padding: 16px;
+ align-self: center;
+ width: 30%;
+ float: left;
+
+ box-sizing: border-box;
+ border-radius: 4px;
+
+ /* Separation */
+ /*box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);*/
+
+ /* Text */
+ color: white;
+}
+
+/* Elements */
+.process {
+ /* Center text */
+ text-align: center;
+}
+
+/* Info/error tooltip */
+.tooltip {
position: relative;
-
- padding: 2px; margin: 8px 16px;
- width: calc(100% - 32px - 8px); /* Wrapper width - (margin + padding + textarea borders) */
- height: 32px;
- line-height: 32px;
+ width: 100%;
+
+ display: none;
}
+.tooltip > span {
+ /* Size */
+ position: absolute;
+ width: 90%;
-/* The download popup */
-.modal {
- display: none; /* Hidden by default */
- position: fixed; /* Stay in place */
- z-index: 1; /* Sit on top */
- left: 0;
- top: 0;
- width: 100%; /* Full width */
- height: 100%; /* Full height */
- overflow: auto; /* Enable scroll if needed */
- background-color: rgb(0,0,0); /* Fallback color */
- background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
+ /* Position */
+ left: 50%;
+ transform: translateX(-50%);
+ margin-top: 12px;
+ z-index: -1;
+
+ /* Style */
+ text-align: left;
+ border-radius: 4px;
+ white-space: pre-wrap;
+ padding: 4px;
+ color: white;
+}
+.tooltip > span::before {
+ content: "";
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ margin-left: -8px;
+ border-width: 8px;
+ border-style: solid;
}
+.tooltip.info > span {background-color: #029bc9;}
+.tooltip.info > span::before {border-color: transparent transparent #029bc9 transparent;}
-/* Popup Content/Box */
-.modal-content {
- background-color: #fefefe;
- margin: 15% auto; /* 15% from the top and centered */
- padding: 20px;
- border: 1px solid #888;
- width: 80%; /* Could be more or less, depending on screen size */
+.tooltip.error > span {background-color: #cc0000;}
+.tooltip.error > span::before {border-color: transparent transparent #cc0000 transparent;}
+
+.combined-but > button {
+ width: 112px;
+ border-right: 0;
}
+.combined-but > select {
+ /* Postion */
+ margin-left: -4px;
-/* The Close Button */
-.close {
- color: #aaa;
- float: right;
- font-size: 28px;
- font-weight: bold;
+ /* Style */
+ color: transparent;
+ border: 1px solid white;
+ border-left: 0;
+
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background: url(../imgs/arrow-down.png) no-repeat white center;
+
+ /* Size */
+ width: 16px;
+ height: 32px;
}
-.close:hover,
-.close:focus {
- color: black;
- text-decoration: none;
- cursor: pointer;
+.combined-but > select:disabled {
+ /* Postion */
+ opacity: .5;
}
diff --git a/assets/imgs/arrow-down.png b/assets/imgs/arrow-down.png
new file mode 100644
index 0000000..726f415
Binary files /dev/null and b/assets/imgs/arrow-down.png differ
diff --git a/assets/imgs/background.jpg b/assets/imgs/background.jpg
new file mode 100644
index 0000000..dc0e19c
Binary files /dev/null and b/assets/imgs/background.jpg differ
diff --git a/assets/js/main.js b/assets/js/main.js
index 117cc06..505974a 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -1,86 +1,82 @@
-jQuery(function() { // Wait for jQuery
+$(function() { /* Wait for jQuery */
- init();
+ /* Init vars */
+ var isCodeCompiled = false;
+ var LocKey = new LocaleKeyboard();
+ var Duck = new Duckuino();
- // Check if download button can be used
try {
var isFileSaverSupported = !!new Blob();
} catch (e) {}
- // Hijack console.log and console.error
- (function(){
- var oldLog = console.log;
- console.log = function (message) {
- $(".console").val(" ℹ - " + message + '\n');
- $(".console").css("color", "#2b2b2b");
- oldLog.apply(console, arguments);
- };
- var oldErrorLog = console.error;
- console.error = function (message) {
- $(".console").val(" ⚠ - " + message + '\n');
- $(".console").css("color", "#ff3434");
- oldErrorLog.apply(console, arguments);
- };
- })();
-
- // Create a little duck translator
- Duck = new Dckuinojs();
-
- // Compile button
- $(".compile-but").click(function(e) {
- var duckOutput = Duck.toArduino($(".duckyscript").val());
-
- if (duckOutput !== false)
- {
- $(".arduino").val(duckOutput);
- if (isFileSaverSupported)
- enableDl(500); // Enable download button
- }
- else {
- $(".arduino").val('An error occured, the compiler returned undefined content !');
- disableDl(500); // Disable download button
+ /* Compile button enable/disable */
+ $(".input > textarea").keyup(function() {
+ if($(this).val() !== "") {
+ $(".process-but button").prop("disabled", false);
+ $(".process-but select").prop("disabled", false);
+ } else {
+ $(".process-but button").prop("disabled", true);
+ $(".process-but select").prop("disabled", true);
}
});
- // Generate locale list
- var LocaleKeyboardjs = new LocaleKeyboard();
-
- // Download popup
- $(".dl-but").click(function() {
- if ($(".dl-but").hasClass("hoverable")) {
- $("#dl-popup").fadeIn(400);
-
- // Fill filename area
- $("#dl-filename").val("Dckuino.js-" + makeId(4));
-
- // Clear locale list
- $('#locale-select').find('option').remove();
-
- // Fill locale list
- $(LocaleKeyboardjs.listLocales()).each(function() {
- $("#locale-select").append($("");
});
- // Download button
- $("#start-dl").click(function() {
- // Check if all is ready
- if ($("#dl-filename").val() === "") {
- alert("You must enter a filename");
- return;
- }
+ /* List modules */
+ Duck.listModules().forEach(function (moduleName) {
+ $(".process-but select").append("");
+ });
+
+ /* Download button */
+ $(".dl-but button").click(function() {
+ var compilerOut = $(".export > textarea").val();
- // Create a zip and download
- var sketchName = $("#dl-filename").val();
+ var sketchName = "Sketch";
var zipHandler = new JSZip();
// Add the payload as .ino
- zipHandler.file(sketchName + "/" + sketchName + ".ino", $(".arduino").val());
+ zipHandler.file(sketchName + "/" + sketchName + ".ino", compilerOut);
+
// Add readme
zipHandler.file("readme", $.ajax({
url: 'readme.default',
@@ -90,13 +86,13 @@ jQuery(function() { // Wait for jQuery
}));
// Add custom version of Keyboard lib if needed
- if ($("#locale-select").find(":selected").text() !== "en_US") {
+ if ($(".export-but select").find(":selected").text() !== "en_US") {
// Set the locale
- LocaleKeyboardjs.setLocale($("#locale-select").find(":selected").text());
+ LocKey.setLocale($(".dl-but select").find(":selected").text());
// Append all to the zip
- zipHandler.file(sketchName + "/Keyboard.cpp", LocaleKeyboardjs.getSource());
- zipHandler.file(sketchName + "/Keyboard.h", LocaleKeyboardjs.getHeader());
+ zipHandler.file(sketchName + "/Keyboard.cpp", LocKey.getSource());
+ zipHandler.file(sketchName + "/Keyboard.h", LocKey.getHeader());
}
// Download
@@ -106,36 +102,17 @@ jQuery(function() { // Wait for jQuery
}
);
});
-});
-
-function init()
-{
- // Init page
-
- // Disable download button by default
- disableDl(500);
-
- // Clear console
- $(".console").val("");
-}
-function disableDl(time) {
- $(".dl-but").addClass("disabled").removeClass("hoverable");
- $(".dl-but span i.fa-ban").fadeTo(time, 1);
-}
+ /* Copy to clipboard button */
+ $(".copy-but").click(function() {
+ var copyTextarea = $(".export > textarea");
+ copyTextarea.select();
-function enableDl(time) {
- $(".dl-but").removeClass("disabled").addClass("hoverable");
- $(".dl-but span i.fa-ban").fadeTo(time, 0);
-}
+ try {
+ document.execCommand('copy');
-function makeId(idLenght)
-{
- var text = "";
- var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-
- for( var i=0; i < idLenght; i++ )
- text += possible.charAt(Math.floor(Math.random() * possible.length));
-
- return text;
-}
+ $(".copy-but").text("Copied !");
+ $(".copy-but").prop("disabled", true);
+ } catch (e) {/* Error */}
+ });
+});
diff --git a/index.html b/index.html
index b8358f4..5e58835 100644
--- a/index.html
+++ b/index.html
@@ -3,14 +3,6 @@
-
-
-
-
-
-
-
-
@@ -19,56 +11,68 @@
- Dckuino.js
+ Duckuino
-
-