Add docker rename volume tool

This commit is contained in:
Illya Marchenko 2024-09-28 15:16:10 +03:00
parent ee930f96fc
commit f75809c12d
Signed by: stuzer05
GPG Key ID: A6ABAAA9268F9F4F
32 changed files with 703 additions and 627 deletions

@ -2,13 +2,13 @@
require("@rushstack/eslint-patch/modern-module-resolution"); require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = { module.exports = {
"root": true, root: true,
"extends": [ extends: [
"plugin:vue/vue3-essential", "plugin:vue/vue3-essential",
"eslint:recommended", "eslint:recommended",
"@vue/eslint-config-prettier" "@vue/eslint-config-prettier",
], ],
"env": { env: {
"vue/setup-compiler-macros": true "vue/setup-compiler-macros": true,
} },
} };

@ -62,6 +62,9 @@ export default {
'php_array_to_json': 'PHP array to Json', 'php_array_to_json': 'PHP array to Json',
'php_serialize': 'PHP serialize', 'php_serialize': 'PHP serialize',
}, },
'Docker': {
'docker_rename_volume': 'Rename volume',
},
'GO': { 'GO': {
'go_json_to_struct': 'JSON to Go struct', 'go_json_to_struct': 'JSON to Go struct',
// 'sql_tables_to_struct': 'SQL tables Go struct', // 'sql_tables_to_struct': 'SQL tables Go struct',

@ -149,6 +149,15 @@ const router = createRouter({
component: () => import('../views/GoSQLTablesToStruct.vue'), component: () => import('../views/GoSQLTablesToStruct.vue'),
}, },
/**
* Docker
*/
{
path: '/docker_rename_volume',
name: 'docker_rename_volume',
component: () => import('../views/DockerRenameVolume.vue'),
},
/** /**
* SQL manipulation * SQL manipulation
*/ */

@ -0,0 +1,58 @@
<template>
<h2 class="tool-title">Docker rename volume</h2>
<hr class="mt-5 mb-5">
<div class="input-group">
<label for="volume_name_old">Old volume name</label>
<input id="volume_name_old" v-model="toolData.volumeNameOld" v-on:keyup="result" type="text">
</div>
<div class="input-group">
<label for="volume_name_new">New volume name</label>
<input id="volume_name_new" v-model="toolData.volumeNameNew" v-on:keyup="result" type="text">
</div>
<hr class="mt-5 mb-5">
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
</div>
</template>
<script>
import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
},
data() {
return {
toolData: {
volumeNameOld: "",
volumeNameNew: ""
},
toolResult: ""
};
},
methods: {
result() {
if (!this.toolData.volumeNameOld.length) {
this.toolResult = "fill old volume name";
return;
}
if (!this.toolData.volumeNameNew.length) {
this.toolResult = "fill new volume name";
return;
}
this.toolResult = `docker run --rm -v ${this.toolData.volumeNameOld}:/from -v ${this.toolData.volumeNameNew}:/to busybox cp -av /from/. /to`;
}
}
};
</script>
<style lang="scss">
</style>

@ -5,9 +5,11 @@
<div class="input-group"> <div class="input-group">
<label>Dimensions</label> <label>Dimensions</label>
<div style="display: flex"> <div style="display: flex">
<input class="input" v-model="toolData.width" v-on:keyup="result" v-on:change="result" placeholder="500" type="number" style="width: 70px">px <input class="input" v-model="toolData.width" v-on:keyup="result" v-on:change="result" placeholder="500"
type="number" style="width: 70px">px
<span style="padding: 0 10px">x</span> <span style="padding: 0 10px">x</span>
<input class="input" v-model="toolData.height" v-on:keyup="result" v-on:change="result" placeholder="500" type="number" style="width: 70px">px <input class="input" v-model="toolData.height" v-on:keyup="result" v-on:change="result" placeholder="500"
type="number" style="width: 70px">px
</div> </div>
</div> </div>
@ -26,7 +28,8 @@
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<div :style="{'width': toolData.width, 'height': toolData.height}"> <div :style="{'width': toolData.width, 'height': toolData.height}">
<canvas ref="canvas" :width="toolData.width" :height="toolData.height" style="max-width: 50vw; max-height: 50vh;"></canvas> <canvas ref="canvas" :width="toolData.width" :height="toolData.height"
style="max-width: 50vw; max-height: 50vh;"></canvas>
</div> </div>
</div> </div>
</template> </template>
@ -38,10 +41,10 @@ export default {
toolData: { toolData: {
width: 500, width: 500,
height: 500, height: 500,
color_bg: '#000000', color_bg: "#000000",
color_text: '#ffffff', color_text: "#ffffff"
}, },
toolResult: '', toolResult: ""
}; };
}, },
mounted() { mounted() {
@ -49,7 +52,7 @@ export default {
}, },
methods: { methods: {
result() { result() {
const ctx = this.$refs.canvas.getContext('2d'); const ctx = this.$refs.canvas.getContext("2d");
// Set background color // Set background color
ctx.fillStyle = this.toolData.color_bg; ctx.fillStyle = this.toolData.color_bg;
@ -57,7 +60,7 @@ export default {
// Set text color and font // Set text color and font
ctx.fillStyle = this.toolData.color_text; ctx.fillStyle = this.toolData.color_text;
ctx.font = 'bold 30px Arial'; ctx.font = "bold 30px Arial";
// Draw text on the canvas // Draw text on the canvas
const text = `${this.toolData.width}x${this.toolData.height}`; const text = `${this.toolData.width}x${this.toolData.height}`;
@ -65,9 +68,9 @@ export default {
const x = (this.toolData.width - textWidth) / 2; const x = (this.toolData.width - textWidth) / 2;
const y = this.toolData.height / 2 + 10; const y = this.toolData.height / 2 + 10;
ctx.fillText(text, x, y); ctx.fillText(text, x, y);
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -16,7 +16,7 @@
</template> </template>
<script> <script>
import cronstrue from 'cronstrue'; import cronstrue from "cronstrue";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -26,15 +26,15 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '* * * * *', data: "* * * * *"
}, },
toolResult: '', toolResult: ""
}; };
}, },
mounted() { mounted() {
this.toolResult = cronstrue.toString(this.toolData.data, { this.toolResult = cronstrue.toString(this.toolData.data, {
use24HourTimeFormat: true, use24HourTimeFormat: true,
verbose: true, verbose: true
}); });
}, },
methods: { methods: {
@ -42,14 +42,14 @@ export default {
try { try {
this.toolResult = cronstrue.toString(this.toolData.data, { this.toolResult = cronstrue.toString(this.toolData.data, {
use24HourTimeFormat: true, use24HourTimeFormat: true,
verbose: true, verbose: true
}); });
} catch (e) { } catch (e) {
this.toolResult = 'invalid syntax'; this.toolResult = "invalid syntax";
} }
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -15,7 +15,8 @@
<label>Strip mime/type</label> <label>Strip mime/type</label>
<div> <div>
<input id="strip_mime" name="strip_mime" v-model="toolData.stripMime" v-on:change="encode" type="checkbox"> <label for="strip_mime">strip mime</label> <input id="strip_mime" name="strip_mime" v-model="toolData.stripMime" v-on:change="encode" type="checkbox"> <label
for="strip_mime">strip mime</label>
</div> </div>
</div> </div>
@ -23,8 +24,10 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="base64_mode_encode" value="encode" name="base64_mode" v-model="toolData.base64Mode" type="radio"> <label for="base64_mode_encode">file -> base64</label><br> <input id="base64_mode_encode" value="encode" name="base64_mode" v-model="toolData.base64Mode" type="radio">
<input id="base64_mode_decode" value="decode" name="base64_mode" v-model="toolData.base64Mode" type="radio"> <label for="base64_mode_decode">base64 -> file</label> <label for="base64_mode_encode">file -> base64</label><br>
<input id="base64_mode_decode" value="decode" name="base64_mode" v-model="toolData.base64Mode" type="radio">
<label for="base64_mode_decode">base64 -> file</label>
</div> </div>
</div> </div>
@ -50,11 +53,11 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
base64Mode: 'encode', base64Mode: "encode",
stripMime: true, stripMime: true
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
@ -64,7 +67,7 @@ export default {
reader.onload = () => { reader.onload = () => {
if (this.toolData.stripMime) { if (this.toolData.stripMime) {
this.toolResult = reader.result.split(',')[1]; this.toolResult = reader.result.split(",")[1];
} else { } else {
this.toolResult = reader.result; this.toolResult = reader.result;
} }
@ -75,7 +78,7 @@ export default {
} }
}, },
decode() { decode() {
const byteCharacters = atob(this.toolData.data.split(',')[1] ?? this.toolData.data); const byteCharacters = atob(this.toolData.data.split(",")[1] ?? this.toolData.data);
const byteNumbers = new Array(byteCharacters.length); const byteNumbers = new Array(byteCharacters.length);
// create file // create file
@ -84,16 +87,16 @@ export default {
} }
const byteArray = new Uint8Array(byteNumbers); const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: 'application/octet-stream' }); const blob = new Blob([byteArray], { type: "application/octet-stream" });
// download // download
const link = document.createElement('a'); const link = document.createElement("a");
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
link.download = 'file'; link.download = "file";
link.click(); link.click();
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -11,8 +11,10 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="keyboard_mode_en_ru" value="en-ru" name="keyboard_mode" v-model="toolData.keyboardMode" v-on:change="result" type="radio"> <label for="keyboard_mode_en_ru">en -> ru</label><br> <input id="keyboard_mode_en_ru" value="en-ru" name="keyboard_mode" v-model="toolData.keyboardMode"
<input id="keyboard_mode_ru_en" value="ru-en" name="keyboard_mode" v-model="toolData.keyboardMode" v-on:change="result" type="radio"> <label for="keyboard_mode_ru_en">ru -> en</label> v-on:change="result" type="radio"> <label for="keyboard_mode_en_ru">en -> ru</label><br>
<input id="keyboard_mode_ru_en" value="ru-en" name="keyboard_mode" v-model="toolData.keyboardMode"
v-on:change="result" type="radio"> <label for="keyboard_mode_ru_en">ru -> en</label>
</div> </div>
</div> </div>
@ -35,22 +37,22 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
keyboardMode: 'en-ru', keyboardMode: "en-ru"
}, },
dictionary: { dictionary: {
'en-ru': '`~!@#$%^&qwertyuiop[]asdfghjkl;\'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?', "en-ru": "`~!@#$%^&qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?",
'ru-en': 'ёЁ!"№;%:?йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,', "ru-en": "ёЁ!\"№;%:?йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
let data = unproxy(this.toolData.data).split(''); let data = unproxy(this.toolData.data).split("");
const dict = this.dictionary[this.toolData.keyboardMode]; const dict = this.dictionary[this.toolData.keyboardMode];
const dictOpposite = this.dictionary[this.toolData.keyboardMode === 'en-ru' ? 'ru-en' : 'en-ru']; const dictOpposite = this.dictionary[this.toolData.keyboardMode === "en-ru" ? "ru-en" : "en-ru"];
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const dictPos = dict.indexOf(data[i]); const dictPos = dict.indexOf(data[i]);
@ -59,10 +61,10 @@ export default {
data[i] = unproxy(dictOpposite[dictPos]); data[i] = unproxy(dictOpposite[dictPos]);
} }
this.toolResult = data.join(''); this.toolResult = data.join("");
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -9,10 +9,12 @@
<div class="input-group"> <div class="input-group">
<div> <div>
<input id="flatten" name="flatten" v-model="toolData.flatten" v-on:change="result" type="checkbox"> <label for="flatten">inline type definitions</label> <input id="flatten" name="flatten" v-model="toolData.flatten" v-on:change="result" type="checkbox"> <label
for="flatten">inline type definitions</label>
</div> </div>
<div> <div>
<input id="omitempty" name="omitempty" v-model="toolData.omitempty" v-on:change="result" type="checkbox"> <label for="omitempty">omitempty</label> <input id="omitempty" name="omitempty" v-model="toolData.omitempty" v-on:change="result" type="checkbox"> <label
for="omitempty">omitempty</label>
</div> </div>
</div> </div>
@ -40,13 +42,10 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
let innerTabs = 0; let innerTabs = 0;
let parent = ""; let parent = "";
try try {
{
data = JSON.parse(json.replace(/(:\s*\[?\s*-?\d*)\.0/g, "$1.1")); // hack that forces floats to stay as floats data = JSON.parse(json.replace(/(:\s*\[?\s*-?\d*)\.0/g, "$1.1")); // hack that forces floats to stay as floats
scope = data; scope = data;
} } catch (e) {
catch (e)
{
return { return {
go: "", go: "",
error: e.message error: e.message
@ -65,22 +64,17 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
}; };
function parseScope(scope, depth = 0) function parseScope(scope, depth = 0) {
{ if (typeof scope === "object" && scope !== null) {
if (typeof scope === "object" && scope !== null) if (Array.isArray(scope)) {
{
if (Array.isArray(scope))
{
let sliceType; let sliceType;
const scopeLength = scope.length; const scopeLength = scope.length;
for (let i = 0; i < scopeLength; i++) for (let i = 0; i < scopeLength; i++) {
{
const thisType = goType(scope[i]); const thisType = goType(scope[i]);
if (!sliceType) if (!sliceType)
sliceType = thisType; sliceType = thisType;
else if (sliceType != thisType) else if (sliceType != thisType) {
{
sliceType = mostSpecificPossibleGoType(thisType, sliceType); sliceType = mostSpecificPossibleGoType(thisType, sliceType);
if (sliceType == "any") if (sliceType == "any")
break; break;
@ -94,24 +88,21 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
if (flatten && depth >= 2) if (flatten && depth >= 2)
appender(slice); appender(slice);
else else
append(slice) append(slice);
if (sliceType == "struct") { if (sliceType == "struct") {
const allFields = {}; const allFields = {};
// for each field counts how many times appears // for each field counts how many times appears
for (let i = 0; i < scopeLength; i++) for (let i = 0; i < scopeLength; i++) {
{ const keys = Object.keys(scope[i]);
const keys = Object.keys(scope[i]) for (let k in keys) {
for (let k in keys)
{
let keyname = keys[k]; let keyname = keys[k];
if (!(keyname in allFields)) { if (!(keyname in allFields)) {
allFields[keyname] = { allFields[keyname] = {
value: scope[i][keyname], value: scope[i][keyname],
count: 0 count: 0
} };
} } else {
else {
const existingValue = allFields[keyname].value; const existingValue = allFields[keyname].value;
const currentValue = scope[i][keyname]; const currentValue = scope[i][keyname];
@ -119,7 +110,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
const comparisonResult = compareObjectKeys( const comparisonResult = compareObjectKeys(
Object.keys(currentValue), Object.keys(currentValue),
Object.keys(existingValue) Object.keys(existingValue)
) );
if (!comparisonResult) { if (!comparisonResult) {
keyname = `${keyname}_${uuidv4()}`; keyname = `${keyname}_${uuidv4()}`;
allFields[keyname] = { allFields[keyname] = {
@ -136,63 +127,53 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
// create a common struct with all fields found in the current array // create a common struct with all fields found in the current array
// omitempty dict indicates if a field is optional // omitempty dict indicates if a field is optional
const keys = Object.keys(allFields), struct = {}, omitempty = {}; const keys = Object.keys(allFields), struct = {}, omitempty = {};
for (let k in keys) for (let k in keys) {
{
const keyname = keys[k], elem = allFields[keyname]; const keyname = keys[k], elem = allFields[keyname];
struct[keyname] = elem.value; struct[keyname] = elem.value;
omitempty[keyname] = elem.count != scopeLength; omitempty[keyname] = elem.count != scopeLength;
} }
parseStruct(depth + 1, innerTabs, struct, omitempty); // finally parse the struct !! parseStruct(depth + 1, innerTabs, struct, omitempty); // finally parse the struct !!
} } else if (sliceType == "slice") {
else if (sliceType == "slice") { parseScope(scope[0], depth);
parseScope(scope[0], depth) } else {
}
else {
if (flatten && depth >= 2) { if (flatten && depth >= 2) {
appender(sliceType || "any"); appender(sliceType || "any");
} else { } else {
append(sliceType || "any"); append(sliceType || "any");
} }
} }
} } else {
else
{
if (flatten) { if (flatten) {
if (depth >= 2) { if (depth >= 2) {
appender(parent) appender(parent);
} } else {
else { append(parent);
append(parent)
} }
} }
parseStruct(depth + 1, innerTabs, scope); parseStruct(depth + 1, innerTabs, scope);
} }
} } else {
else {
if (flatten && depth >= 2) { if (flatten && depth >= 2) {
appender(goType(scope)); appender(goType(scope));
} } else {
else {
append(goType(scope)); append(goType(scope));
} }
} }
} }
function parseStruct(depth, innerTabs, scope, omitempty) function parseStruct(depth, innerTabs, scope, omitempty) {
{
if (flatten) { if (flatten) {
stack.push( stack.push(
depth >= 2 depth >= 2
? "\n" ? "\n"
: "" : ""
) );
} }
const seenTypeNames = []; const seenTypeNames = [];
if (flatten && depth >= 2) if (flatten && depth >= 2) {
{
const parentType = `type ${parent}`; const parentType = `type ${parent}`;
const scopeKeys = formatScopeKeys(Object.keys(scope)); const scopeKeys = formatScopeKeys(Object.keys(scope));
@ -201,57 +182,50 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
// three or more duplicate keys with different values // three or more duplicate keys with different values
if (parent in seen && compareObjectKeys(scopeKeys, seen[parent])) { if (parent in seen && compareObjectKeys(scopeKeys, seen[parent])) {
stack.pop(); stack.pop();
return return;
} }
seen[parent] = scopeKeys; seen[parent] = scopeKeys;
appender(`${parentType} struct {\n`); appender(`${parentType} struct {\n`);
++innerTabs; ++innerTabs;
const keys = Object.keys(scope); const keys = Object.keys(scope);
for (let i in keys) for (let i in keys) {
{
const keyname = getOriginalName(keys[i]); const keyname = getOriginalName(keys[i]);
indenter(innerTabs) indenter(innerTabs);
const typename = uniqueTypeName(format(keyname), seenTypeNames) const typename = uniqueTypeName(format(keyname), seenTypeNames);
seenTypeNames.push(typename) seenTypeNames.push(typename);
appender(typename + " "); appender(typename + " ");
parent = typename parent = typename;
parseScope(scope[keys[i]], depth); parseScope(scope[keys[i]], depth);
appender(' `json:"'+keyname); appender(" `json:\"" + keyname);
if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) {
{ appender(",omitempty");
appender(',omitempty');
} }
appender('"`\n'); appender("\"`\n");
} }
indenter(--innerTabs); indenter(--innerTabs);
appender("}"); appender("}");
} } else {
else
{
append("struct {\n"); append("struct {\n");
++tabs; ++tabs;
const keys = Object.keys(scope); const keys = Object.keys(scope);
for (let i in keys) for (let i in keys) {
{
const keyname = getOriginalName(keys[i]); const keyname = getOriginalName(keys[i]);
indent(tabs); indent(tabs);
const typename = uniqueTypeName(format(keyname), seenTypeNames) const typename = uniqueTypeName(format(keyname), seenTypeNames);
seenTypeNames.push(typename) seenTypeNames.push(typename);
append(typename + " "); append(typename + " ");
parent = typename parent = typename;
parseScope(scope[keys[i]], depth); parseScope(scope[keys[i]], depth);
append(' `json:"'+keyname); append(" `json:\"" + keyname);
if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) {
{ append(",omitempty");
append(',omitempty');
} }
if (example && scope[keys[i]] !== "" && typeof scope[keys[i]] !== "object") if (example && scope[keys[i]] !== "" && typeof scope[keys[i]] !== "object") {
{ append("\" example:\"" + scope[keys[i]]);
append('" example:"'+scope[keys[i]])
} }
append('"`\n'); append("\"`\n");
} }
indent(--tabs); indent(--tabs);
append("}"); append("}");
@ -260,25 +234,21 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
accumulator += stack.pop(); accumulator += stack.pop();
} }
function indent(tabs) function indent(tabs) {
{
for (let i = 0; i < tabs; i++) for (let i = 0; i < tabs; i++)
go += '\t'; go += "\t";
} }
function append(str) function append(str) {
{
go += str; go += str;
} }
function indenter(tabs) function indenter(tabs) {
{
for (let i = 0; i < tabs; i++) for (let i = 0; i < tabs; i++)
stack[stack.length - 1] += '\t'; stack[stack.length - 1] += "\t";
} }
function appender(str) function appender(str) {
{
stack[stack.length - 1] += str; stack[stack.length - 1] += str;
} }
@ -301,18 +271,17 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
// Sanitizes and formats a string to make an appropriate identifier in Go // Sanitizes and formats a string to make an appropriate identifier in Go
function format(str) function format(str) {
{
str = formatNumber(str); str = formatNumber(str);
let sanitized = toProperCase(str).replace(/[^a-z0-9]/ig, "") let sanitized = toProperCase(str).replace(/[^a-z0-9]/ig, "");
if (!sanitized) { if (!sanitized) {
return "NAMING_FAILED"; return "NAMING_FAILED";
} }
// After sanitizing the remaining characters can start with a number. // After sanitizing the remaining characters can start with a number.
// Run the sanitized string again trough formatNumber to make sure the identifier is Num[0-9] or Zero_... instead of 1. // Run the sanitized string again trough formatNumber to make sure the identifier is Num[0-9] or Zero_... instead of 1.
return formatNumber(sanitized) return formatNumber(sanitized);
} }
// Adds a prefix to a number to make an appropriate identifier in Go // Adds a prefix to a number to make an appropriate identifier in Go
@ -321,11 +290,12 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
return ""; return "";
else if (str.match(/^\d+$/)) else if (str.match(/^\d+$/))
str = "Num" + str; str = "Num" + str;
else if (str.charAt(0).match(/\d/)) else if (str.charAt(0).match(/\d/)) {
{ const numbers = {
const numbers = {'0': "Zero_", '1': "One_", '2': "Two_", '3': "Three_", "0": "Zero_", "1": "One_", "2": "Two_", "3": "Three_",
'4': "Four_", '5': "Five_", '6': "Six_", '7': "Seven_", "4": "Four_", "5": "Five_", "6": "Six_", "7": "Seven_",
'8': "Eight_", '9': "Nine_"}; "8": "Eight_", "9": "Nine_"
};
str = numbers[str.charAt(0)] + str.substr(1); str = numbers[str.charAt(0)] + str.substr(1);
} }
@ -333,27 +303,23 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
// Determines the most appropriate Go type // Determines the most appropriate Go type
function goType(val) function goType(val) {
{
if (val === null) if (val === null)
return "any"; return "any";
switch (typeof val) switch (typeof val) {
{
case "string": case "string":
if (/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(\+\d\d:\d\d|Z)$/.test(val)) if (/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(\+\d\d:\d\d|Z)$/.test(val))
return "time.Time"; return "time.Time";
else else
return "string"; return "string";
case "number": case "number":
if (val % 1 === 0) if (val % 1 === 0) {
{
if (val > -2147483648 && val < 2147483647) if (val > -2147483648 && val < 2147483647)
return "int"; return "int";
else else
return "int64"; return "int64";
} } else
else
return "float64"; return "float64";
case "boolean": case "boolean":
return "bool"; return "bool";
@ -367,8 +333,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
// Given two types, returns the more specific of the two // Given two types, returns the more specific of the two
function mostSpecificPossibleGoType(typ1, typ2) function mostSpecificPossibleGoType(typ1, typ2) {
{
if (typ1.substr(0, 5) == "float" if (typ1.substr(0, 5) == "float"
&& typ2.substr(0, 3) == "int") && typ2.substr(0, 3) == "int")
return typ1; return typ1;
@ -380,8 +345,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
// Proper cases a string according to Go conventions // Proper cases a string according to Go conventions
function toProperCase(str) function toProperCase(str) {
{
// ensure that the SCREAMING_SNAKE_CASE is converted to snake_case // ensure that the SCREAMING_SNAKE_CASE is converted to snake_case
if (str.match(/^[_A-Z0-9]+$/)) { if (str.match(/^[_A-Z0-9]+$/)) {
str = str.toLowerCase(); str = str.toLowerCase();
@ -395,14 +359,12 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
"URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS" "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS"
]; ];
return str.replace(/(^|[^a-zA-Z])([a-z]+)/g, function(unused, sep, frag) return str.replace(/(^|[^a-zA-Z])([a-z]+)/g, function(unused, sep, frag) {
{
if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0) if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0)
return sep + frag.toUpperCase(); return sep + frag.toUpperCase();
else else
return sep + frag[0].toUpperCase() + frag.substr(1).toLowerCase(); return sep + frag[0].toUpperCase() + frag.substr(1).toLowerCase();
}).replace(/([A-Z])([a-z]+)/g, function(unused, sep, frag) }).replace(/([A-Z])([a-z]+)/g, function(unused, sep, frag) {
{
if (commonInitialisms.indexOf(sep + frag.toUpperCase()) >= 0) if (commonInitialisms.indexOf(sep + frag.toUpperCase()) >= 0)
return (sep + frag).toUpperCase(); return (sep + frag).toUpperCase();
else else
@ -411,23 +373,23 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
function uuidv4() { function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
return v.toString(16); return v.toString(16);
}); });
} }
function getOriginalName(unique) { function getOriginalName(unique) {
const reLiteralUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i const reLiteralUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const uuidLength = 36; const uuidLength = 36;
if (unique.length >= uuidLength) { if (unique.length >= uuidLength) {
const tail = unique.substr(-uuidLength); const tail = unique.substr(-uuidLength);
if (reLiteralUUID.test(tail)) { if (reLiteralUUID.test(tail)) {
return unique.slice(0, -1 * (uuidLength + 1)) return unique.slice(0, -1 * (uuidLength + 1));
} }
} }
return unique return unique;
} }
function compareObjects(objectA, objectB) { function compareObjects(objectA, objectB) {
@ -459,7 +421,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
for (let i in keys) { for (let i in keys) {
keys[i] = format(keys[i]); keys[i] = format(keys[i]);
} }
return keys return keys;
} }
} }
@ -470,30 +432,30 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
flatten: false, flatten: false,
omitempty: false, omitempty: false
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
if (!this.toolData.data.length) { if (!this.toolData.data.length) {
this.toolResult = ''; this.toolResult = "";
return; return;
} }
const json = jsonToGo(this.toolData.data, "", this.toolData.flatten, false, this.toolData.omitempty); const json = jsonToGo(this.toolData.data, "", this.toolData.flatten, false, this.toolData.omitempty);
if (json.error?.length) { if (json.error?.length) {
this.toolResult = 'invalid json'; this.toolResult = "invalid json";
return; return;
} }
this.toolResult = json.go; this.toolResult = json.go;
} }
},
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -4,21 +4,24 @@
<div class="input-group"> <div class="input-group">
<label for="result">MariaDB</label> <label for="result">MariaDB</label>
<MonacoEditor name="dialects_mariadb" language="sql" :value="toolData.dialects.mariadb" readonly="true" style="height: 500px"></MonacoEditor> <MonacoEditor name="dialects_mariadb" language="sql" :value="toolData.dialects.mariadb" readonly="true"
style="height: 500px"></MonacoEditor>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label for="result">PostgreSQL</label> <label for="result">PostgreSQL</label>
<MonacoEditor name="dialects_postgresql" language="sql" :value="toolData.dialects.postgresql" readonly="true" style="height: 500px"></MonacoEditor> <MonacoEditor name="dialects_postgresql" language="sql" :value="toolData.dialects.postgresql" readonly="true"
style="height: 500px"></MonacoEditor>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label for="result">OracleSQL</label> <label for="result">OracleSQL</label>
<MonacoEditor name="dialects_oraclesql" language="sql" :value="toolData.dialects.oraclesql" readonly="true" style="height: 500px"></MonacoEditor> <MonacoEditor name="dialects_oraclesql" language="sql" :value="toolData.dialects.oraclesql" readonly="true"
style="height: 500px"></MonacoEditor>
</div> </div>
</template> </template>
@ -33,11 +36,12 @@ export default {
return { return {
toolData: { toolData: {
dialects: { dialects: {
mariadb: `WITH models AS ( mariadb: `WITH models AS (WITH data AS (SELECT REPLACE(CONCAT(UPPER(SUBSTRING(table_name, 1, 1)),
WITH data AS ( LOWER(SUBSTRING(table_name, 2))), '_',
SELECT '') AS table_name,
REPLACE(CONCAT(UPPER(SUBSTRING(table_name, 1, 1)), LOWER(SUBSTRING(table_name, 2))), '_', '') AS table_name, REPLACE(CONCAT(UPPER(SUBSTRING(column_name, 1, 1)),
REPLACE(CONCAT(UPPER(SUBSTRING(column_name, 1, 1)), LOWER(SUBSTRING(column_name, 2))), '_', '') AS column_name, LOWER(SUBSTRING(column_name, 2))), '_',
'') AS column_name,
CASE data_type CASE data_type
WHEN 'timestamp' THEN 'time.Time' WHEN 'timestamp' THEN 'time.Time'
WHEN 'tinyint(1)' THEN 'bool' WHEN 'tinyint(1)' THEN 'bool'
@ -59,19 +63,15 @@ export default {
CONCAT('\`json:"', column_name, '"\`') AS annotation CONCAT('\`json:"', column_name, '"\`') AS annotation
FROM information_schema.columns FROM information_schema.columns
WHERE table_schema IN ('work-euroline.local') WHERE table_schema IN ('work-euroline.local')
ORDER BY table_schema, table_name, ordinal_position ORDER BY table_schema, table_name, ordinal_position)
) SELECT table_name,
SELECT table_name, GROUP_CONCAT(CONCAT('\\t', column_name, '\\t', type_info, '\\t', annotation) SEPARATOR '\\n') AS fields GROUP_CONCAT(CONCAT('\\t', column_name, '\\t', type_info, '\\t', annotation) SEPARATOR '\\n') AS fields
FROM data FROM data
GROUP BY table_name GROUP BY table_name)
)
SELECT CONCAT('type ', table_name, ' struct {\\n', fields, '\\n}') AS models SELECT CONCAT('type ', table_name, ' struct {\\n', fields, '\\n}') AS models
FROM models FROM models
ORDER BY table_name`, ORDER BY table_name`,
postgresql: `WITH models AS ( postgresql: `WITH models AS (WITH data AS (SELECT replace(initcap(table_name::text), '_', '') table_name,
WITH data AS (
SELECT
replace(initcap(table_name::text), '_', '') table_name,
replace(initcap(column_name::text), '_', '') column_name, replace(initcap(column_name::text), '_', '') column_name,
CASE data_type CASE data_type
WHEN 'timestamp without time zone' THEN 'time.Time' WHEN 'timestamp without time zone' THEN 'time.Time'
@ -88,25 +88,20 @@ ORDER BY table_name`,
'\`json:"' || column_name || '"\`' AS annotation '\`json:"' || column_name || '"\`' AS annotation
FROM information_schema.columns FROM information_schema.columns
WHERE table_schema IN ('public') WHERE table_schema IN ('public')
ORDER BY table_schema, table_name, ordinal_position ORDER BY table_schema, table_name, ordinal_position)
)
SELECT table_name, STRING_AGG(E'\\t' || column_name || E'\\t' || type_info || E'\\t' || annotation, E '\\n') fields SELECT table_name, STRING_AGG(E'\\t' || column_name || E'\\t' || type_info || E'\\t' || annotation, E '\\n') fields
FROM data FROM data
GROUP BY table_name GROUP BY table_name)
)
SELECT 'type ' || table_name || E ' struct {\\n' || fields || E'\\n}' models SELECT 'type ' || table_name || E ' struct {\\n' || fields || E'\\n}' models
FROM models ORDER BY table_name`, FROM models
oraclesql: `SELECT ORDER BY table_name`,
'type ' || table_name || ' struct {' || CHR(10) || fields || CHR(10) || '}' AS models oraclesql: `SELECT 'type ' || table_name || ' struct {' || CHR(10) || fields || CHR(10) || '}' AS models
FROM FROM (SELECT table_name,
( REPLACE(RTRIM(XMLAGG(XMLELEMENT(E, CHR(9) || column_name || CHR(9) || type_info ||
SELECT CHR(9) || annotation ||
table_name, CHR(10))).EXTRACT('//text()').GETCLOBVAL(),
REPLACE(RTRIM(XMLAGG(XMLELEMENT(E, CHR(9) || column_name || CHR(9) || type_info || CHR(9) || annotation || CHR(10))).EXTRACT('//text()').GETCLOBVAL(), CHR(10)), '&quot;', '"') AS fields CHR(10)), '&quot;', '"') AS fields
FROM FROM (SELECT REPLACE(INITCAP(table_name), '_', '') AS table_name,
(
SELECT
REPLACE(INITCAP(table_name), '_', '') AS table_name,
REPLACE(INITCAP(column_name), '_', '') AS column_name, REPLACE(INITCAP(column_name), '_', '') AS column_name,
CASE data_type CASE data_type
WHEN 'TIMESTAMP' THEN 'time.Time' WHEN 'TIMESTAMP' THEN 'time.Time'
@ -138,18 +133,16 @@ FROM
END AS type_info, END AS type_info,
'\`json:"' || column_name || '" db:"' || column_name || '"\`' AS annotation '\`json:"' || column_name || '" db:"' || column_name || '"\`' AS annotation
FROM all_tab_columns FROM all_tab_columns
WHERE owner = 'DELOPRO' WHERE owner = 'DELOPRO')
)
--WHERE type_info = 'UNKNOWN' --WHERE type_info = 'UNKNOWN'
GROUP BY table_name GROUP BY table_name)
)
--WHERE table_name = 'V8EventVw' --WHERE table_name = 'V8EventVw'
ORDER BY table_name`, ORDER BY table_name`
}
} }
},
}; };
},
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -3,7 +3,9 @@
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label>Team <button @click="addTeamGroup"></button></label> <label>Team
<button @click="addTeamGroup"></button>
</label>
<div class="humans-group" v-for="(group, groupIndex) in toolData.team" :key="groupIndex"> <div class="humans-group" v-for="(group, groupIndex) in toolData.team" :key="groupIndex">
<div v-for="(field, fieldIndex) in group" :key="fieldIndex"> <div v-for="(field, fieldIndex) in group" :key="fieldIndex">
<input class="input" v-model="field.key" v-on:keyup="result" placeholder="Key" type="text"> <input class="input" v-model="field.key" v-on:keyup="result" placeholder="Key" type="text">
@ -23,7 +25,9 @@
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label>Thanks <button @click="addThanksGroup"></button></label> <label>Thanks
<button @click="addThanksGroup"></button>
</label>
<div class="humans-group" v-for="(group, groupIndex) in toolData.thanks" :key="groupIndex"> <div class="humans-group" v-for="(group, groupIndex) in toolData.thanks" :key="groupIndex">
<div v-for="(field, fieldIndex) in group" :key="fieldIndex"> <div v-for="(field, fieldIndex) in group" :key="fieldIndex">
<input class="input" v-model="field.key" v-on:keyup="result" placeholder="Key" type="text"> <input class="input" v-model="field.key" v-on:keyup="result" placeholder="Key" type="text">
@ -43,7 +47,9 @@
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label>Site info <button @click="addSite"></button></label> <label>Site info
<button @click="addSite"></button>
</label>
<div v-for="(info, fieldIndex) in toolData.site" :key="fieldIndex"> <div v-for="(info, fieldIndex) in toolData.site" :key="fieldIndex">
<input class="input" v-model="info.key" v-on:keyup="result" placeholder="Key" type="text"> <input class="input" v-model="info.key" v-on:keyup="result" placeholder="Key" type="text">
<input class="input" v-model="info.value" v-on:keyup="result" placeholder="Value" type="text"> <input class="input" v-model="info.value" v-on:keyup="result" placeholder="Value" type="text">
@ -56,7 +62,9 @@
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5">
<div class="input-group"> <div class="input-group">
<label>Import humans.txt <button @click="importHumans">Import</button></label> <label>Import humans.txt
<button @click="importHumans">Import</button>
</label>
<textarea v-model="toolData.importedHumansTxt" style="height: 250px"></textarea> <textarea v-model="toolData.importedHumansTxt" style="height: 250px"></textarea>
</div> </div>
@ -80,20 +88,20 @@ export default {
toolData: { toolData: {
team: [ team: [
[ [
{ key: '', value: '' } { key: "", value: "" }
] ]
], ],
thanks: [ thanks: [
[ [
{ key: '', value: '' } { key: "", value: "" }
] ]
], ],
site: [ site: [
{ key: '', value: '' } { key: "", value: "" }
], ],
importedHumansTxt: '' importedHumansTxt: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
mounted() { mounted() {
@ -105,16 +113,16 @@ export default {
* Team * Team
*/ */
addTeamGroup() { addTeamGroup() {
this.toolData.team.push([{ key: '', value: '' }]); this.toolData.team.push([{ key: "", value: "" }]);
}, },
addTeamField(groupIndex) { addTeamField(groupIndex) {
this.toolData.team[groupIndex].push({ key: '', value: '' }); this.toolData.team[groupIndex].push({ key: "", value: "" });
}, },
removeTeamField(groupIndex, fieldIndex) { removeTeamField(groupIndex, fieldIndex) {
this.toolData.team[groupIndex].splice(fieldIndex, 1); this.toolData.team[groupIndex].splice(fieldIndex, 1);
if (this.toolData.team[groupIndex].length == 0) { if (this.toolData.team[groupIndex].length == 0) {
this.removeTeamGroup(groupIndex) this.removeTeamGroup(groupIndex);
} }
this.result(); this.result();
@ -164,16 +172,16 @@ export default {
* Thank * Thank
*/ */
addThanksGroup() { addThanksGroup() {
this.toolData.thanks.push([{ key: '', value: '' }]); this.toolData.thanks.push([{ key: "", value: "" }]);
}, },
addThanksField(groupIndex) { addThanksField(groupIndex) {
this.toolData.thanks[groupIndex].push({ key: '', value: '' }); this.toolData.thanks[groupIndex].push({ key: "", value: "" });
}, },
removeThanksField(groupIndex, fieldIndex) { removeThanksField(groupIndex, fieldIndex) {
this.toolData.thanks[groupIndex].splice(fieldIndex, 1); this.toolData.thanks[groupIndex].splice(fieldIndex, 1);
if (this.toolData.thanks[groupIndex].length == 0) { if (this.toolData.thanks[groupIndex].length == 0) {
this.removeThanksGroup(groupIndex) this.removeThanksGroup(groupIndex);
} }
this.result(); this.result();
@ -222,7 +230,7 @@ export default {
* Site * Site
*/ */
addSite() { addSite() {
this.toolData.site.push({ label: '', value: '' }); this.toolData.site.push({ label: "", value: "" });
}, },
removeSiteField(fieldIndex) { removeSiteField(fieldIndex) {
this.toolData.site.splice(fieldIndex, 1); this.toolData.site.splice(fieldIndex, 1);
@ -252,7 +260,7 @@ export default {
* Import * Import
*/ */
importHumans() { importHumans() {
const lines = this.toolData.importedHumansTxt.split('\n'); const lines = this.toolData.importedHumansTxt.split("\n");
let currentSection = null; let currentSection = null;
this.toolData.team = []; this.toolData.team = [];
@ -262,29 +270,29 @@ export default {
let currentGroup = []; let currentGroup = [];
for (const line of lines) { for (const line of lines) {
if (line.toLowerCase().startsWith('/* TEAM */'.toLowerCase())) { if (line.toLowerCase().startsWith("/* TEAM */".toLowerCase())) {
currentSection = 'team'; currentSection = "team";
} else if (line.toLowerCase().startsWith('/* THANKS */'.toLowerCase())) { } else if (line.toLowerCase().startsWith("/* THANKS */".toLowerCase())) {
currentSection = 'thanks'; currentSection = "thanks";
} else if (line.toLowerCase().startsWith('/* SITE */'.toLowerCase())) { } else if (line.toLowerCase().startsWith("/* SITE */".toLowerCase())) {
currentSection = 'site'; currentSection = "site";
} else if (line.trim() !== '') { } else if (line.trim() !== "") {
if (currentSection === 'team') { if (currentSection === "team") {
const [key, value] = line.split(':'); const [key, value] = line.split(":");
currentGroup.push({ key: key.trim(), value: value.trim() }); currentGroup.push({ key: key.trim(), value: value.trim() });
} else if (currentSection === 'thanks') { } else if (currentSection === "thanks") {
const [key, value] = line.split(':'); const [key, value] = line.split(":");
currentGroup.push({ key: key.trim(), value: value.trim() }); currentGroup.push({ key: key.trim(), value: value.trim() });
} else if (currentSection === 'site') { } else if (currentSection === "site") {
const [key, value] = line.split(':'); const [key, value] = line.split(":");
this.toolData.site.push({ key: key.trim(), value: value.trim() }); this.toolData.site.push({ key: key.trim(), value: value.trim() });
} }
} else if (line.trim() === '' && currentSection === 'team') { } else if (line.trim() === "" && currentSection === "team") {
if (currentGroup.length > 0) { if (currentGroup.length > 0) {
this.toolData.team.push(currentGroup); this.toolData.team.push(currentGroup);
currentGroup = []; currentGroup = [];
} }
} else if (line.trim() === '' && currentSection === 'thanks') { } else if (line.trim() === "" && currentSection === "thanks") {
if (currentGroup.length > 0) { if (currentGroup.length > 0) {
this.toolData.thanks.push(currentGroup); this.toolData.thanks.push(currentGroup);
currentGroup = []; currentGroup = [];
@ -301,63 +309,63 @@ export default {
* Generate * Generate
*/ */
result() { result() {
let output = ''; let output = "";
if (this.toolData.team.length) { if (this.toolData.team.length) {
output += '/* TEAM */\n'; output += "/* TEAM */\n";
for (const group of this.toolData.team) { for (const group of this.toolData.team) {
let groupOutput = ''; let groupOutput = "";
for (const field of group) { for (const field of group) {
if (field.key.trim() !== '' && field.value.trim() !== '') { if (field.key.trim() !== "" && field.value.trim() !== "") {
groupOutput += `\t${field.key.trim()}: ${field.value.trim()}\n`; groupOutput += `\t${field.key.trim()}: ${field.value.trim()}\n`;
} }
} }
if (groupOutput !== '') { if (groupOutput !== "") {
output += groupOutput + '\n'; output += groupOutput + "\n";
} }
} }
} }
if (this.toolData.thanks.length) { if (this.toolData.thanks.length) {
output += '/* THANKS */\n'; output += "/* THANKS */\n";
for (const group of this.toolData.thanks) { for (const group of this.toolData.thanks) {
let groupOutput = ''; let groupOutput = "";
for (const field of group) { for (const field of group) {
if (field.key.trim() !== '' && field.value.trim() !== '') { if (field.key.trim() !== "" && field.value.trim() !== "") {
groupOutput += `\t${field.key.trim()}: ${field.value.trim()}\n`; groupOutput += `\t${field.key.trim()}: ${field.value.trim()}\n`;
} }
} }
if (groupOutput !== '') { if (groupOutput !== "") {
output += groupOutput + '\n'; output += groupOutput + "\n";
} }
} }
} }
if (this.toolData.site.length) { if (this.toolData.site.length) {
output += '/* SITE */\n'; output += "/* SITE */\n";
for (const info of this.toolData.site) { for (const info of this.toolData.site) {
if (info.key.trim() !== '' && info.value.trim() !== '') { if (info.key.trim() !== "" && info.value.trim() !== "") {
output += `\t${info.key.trim()}: ${info.value.trim()}\n`; output += `\t${info.key.trim()}: ${info.value.trim()}\n`;
} }
} }
} }
this.toolResult = output; this.toolResult = output;
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">
.humans-group { .humans-group {
padding: 10px 0; padding: 10px 0;
} }
.humans-group:nth-child(odd) { .humans-group:nth-child(odd) {
background-color: #f7f7f7; background-color: #f7f7f7;
} }
</style> </style>

@ -25,25 +25,25 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
if (!this.toolData.data.length) { if (!this.toolData.data.length) {
this.toolResult = ''; this.toolResult = "";
} else { } else {
try { try {
this.toolResult = JSON.stringify(JSON.parse(this.toolData.data), null, 4); this.toolResult = JSON.stringify(JSON.parse(this.toolData.data), null, 4);
} catch (e) { } catch (e) {
this.toolResult = 'invalid syntax'; this.toolResult = "invalid syntax";
} }
} }
} }
},
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -25,25 +25,25 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
minify() { minify() {
if (!this.toolData.data.length) { if (!this.toolData.data.length) {
this.toolResult = ''; this.toolResult = "";
} else { } else {
try { try {
this.toolResult = JSON.stringify(JSON.parse(this.toolData.data)); this.toolResult = JSON.stringify(JSON.parse(this.toolData.data));
} catch (e) { } catch (e) {
this.toolResult = 'invalid syntax'; this.toolResult = "invalid syntax";
} }
} }
} }
},
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -9,7 +9,8 @@
<div class="input-group"> <div class="input-group">
<div> <div>
<input id="minify_json" name="minify_json" v-model="toolData.minifyJson" v-on:change="result" type="checkbox"> <label for="minify_json">minify json</label> <input id="minify_json" name="minify_json" v-model="toolData.minifyJson" v-on:change="result" type="checkbox">
<label for="minify_json">minify json</label>
</div> </div>
</div> </div>
@ -22,8 +23,8 @@
</template> </template>
<script> <script>
import axios from 'axios' import axios from "axios";
import { config } from '../../config'; import { config } from "../../config";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -33,17 +34,17 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
minifyJson: '', minifyJson: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
axios.post(`${config.APP_URL}/api/php/php_array_to_json.php`, { axios.post(`${config.APP_URL}/api/php/php_array_to_json.php`, {
data: this.toolData.data, data: this.toolData.data,
minify_json: this.toolData.minifyJson ? true : false, minify_json: this.toolData.minifyJson ? true : false
}) })
.then((response) => { .then((response) => {
this.toolResult = response.data.data; this.toolResult = response.data.data;
@ -52,7 +53,7 @@ export default {
}); });
} }
} }
} };
</script> </script>
<style lang="scss"> <style lang="scss">

@ -11,8 +11,10 @@
<label for="data_delimiter">Mode</label> <label for="data_delimiter">Mode</label>
<div> <div>
<input id="mode_serialize" value="serialize" name="mode" v-model="toolData.mode" v-on:change="result" type="radio"> <label for="mode_serialize">serialize</label><br> <input id="mode_serialize" value="serialize" name="mode" v-model="toolData.mode" v-on:change="result"
<input id="mode_unserialize" value="unserialize" name="mode" v-model="toolData.mode" v-on:change="result" type="radio"> <label for="mode_unserialize">unserialize</label><br> type="radio"> <label for="mode_serialize">serialize</label><br>
<input id="mode_unserialize" value="unserialize" name="mode" v-model="toolData.mode" v-on:change="result"
type="radio"> <label for="mode_unserialize">unserialize</label><br>
</div> </div>
</div> </div>
@ -25,8 +27,8 @@
</template> </template>
<script> <script>
import axios from 'axios' import axios from "axios";
import { config } from '../../config'; import { config } from "../../config";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -36,17 +38,17 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
mode: 'serialize', mode: "serialize"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
axios.post(`${config.APP_URL}/api/php/php_serialize.php`, { axios.post(`${config.APP_URL}/api/php/php_serialize.php`, {
data: this.toolData.data, data: this.toolData.data,
mode: this.toolData.mode, mode: this.toolData.mode
}) })
.then((response) => { .then((response) => {
this.toolResult = response.data; this.toolResult = response.data;
@ -55,7 +57,7 @@ export default {
}); });
} }
} }
} };
</script> </script>
<style lang="scss"> <style lang="scss">

@ -21,7 +21,8 @@
<div class="input-group"> <div class="input-group">
<label for="height">White border:</label> <label for="height">White border:</label>
<input id="quietZone" v-model.number="toolData.options.quietZone" v-on:change="result" v-on:keyup="result" type="number"> <input id="quietZone" v-model.number="toolData.options.quietZone" v-on:change="result" v-on:keyup="result"
type="number">
</div> </div>
<div class="input-group"> <div class="input-group">
@ -49,14 +50,16 @@
<div class="input-group"> <div class="input-group">
<label for="backgroundImageUpload">Background Image Upload:</label> <label for="backgroundImageUpload">Background Image Upload:</label>
<div> <div>
<input type="file" id="backgroundImageUpload" ref="backgroundImageUpload" @change="handleBackgroundImageUpload" accept="image/*"> <input type="file" id="backgroundImageUpload" ref="backgroundImageUpload" @change="handleBackgroundImageUpload"
accept="image/*">
<button @click="removeBackgroundImage">🞩</button> <button @click="removeBackgroundImage">🞩</button>
</div> </div>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="backgroundImageAlpha">Background Image Alpha:</label> <label for="backgroundImageAlpha">Background Image Alpha:</label>
<input id="backgroundImageAlpha" v-model.number="toolData.options.backgroundImageAlpha" step="0.1" min="0" max="1" v-on:change="result" v-on:keyup="result" type="number"> <input id="backgroundImageAlpha" v-model.number="toolData.options.backgroundImageAlpha" step="0.1" min="0" max="1"
v-on:change="result" v-on:keyup="result" type="number">
</div> </div>
<!-- <!--
@ -89,7 +92,7 @@
</template> </template>
<script> <script>
import QRCode from 'easyqrcodejs'; import QRCode from "easyqrcodejs";
import { unproxy } from "../utils/unproxy"; import { unproxy } from "../utils/unproxy";
export default { export default {
@ -97,39 +100,39 @@ export default {
return { return {
toolData: { toolData: {
options: { options: {
text: '', text: "",
width: 256, width: 256,
height: 256, height: 256,
correctLevel: 'L', correctLevel: "L",
logo: '', logo: "",
quietZone: 10, quietZone: 10,
logoBackgroundTransparent: true, logoBackgroundTransparent: true,
backgroundImage: '', backgroundImage: "",
backgroundImageAlpha: 1, backgroundImageAlpha: 1,
autoColor: true, autoColor: true,
drawer: 'canvas', drawer: "canvas"
}, }
}, }
}; };
}, },
mounted() { mounted() {
this.toolData.options.text = ' '; this.toolData.options.text = " ";
this.result(); this.result();
this.toolData.options.text = ''; this.toolData.options.text = "";
}, },
methods: { methods: {
result() { result() {
// Clear previous QR code // Clear previous QR code
this.$refs.qrcodeContainer.innerHTML = ''; this.$refs.qrcodeContainer.innerHTML = "";
let options = unproxy(this.toolData.options); let options = unproxy(this.toolData.options);
// convert correction levels // convert correction levels
options.correctLevel = { options.correctLevel = {
'L': QRCode.CorrectLevel.L, "L": QRCode.CorrectLevel.L,
'M': QRCode.CorrectLevel.M, "M": QRCode.CorrectLevel.M,
'Q': QRCode.CorrectLevel.Q, "Q": QRCode.CorrectLevel.Q,
'H': QRCode.CorrectLevel.H, "H": QRCode.CorrectLevel.H
}[options.correctLevel]; }[options.correctLevel];
console.log(options.correctLevel); console.log(options.correctLevel);
@ -162,15 +165,15 @@ export default {
}, },
removeLogo() { removeLogo() {
this.toolData.options.logo = ''; this.toolData.options.logo = "";
this.result(); this.result();
}, },
removeBackgroundImage() { removeBackgroundImage() {
this.toolData.options.backgroundImage = ''; this.toolData.options.backgroundImage = "";
this.result(); this.result();
},
} }
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -16,7 +16,7 @@
</template> </template>
<script> <script>
import { format } from 'sql-formatter'; import { format } from "sql-formatter";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -26,38 +26,38 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
minifyJson: '', minifyJson: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
try { try {
this.toolResult = format(this.toolData.data, { this.toolResult = format(this.toolData.data, {
language: 'sql', language: "sql",
tabWidth: 4, tabWidth: 4,
keywordCase: 'upper', keywordCase: "upper",
functionCase: 'upper', functionCase: "upper",
identifierCase: 'lower', identifierCase: "lower",
linesBetweenQueries: 1, linesBetweenQueries: 1,
paramTypes: { paramTypes: {
custom: [ custom: [
{ regex: String.raw`\{\$?[\w\d\->\[\]]+\}` }, { regex: String.raw`\{\$?[\w\d\->\[\]]+\}` },
{ regex: String.raw`\$[\w\d\->\[\]]+` }, { regex: String.raw`\$[\w\d\->\[\]]+` },
{ regex: String.raw`['"].*['"]` }, { regex: String.raw`['"].*['"]` }
], ],
positional: true, positional: true,
named: [':', '@'], named: [":", "@"]
}, }
}); });
} catch (e) { } catch (e) {
this.toolResult = 'invalid syntax'; this.toolResult = "invalid syntax";
}
} }
} }
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -21,9 +21,12 @@
<label>Wrap in quotes</label> <label>Wrap in quotes</label>
<div> <div>
<input id="wrap_in_quotes_no" value="" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-on:change="result" type="radio"> <label for="wrap_in_quotes_no">No</label><br> <input id="wrap_in_quotes_no" value="" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-on:change="result"
<input id="wrap_in_quotes_single" value="single" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-on:change="result" type="radio"> <label for="wrap_in_quotes_single">Single</label><br> type="radio"> <label for="wrap_in_quotes_no">No</label><br>
<input id="wrap_in_quotes_double" value="double" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-on:change="result" type="radio"> <label for="wrap_in_quotes_double">Double</label> <input id="wrap_in_quotes_single" value="single" name="wrap_in_quotes" v-model="toolData.wrapInQuotes"
v-on:change="result" type="radio"> <label for="wrap_in_quotes_single">Single</label><br>
<input id="wrap_in_quotes_double" value="double" name="wrap_in_quotes" v-model="toolData.wrapInQuotes"
v-on:change="result" type="radio"> <label for="wrap_in_quotes_double">Double</label>
</div> </div>
</div> </div>
@ -59,29 +62,29 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
fieldName: '', fieldName: "",
data: '', data: "",
dataDelimiter: '', dataDelimiter: "",
wrapInQuotes: '', wrapInQuotes: "",
chunkBy: 900, chunkBy: 900
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
let data = this.toolData.data let data = this.toolData.data
.split(this.toolData.dataDelimiter ? this.toolData.dataDelimiter : '\n'); .split(this.toolData.dataDelimiter ? this.toolData.dataDelimiter : "\n");
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
let value = data[i]; let value = data[i];
switch (this.toolData.wrapInQuotes) { switch (this.toolData.wrapInQuotes) {
case 'single': case "single":
value = "'" + value.replace("'", "\\'") + "'"; value = "'" + value.replace("'", "\\'") + "'";
break; break;
case 'double': case "double":
value = '"' + value.replace('"', '\\"') + '"'; value = "\"" + value.replace("\"", "\\\"") + "\"";
break; break;
} }
@ -94,13 +97,13 @@ export default {
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
let chunk = data[i]; let chunk = data[i];
data[i] = '(' + chunk.join(',') + ')'; data[i] = "(" + chunk.join(",") + ")";
} }
this.toolResult = '(' + this.toolData.fieldName + ' IN ' + data.join(' OR ' + this.toolData.fieldName + ' IN ') + ')'; this.toolResult = "(" + this.toolData.fieldName + " IN " + data.join(" OR " + this.toolData.fieldName + " IN ") + ")";
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -12,9 +12,13 @@
<input id="data_delimiter" v-model="toolData.dataDelimiter" v-on:keyup="result" placeholder="," type="text"> <input id="data_delimiter" v-model="toolData.dataDelimiter" v-on:keyup="result" placeholder="," type="text">
<div> <div>
<input id="count_mode_characters" value="characters" name="count_mode" v-model="toolData.countMode" v-on:change="result" :disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_characters">characters</label><br> <input id="count_mode_characters" value="characters" name="count_mode" v-model="toolData.countMode"
<input id="count_mode_words" value="words" name="count_mode" v-model="toolData.countMode" v-on:change="result" :disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_words">words</label><br> v-on:change="result" :disabled="toolData.dataDelimiter.length" type="radio"> <label
<input id="count_mode_lines" value="lines" name="count_mode" v-model="toolData.countMode" v-on:change="result" :disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_lines">lines</label> for="count_mode_characters">characters</label><br>
<input id="count_mode_words" value="words" name="count_mode" v-model="toolData.countMode" v-on:change="result"
:disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_words">words</label><br>
<input id="count_mode_lines" value="lines" name="count_mode" v-model="toolData.countMode" v-on:change="result"
:disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_lines">lines</label>
</div> </div>
</div> </div>
@ -36,11 +40,11 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
dataDelimiter: '', dataDelimiter: "",
countMode: 'characters', countMode: "characters"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
@ -51,20 +55,20 @@ export default {
this.toolResult = this.toolData.data.split(this.toolData.dataDelimiter).length; this.toolResult = this.toolData.data.split(this.toolData.dataDelimiter).length;
} else { } else {
switch (this.toolData.countMode) { switch (this.toolData.countMode) {
case 'characters': case "characters":
this.toolResult = this.toolData.data.length; this.toolResult = this.toolData.data.length;
break; break;
case 'words': case "words":
this.toolResult = this.toolData.data.trim().split(/\s+/).length; this.toolResult = this.toolData.data.trim().split(/\s+/).length;
break; break;
case 'lines': case "lines":
this.toolResult = this.toolData.data.split('\n').length; this.toolResult = this.toolData.data.split("\n").length;
break; break;
} }
} }
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -26,9 +26,9 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
@ -37,7 +37,7 @@ export default {
if (word.length <= 3) { if (word.length <= 3) {
this.toolResult = word; this.toolResult = word;
return return;
} }
const firstLetter = word[0]; const firstLetter = word[0];
@ -45,9 +45,9 @@ export default {
const numberOfLetters = word.length - 2; const numberOfLetters = word.length - 2;
this.toolResult = `${firstLetter}${numberOfLetters}${lastLetter}`; this.toolResult = `${firstLetter}${numberOfLetters}${lastLetter}`;
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -21,8 +21,10 @@
<label>Pad position</label> <label>Pad position</label>
<div> <div>
<input id="pad_pos_begin" value="begin" name="pad_pos" v-model="toolData.padPos" v-on:change="result" type="radio"> <label for="pad_pos_begin">begin</label><br> <input id="pad_pos_begin" value="begin" name="pad_pos" v-model="toolData.padPos" v-on:change="result"
<input id="pad_pos_end" value="end" name="pad_pos" v-model="toolData.padPos" v-on:change="result" type="radio"> <label for="pad_pos_end">end</label> type="radio"> <label for="pad_pos_begin">begin</label><br>
<input id="pad_pos_end" value="end" name="pad_pos" v-model="toolData.padPos" v-on:change="result" type="radio">
<label for="pad_pos_end">end</label>
</div> </div>
</div> </div>
@ -30,8 +32,10 @@
<label>Pad by</label> <label>Pad by</label>
<div> <div>
<input id="pad_by_repeat_symbol" value="repeat_symbol" name="pad_by" v-model="toolData.padBy" v-on:change="result" type="radio"> <label for="pad_by_repeat_symbol">repeat symbol</label><br> <input id="pad_by_repeat_symbol" value="repeat_symbol" name="pad_by" v-model="toolData.padBy" v-on:change="result"
<input id="pad_by_string_length" value="string_length" name="pad_by" v-model="toolData.padBy" v-on:change="result" type="radio"> <label for="pad_by_string_length">to string length</label> type="radio"> <label for="pad_by_repeat_symbol">repeat symbol</label><br>
<input id="pad_by_string_length" value="string_length" name="pad_by" v-model="toolData.padBy" v-on:change="result"
type="radio"> <label for="pad_by_string_length">to string length</label>
</div> </div>
</div> </div>
@ -53,25 +57,25 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
padSymbol: '0', padSymbol: "0",
padCount: 3, padCount: 3,
padPos: 'begin', padPos: "begin",
padBy: 'string_length', padBy: "string_length"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
const lines = this.toolData.data.split('\n'); const lines = this.toolData.data.split("\n");
const paddedLines = lines.map((line) => { const paddedLines = lines.map((line) => {
if (this.toolData.padBy === 'string_length') { if (this.toolData.padBy === "string_length") {
const padLength = Math.max(0, this.toolData.padCount - line.length); const padLength = Math.max(0, this.toolData.padCount - line.length);
const padding = this.toolData.padSymbol.repeat(padLength); const padding = this.toolData.padSymbol.repeat(padLength);
if (this.toolData.padPos === 'begin') { if (this.toolData.padPos === "begin") {
return padding + line; return padding + line;
} else { } else {
return line + padding; return line + padding;
@ -79,7 +83,7 @@ export default {
} else { } else {
const padding = this.toolData.padSymbol.repeat(this.toolData.padCount); const padding = this.toolData.padSymbol.repeat(this.toolData.padCount);
if (this.toolData.padPos === 'begin') { if (this.toolData.padPos === "begin") {
return padding + line; return padding + line;
} else { } else {
return line + padding; return line + padding;
@ -87,10 +91,10 @@ export default {
} }
}); });
this.toolResult = paddedLines.join('\n'); this.toolResult = paddedLines.join("\n");
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -29,17 +29,17 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
this.toolResult = this.toolData.data.split('\n').filter(arrayUnique).join('\n'); this.toolResult = this.toolData.data.split("\n").filter(arrayUnique).join("\n");
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -11,12 +11,17 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="sort_mode_alpha" value="alpha" name="sort_mode" v-model="toolData.sortMode" v-on:change="result" type="radio"> <label for="sort_mode_alpha">alphabetically</label><br> <input id="sort_mode_alpha" value="alpha" name="sort_mode" v-model="toolData.sortMode" v-on:change="result"
<input id="sort_mode_numerically" value="numerically" name="sort_mode" v-model="toolData.sortMode" v-on:change="result" type="radio"> <label for="sort_mode_numerically">numerically</label><br> type="radio"> <label for="sort_mode_alpha">alphabetically</label><br>
<input id="sort_mode_by_length" value="by_length" name="sort_mode" v-model="toolData.sortMode" v-on:change="result" type="radio"> <label for="sort_mode_by_length">by length</label><br> <input id="sort_mode_numerically" value="numerically" name="sort_mode" v-model="toolData.sortMode"
<input id="sort_mode_random" value="random" name="sort_mode" v-model="toolData.sortMode" v-on:change="result" type="radio"> <label for="sort_mode_random">random</label><br> v-on:change="result" type="radio"> <label for="sort_mode_numerically">numerically</label><br>
<input id="sort_mode_by_length" value="by_length" name="sort_mode" v-model="toolData.sortMode"
v-on:change="result" type="radio"> <label for="sort_mode_by_length">by length</label><br>
<input id="sort_mode_random" value="random" name="sort_mode" v-model="toolData.sortMode" v-on:change="result"
type="radio"> <label for="sort_mode_random">random</label><br>
<br> <br>
<input id="sort_mode_reverse" value="random" name="sort_mode_reverse" v-model="toolData.sortModeReverse" v-on:change="result" type="checkbox"> <label for="sort_mode_reverse">reverse</label> <input id="sort_mode_reverse" value="random" name="sort_mode_reverse" v-model="toolData.sortModeReverse"
v-on:change="result" type="checkbox"> <label for="sort_mode_reverse">reverse</label>
</div> </div>
</div> </div>
@ -38,37 +43,37 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
sortMode: 'alpha', sortMode: "alpha",
sortModeReverse: false, sortModeReverse: false
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
let result = [] let result = [];
const data = this.toolData.data.split('\n'); const data = this.toolData.data.split("\n");
switch (this.toolData.sortMode) { switch (this.toolData.sortMode) {
case 'alpha': case "alpha":
result = data.sort(function(a, b) { result = data.sort(function(a, b) {
return a.localeCompare(b); return a.localeCompare(b);
}); });
break; break;
case 'numerically': case "numerically":
const collator = new Intl.Collator([], { numeric: true }); const collator = new Intl.Collator([], { numeric: true });
result = data.sort(function(a, b) { result = data.sort(function(a, b) {
return collator.compare(a, b); return collator.compare(a, b);
}); });
break; break;
case 'by_length': case "by_length":
result = data.sort(function(a, b) { result = data.sort(function(a, b) {
return a.length - b.length; return a.length - b.length;
}); });
break; break;
case 'random': case "random":
result = data.sort(function(a, b) { result = data.sort(function(a, b) {
return Math.random() - .5; return Math.random() - .5;
}); });
@ -79,10 +84,10 @@ export default {
result = result.reverse(); result = result.reverse();
} }
this.toolResult = result.join('\n'); this.toolResult = result.join("\n");
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -11,8 +11,10 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="case_mode_lower" value="lower" name="case_mode" v-model="toolData.caseMode" v-on:change="result" type="radio"> <label for="case_mode_lower">to lower</label><br> <input id="case_mode_lower" value="lower" name="case_mode" v-model="toolData.caseMode" v-on:change="result"
<input id="case_mode_upper" value="upper" name="case_mode" v-model="toolData.caseMode" v-on:change="result" type="radio"> <label for="case_mode_upper">to upper</label> type="radio"> <label for="case_mode_lower">to lower</label><br>
<input id="case_mode_upper" value="upper" name="case_mode" v-model="toolData.caseMode" v-on:change="result"
type="radio"> <label for="case_mode_upper">to upper</label>
</div> </div>
</div> </div>
@ -34,25 +36,25 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
caseMode: 'upper', caseMode: "upper"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
switch (this.toolData.caseMode) { switch (this.toolData.caseMode) {
case 'lower': case "lower":
this.toolResult = this.toolData.data.toLocaleLowerCase(); this.toolResult = this.toolData.data.toLocaleLowerCase();
break; break;
case 'upper': case "upper":
this.toolResult = this.toolData.data.toLocaleUpperCase(); this.toolResult = this.toolData.data.toLocaleUpperCase();
break; break;
} }
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -16,8 +16,8 @@
</template> </template>
<script> <script>
import axios from 'axios' import axios from "axios";
import { config } from '../../config'; import { config } from "../../config";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -27,27 +27,27 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
const natoAlphabet = { const natoAlphabet = {
'A': 'Alpha', 'B': 'Bravo', 'C': 'Charlie', 'D': 'Delta', "A": "Alpha", "B": "Bravo", "C": "Charlie", "D": "Delta",
'E': 'Echo', 'F': 'Foxtrot', 'G': 'Golf', 'H': 'Hotel', "E": "Echo", "F": "Foxtrot", "G": "Golf", "H": "Hotel",
'I': 'India', 'J': 'Juliett', 'K': 'Kilo', 'L': 'Lima', "I": "India", "J": "Juliett", "K": "Kilo", "L": "Lima",
'M': 'Mike', 'N': 'November', 'O': 'Oscar', 'P': 'Papa', "M": "Mike", "N": "November", "O": "Oscar", "P": "Papa",
'Q': 'Quebec', 'R': 'Romeo', 'S': 'Sierra', 'T': 'Tango', "Q": "Quebec", "R": "Romeo", "S": "Sierra", "T": "Tango",
'U': 'Uniform', 'V': 'Victor', 'W': 'Whiskey', 'X': 'X-ray', "U": "Uniform", "V": "Victor", "W": "Whiskey", "X": "X-ray",
'Y': 'Yankee', 'Z': 'Zulu', "Y": "Yankee", "Z": "Zulu"
}; };
this.toolResult = this.toolData.data.toUpperCase().split('').map(char => natoAlphabet[char] || char).join(' '); this.toolResult = this.toolData.data.toUpperCase().split("").map(char => natoAlphabet[char] || char).join(" ");
}
} }
} }
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -9,10 +9,12 @@
<div class="input-group"> <div class="input-group">
<label for="data_delimiter">Delimiter</label> <label for="data_delimiter">Delimiter</label>
<input id="data_delimiter" v-model="toolData.dataDelimiter" placeholder="," type="text" v-on:keyup="result" :disabled="toolData.dataIsJson"> <input id="data_delimiter" v-model="toolData.dataDelimiter" placeholder="," type="text" v-on:keyup="result"
:disabled="toolData.dataIsJson">
<div> <div>
<input id="data_is_json" name="data_is_json" v-model="toolData.dataIsJson" v-on:change="result" type="checkbox"> <label for="data_is_json">is json</label> <input id="data_is_json" name="data_is_json" v-model="toolData.dataIsJson" v-on:change="result" type="checkbox">
<label for="data_is_json">is json</label>
</div> </div>
</div> </div>
@ -25,8 +27,8 @@
</template> </template>
<script> <script>
import axios from 'axios' import axios from "axios";
import { config } from '../../config'; import { config } from "../../config";
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
@ -36,11 +38,11 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
dataDelimiter: '', dataDelimiter: "",
dataIsJson: false, dataIsJson: false
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
@ -48,7 +50,7 @@ export default {
axios.post(`${config.APP_URL}/api/php/str_to_php_array.php`, { axios.post(`${config.APP_URL}/api/php/str_to_php_array.php`, {
data: this.toolData.data, data: this.toolData.data,
delimiter: this.toolData.dataDelimiter, delimiter: this.toolData.dataDelimiter,
mode: this.toolData.dataIsJson ? 'json' : null, mode: this.toolData.dataIsJson ? "json" : null
}) })
.then((response) => { .then((response) => {
this.toolResult = response.data; this.toolResult = response.data;
@ -57,7 +59,7 @@ export default {
}); });
} }
} }
} };
</script> </script>
<style lang="scss"> <style lang="scss">

@ -20,7 +20,8 @@
<label>Transpose table</label> <label>Transpose table</label>
<div> <div>
<input id="transpose" name="transpose" v-model="toolData.transpose" v-on:change="result" type="checkbox"> <label for="transpose">transpose</label> <input id="transpose" name="transpose" v-model="toolData.transpose" v-on:change="result" type="checkbox"> <label
for="transpose">transpose</label>
</div> </div>
</div> </div>
@ -43,17 +44,17 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
selectedStyle: '', selectedStyle: "",
transpose: false, transpose: false
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
let rows = unproxy(this.toolData.data).split('\n'); let rows = unproxy(this.toolData.data).split("\n");
let numCols = rows[0].split('\t').length; let numCols = rows[0].split("\t").length;
// Transpose the table if the option is selected // Transpose the table if the option is selected
if (this.toolData.transpose) { if (this.toolData.transpose) {
@ -61,39 +62,39 @@ export default {
for (let j = 0; j < numCols; j++) { for (let j = 0; j < numCols; j++) {
const newRow = []; const newRow = [];
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rows.length; i++) {
newRow.push(rows[i].split('\t')[j] || ''); newRow.push(rows[i].split("\t")[j] || "");
} }
transposedData.push(newRow.join('\t')); transposedData.push(newRow.join("\t"));
} }
rows = transposedData; rows = transposedData;
numCols = rows[0].split('\t').length; numCols = rows[0].split("\t").length;
} }
let output = ''; let output = "";
// Generate header row // Generate header row
output += '| ' + rows[0].split('\t').join(' | ') + ' |\n'; output += "| " + rows[0].split("\t").join(" | ") + " |\n";
// Generate separator row based on selected style // Generate separator row based on selected style
switch (this.toolData.selectedStyle) { switch (this.toolData.selectedStyle) {
default: default:
output += '| ' + '-'.repeat(numCols).split('').join(' | ') + ' |\n'; output += "| " + "-".repeat(numCols).split("").join(" | ") + " |\n";
break; break;
} }
// Generate data rows // Generate data rows
for (let i = 1; i < rows.length; i++) { for (let i = 1; i < rows.length; i++) {
if (this.toolData.selectedStyle === 'grid') { if (this.toolData.selectedStyle === "grid") {
output += '| ' + rows[i].split('\t').join(' | ') + ' |\n'; output += "| " + rows[i].split("\t").join(" | ") + " |\n";
} else { } else {
output += '| ' + rows[i].split('\t').join(' | ') + ' |\n'; output += "| " + rows[i].split("\t").join(" | ") + " |\n";
} }
} }
this.toolResult = output; this.toolResult = output;
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -26,32 +26,32 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: ""
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
let output = '{| class="wikitable"\n'; let output = "{| class=\"wikitable\"\n";
const rows = unproxy(this.toolData.data).split('\n'); const rows = unproxy(this.toolData.data).split("\n");
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rows.length; i++) {
const cells = rows[i].split('\t'); const cells = rows[i].split("\t");
output += '|-\n'; output += "|-\n";
for (let j = 0; j < cells.length; j++) { for (let j = 0; j < cells.length; j++) {
output += i === 0 ? '! ' : '| '; output += i === 0 ? "! " : "| ";
output += cells[j].trim() + '\n'; output += cells[j].trim() + "\n";
} }
} }
output += '|}'; output += "|}";
this.toolResult = output; this.toolResult = output;
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -14,7 +14,9 @@
<tr v-for="(value, format) in currentTimestampFormatted" :key="format"> <tr v-for="(value, format) in currentTimestampFormatted" :key="format">
<td>{{ format }}</td> <td>{{ format }}</td>
<td>{{ value }}</td> <td>{{ value }}</td>
<td><button @click="copyTimestamp(value)">📋</button></td> <td>
<button @click="copyTimestamp(value)">📋</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -54,7 +56,9 @@
<td><input type="number" v-model="toolData.inputHour"></td> <td><input type="number" v-model="toolData.inputHour"></td>
<td><input type="number" v-model="toolData.inputMinute"></td> <td><input type="number" v-model="toolData.inputMinute"></td>
<td><input type="number" v-model="toolData.inputSecond"></td> <td><input type="number" v-model="toolData.inputSecond"></td>
<td><button @click="convertToUnix">Convert </button></td> <td>
<button @click="convertToUnix">Convert </button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -63,22 +67,22 @@
</template> </template>
<script> <script>
import moment from 'moment'; import moment from "moment";
export default { export default {
data() { data() {
return { return {
toolData: { toolData: {
inputTimestamp: '', inputTimestamp: "",
inputYear: moment().year(), inputYear: moment().year(),
inputMonth: moment().month() + 1, inputMonth: moment().month() + 1,
inputDay: moment().day(), inputDay: moment().day(),
inputHour: moment().hour(), inputHour: moment().hour(),
inputMinute: moment().minute(), inputMinute: moment().minute(),
inputSecond: moment().second(), inputSecond: moment().second()
}, },
currentTimestamp: 0, currentTimestamp: 0,
currentTimestampFormatted: {}, currentTimestampFormatted: {}
}; };
}, },
mounted() { mounted() {
@ -86,7 +90,7 @@ export default {
this.currentTimestamp = moment().unix(); this.currentTimestamp = moment().unix();
this.currentTimestampFormatted = { this.currentTimestampFormatted = {
'UTC': moment().utc().format('YYYY-MM-DDTHH:mm:ss[Z]'), "UTC": moment().utc().format("YYYY-MM-DDTHH:mm:ss[Z]"),
// 'UTC (local)': moment().format('YYYY-MM-DDTHH:mm:ssZZ'), // 'UTC (local)': moment().format('YYYY-MM-DDTHH:mm:ssZZ'),
// 'ISO 8601': moment().toISOString(), // 'ISO 8601': moment().toISOString(),
// 'RFC 2822': moment().format('ddd, DD MMM YYYY HH:mm:ss ZZ'), // 'RFC 2822': moment().format('ddd, DD MMM YYYY HH:mm:ss ZZ'),
@ -97,10 +101,10 @@ export default {
// 'RFC 3339': moment().format('YYYY-MM-DDTHH:mm:ssZZ'), // 'RFC 3339': moment().format('YYYY-MM-DDTHH:mm:ssZZ'),
// 'COOKIE': moment().format('dddd, DD-MMM-YYYY HH:mm:ss [UTC]'), // 'COOKIE': moment().format('dddd, DD-MMM-YYYY HH:mm:ss [UTC]'),
// 'RSS': moment().format('ddd, DD MMM YYYY HH:mm:ss ZZ'), // 'RSS': moment().format('ddd, DD MMM YYYY HH:mm:ss ZZ'),
'Unix Epoch': moment().unix(), "Unix Epoch": moment().unix(),
'YYYY-DD-MM': moment().format('YYYY/MM/DD'), "YYYY-DD-MM": moment().format("YYYY/MM/DD"),
'SQL DATETIME': moment().toISOString().replaceAll(/[ZT]|(\.[0-9]{3})/g, ' '), "SQL DATETIME": moment().toISOString().replaceAll(/[ZT]|(\.[0-9]{3})/g, " "),
'YYYY/DD/MM HH:MM:SS AM/PM': moment().format('YYYY/MM/DD HH:mm:ss A'), "YYYY/DD/MM HH:MM:SS AM/PM": moment().format("YYYY/MM/DD HH:mm:ss A")
// 'DD.MM.YYYY HH:MM:SS': moment().format('DD.MM.YYYY HH:mm:ss'), // 'DD.MM.YYYY HH:MM:SS': moment().format('DD.MM.YYYY HH:mm:ss'),
}; };
}; };
@ -142,8 +146,8 @@ export default {
.catch(err => { .catch(err => {
// console.error('Failed to copy: ', err); // console.error('Failed to copy: ', err);
}); });
}, }
}, }
}; };
</script> </script>
@ -151,6 +155,7 @@ export default {
.table-date-and-time th { .table-date-and-time th {
text-align: left; text-align: left;
} }
.table-date-and-time td input { .table-date-and-time td input {
width: 80px; width: 80px;
} }

@ -11,8 +11,10 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="encode_mode_encode" value="encode" name="encode_mode" v-model="toolData.encodeMode" v-on:change="result" type="radio"> <label for="encode_mode_encode">encode</label><br> <input id="encode_mode_encode" value="encode" name="encode_mode" v-model="toolData.encodeMode"
<input id="encode_mode_decode" value="decode" name="encode_mode" v-model="toolData.encodeMode" v-on:change="result" type="radio"> <label for="encode_mode_decode">decode</label> v-on:change="result" type="radio"> <label for="encode_mode_encode">encode</label><br>
<input id="encode_mode_decode" value="decode" name="encode_mode" v-model="toolData.encodeMode"
v-on:change="result" type="radio"> <label for="encode_mode_decode">decode</label>
</div> </div>
</div> </div>
@ -34,25 +36,25 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
encodeMode: 'decode', encodeMode: "decode"
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
result() { result() {
switch (this.toolData.encodeMode) { switch (this.toolData.encodeMode) {
case 'encode': case "encode":
this.toolResult = this.toolData.data.split('\n').map(encodeURIComponent).join('\n'); this.toolResult = this.toolData.data.split("\n").map(encodeURIComponent).join("\n");
break; break;
case 'decode': case "decode":
this.toolResult = this.toolData.data.split('\n').map(decodeURIComponent).join('\n'); this.toolResult = this.toolData.data.split("\n").map(decodeURIComponent).join("\n");
break; break;
} }
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">

@ -40,10 +40,10 @@ export default {
data() { data() {
return { return {
toolData: { toolData: {
data: '', data: "",
queryParts: [], queryParts: []
}, },
toolResult: '', toolResult: ""
}; };
}, },
methods: { methods: {
@ -63,22 +63,23 @@ export default {
for (let [key, value] of url.searchParams.entries()) { for (let [key, value] of url.searchParams.entries()) {
queryParams.push({ queryParams.push({
key: key, key: key,
value: value, value: value
}); });
} }
this.toolData.queryParts = queryParams.sort((a, b) => { this.toolData.queryParts = queryParams.sort((a, b) => {
return a.key.localeCompare(b.key); return a.key.localeCompare(b.key);
}) });
},
},
} }
}
};
</script> </script>
<style lang="scss"> <style lang="scss">
table tr:nth-child(even) input { table tr:nth-child(even) input {
background-color: #fbfbfb; background-color: #fbfbfb;
} }
table tr:nth-child(odd) input { table tr:nth-child(odd) input {
background-color: #eee; background-color: #eee;
} }