Add phpinfo

This commit is contained in:
Illya Marchenko 2024-10-16 11:19:00 +03:00
parent 8d883ec96d
commit 37bdd7d9f8
Signed by: stuzer05
GPG Key ID: A6ABAAA9268F9F4F
47 changed files with 1775 additions and 965 deletions

5
api/php/phpinfo.php Normal file

@ -0,0 +1,5 @@
<?php
require_once 'cors.php';
phpinfo();

@ -1,6 +1,5 @@
const config = { const config = {
APP_URL: 'http://localhost:3000', APP_URL: 'http://192.168.33.27:3000/',
// API_URL: 'http://localhost:8080/v1',
}; };
export { config } export { config };

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico"/> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tools</title> <title>Tools</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

@ -1,6 +1,6 @@
module.exports = { module.exports = {
plugins: { plugins: {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };

@ -1,71 +1,90 @@
<template> <template>
<div <div
class="w-full flex flex-col sm:flex-row flex-grow" class="w-full flex flex-col sm:flex-row flex-grow"
:class="{ 'sidebar-toggle': sidebarToggle }"> :class="{ 'sidebar-toggle': sidebarToggle }"
<aside >
class="hidden md:block h-screen overflow-y-auto no-scrollbar border-r"> <aside
<Sidebar/> class="hidden md:block h-screen overflow-y-auto no-scrollbar border-r"
</aside> >
<Sidebar />
</aside>
<main role="main" class="w-full h-full flex-grow overflow-auto p-3"> <main role="main" class="w-full h-full flex-grow overflow-auto p-3">
<RouterView/> <RouterView />
</main> </main>
<button class="sidebar-toggle-btn md:hidden" v-on:click="toggleSidebar"> <button class="sidebar-toggle-btn md:hidden" v-on:click="toggleSidebar">
<svg class="svg-icon" style="width: 30px; height: 30px;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M682.666667 682.666667h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666H170.666667v-170.666666z m512-256h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666H170.666667v-170.666666z m512-256h170.666666v170.666666h-170.666666V170.666667z m-256 0h170.666666v170.666666h-170.666666V170.666667zM170.666667 170.666667h170.666666v170.666666H170.666667V170.666667z" fill="#000000" /></svg> <svg
</button> class="svg-icon"
</div> style="
width: 30px;
height: 30px;
vertical-align: middle;
fill: currentColor;
overflow: hidden;
"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M682.666667 682.666667h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666H170.666667v-170.666666z m512-256h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666h-170.666666v-170.666666z m-256 0h170.666666v170.666666H170.666667v-170.666666z m512-256h170.666666v170.666666h-170.666666V170.666667z m-256 0h170.666666v170.666666h-170.666666V170.666667zM170.666667 170.666667h170.666666v170.666666H170.666667V170.666667z"
fill="#000000"
/>
</svg>
</button>
</div>
</template> </template>
<script> <script>
import { RouterView } from 'vue-router' import { RouterView } from "vue-router";
import Sidebar from '@/components/Sidebar.vue'; import Sidebar from "@/components/Sidebar.vue";
export default { export default {
components: { components: {
Sidebar, Sidebar,
RouterView, RouterView,
}, },
data() { data() {
return { return {
sidebarToggle: false, sidebarToggle: false,
}; };
}, },
methods: { methods: {
toggleSidebar() { toggleSidebar() {
this.sidebarToggle = !this.sidebarToggle; this.sidebarToggle = !this.sidebarToggle;
this.emitter.emit('sidebar.toggle'); this.emitter.emit("sidebar.toggle");
}, },
}, },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
aside { aside {
width: 480px; width: 480px;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.sidebar-toggle { .sidebar-toggle {
aside { aside {
display: block; display: block;
width: 100%; width: 100%;
max-width: initial; max-width: initial;
} }
main { main {
display: none; display: none;
} }
&-btn { &-btn {
right: 10px; right: 10px;
bottom: 10px; bottom: 10px;
position: fixed; position: fixed;
z-index: 1000; z-index: 1000;
background-color: white; background-color: white;
border-radius: 5px; border-radius: 5px;
padding: 2px; padding: 2px;
} }
} }
} }
</style> </style>

@ -1,23 +1,23 @@
import { createApp } from 'vue' import { createApp } from "vue";
import { createPinia } from 'pinia' import { createPinia } from "pinia";
import axios from 'axios' import axios from "axios";
import VueAxios from 'vue-axios' import VueAxios from "vue-axios";
import mitt from 'mitt'; import mitt from "mitt";
import './assets/app.scss' import "./assets/app.scss";
import App from './App.vue' import App from "./App.vue";
import router from './router' import router from "./router";
axios.defaults.withCredentials = true; axios.defaults.withCredentials = true;
const app = createApp(App) const app = createApp(App);
app.config.globalProperties.emitter = mitt(); app.config.globalProperties.emitter = mitt();
app.use(createPinia()) app.use(createPinia());
app.use(VueAxios, axios) app.use(VueAxios, axios);
app.use(router) app.use(router);
app.mount('#app') app.mount("#app");

@ -1,9 +1,9 @@
<template> <template>
<div :id="name"></div> <div :id="name"></div>
</template> </template>
<script> <script>
import loader from '@monaco-editor/loader'; import loader from "@monaco-editor/loader";
let monacoResultInst = null; let monacoResultInst = null;
@ -16,11 +16,11 @@ export default {
}, },
language: { language: {
type: String, type: String,
default: 'text', default: "text",
}, },
value: { value: {
type: String, type: String,
default: '', default: "",
}, },
readonly: { readonly: {
type: Boolean, type: Boolean,
@ -40,7 +40,7 @@ export default {
}, },
unmounted() { unmounted() {
if (monacoResultInst) { if (monacoResultInst) {
monacoResultInst.editor.getModels().forEach(model => model.dispose()); monacoResultInst.editor.getModels().forEach((model) => model.dispose());
} }
}, },
watch: { watch: {
@ -50,16 +50,14 @@ export default {
deep: true, deep: true,
async handler(value, oldValue) { async handler(value, oldValue) {
while (!monacoResultInst) { while (!monacoResultInst) {
await new Promise(r => setTimeout(r, 10)); await new Promise((r) => setTimeout(r, 10));
} }
monacoResultInst.editor.getModels()[0].setValue(value.toString()); monacoResultInst.editor.getModels()[0].setValue(value.toString());
} },
} },
} },
}; };
</script> </script>
<style scoped> <style scoped></style>
</style>

@ -1,30 +1,53 @@
<template> <template>
<header class="flex justify-between mx-2 mt-1"> <header class="flex justify-between mx-2 mt-1">
<span class="font-bold">Tools</span> <span class="font-bold">Tools</span>
<router-link :to="{name:'home'}" class="ml-4" tag="button">Home</router-link> <router-link :to="{ name: 'home' }" class="ml-4" tag="button"
</header> >Home</router-link
>
</header>
<hr class="mt-2 mb-2"> <hr class="mt-2 mb-2" />
<nav class="flex flex-col ml-2"> <nav class="flex flex-col ml-2">
<div v-for="[title, routes] of Object.entries(menuRoutes).sort((a, b) => a[0].localeCompare(b[0]))" class="flex flex-col mb-2"> <div
<p><i>{{ title }}</i></p> v-for="[title, routes] of Object.entries(menuRoutes).sort((a, b) =>
<router-link v-for="[key, value] of Object.entries(routes)" :to="{name:key}" class="ml-4" tag="button">{{ value }}</router-link> a[0].localeCompare(b[0])
)"
class="flex flex-col mb-2"
>
<p>
<i>{{ title }}</i>
</p>
<router-link
v-for="[key, value] of Object.entries(routes)"
:to="{ name: key }"
class="ml-4"
tag="button"
>{{ value }}</router-link
>
</div> </div>
<hr class="mt-3 mb-3"> <hr class="mt-3 mb-3" />
<div class="flex flex-col mb-2"> <div class="flex flex-col mb-2">
<p><i>Other</i></p> <p><i>Other</i></p>
<a href="https://gist.stuzer.link/stuzer05/liked" class="ml-4" tag="button">Gist</a> <a
<a href="https://cyberchef.tools.stuzer.link/" class="ml-4" tag="button">Cyberchef</a> href="https://gist.stuzer.link/stuzer05/liked"
<a href="https://pdf.tools.stuzer.link/" class="ml-4" tag="button">PDF tools</a> class="ml-4"
tag="button"
>Gist</a
>
<a href="https://cyberchef.tools.stuzer.link/" class="ml-4" tag="button"
>Cyberchef</a
>
<a href="https://pdf.tools.stuzer.link/" class="ml-4" tag="button"
>PDF tools</a
>
</div> </div>
</nav> </nav>
</template> </template>
<script> <script>
import { useToolsStore } from "@/stores/toolsStore"; import { useToolsStore } from "@/stores/toolsStore";
export default { export default {
@ -37,6 +60,6 @@ export default {
}, },
mounted() { mounted() {
this.menuRoutes = useToolsStore().tools; this.menuRoutes = useToolsStore().tools;
} },
} };
</script> </script>

@ -9,57 +9,57 @@ const router = createRouter({
{ {
path: "/", path: "/",
name: "home", name: "home",
component: () => import("../views/HomeView.vue") component: () => import("../views/HomeView.vue"),
}, },
{ {
path: "/explain_crontab", path: "/explain_crontab",
name: "explain_crontab", name: "explain_crontab",
component: () => import("../views/unix/ExplainCrontab.vue") component: () => import("../views/unix/ExplainCrontab.vue"),
}, },
{ {
path: "/table_to_markdown_table", path: "/table_to_markdown_table",
name: "table_to_markdown_table", name: "table_to_markdown_table",
component: () => import("../views/general/TableToMarkdownTable.vue") component: () => import("../views/general/TableToMarkdownTable.vue"),
}, },
{ {
path: "/table_to_mediawiki_table", path: "/table_to_mediawiki_table",
name: "table_to_mediawiki_table", name: "table_to_mediawiki_table",
component: () => import("../views/general/TableToMediawikiTable.vue") component: () => import("../views/general/TableToMediawikiTable.vue"),
}, },
{ {
path: "/dummy_image", path: "/dummy_image",
name: "dummy_image", name: "dummy_image",
component: () => import("../views/generators/DummyImage.vue") component: () => import("../views/generators/DummyImage.vue"),
}, },
{ {
path: "/humans_txt", path: "/humans_txt",
name: "humans_txt", name: "humans_txt",
component: () => import("../views/general/HumansTxt.vue") component: () => import("../views/general/HumansTxt.vue"),
}, },
{ {
path: "/qr_code", path: "/qr_code",
name: "qr_code", name: "qr_code",
component: () => import("../views/generators/QRCode.vue") component: () => import("../views/generators/QRCode.vue"),
}, },
{ {
path: "/unix_timestamp", path: "/unix_timestamp",
name: "unix_timestamp", name: "unix_timestamp",
component: () => import("../views/unix/UnixTimestamp.vue") component: () => import("../views/unix/UnixTimestamp.vue"),
}, },
{ {
path: "/file_base64_encode_decode", path: "/file_base64_encode_decode",
name: "file_base64_encode_decode", name: "file_base64_encode_decode",
component: () => import("../views/unix/FileBase64EncodeDecode.vue") component: () => import("../views/unix/FileBase64EncodeDecode.vue"),
}, },
{ {
path: "/sed_generator", path: "/sed_generator",
name: "sed_generator", name: "sed_generator",
component: () => import("../views/unix/SedGenerator.vue") component: () => import("../views/unix/SedGenerator.vue"),
}, },
{ {
path: "/htaccess_generator", path: "/htaccess_generator",
name: "htaccess_generator", name: "htaccess_generator",
component: () => import("../views/unix/HtaccessGenerator.vue") component: () => import("../views/unix/HtaccessGenerator.vue"),
}, },
/** /**
@ -68,57 +68,57 @@ const router = createRouter({
{ {
path: "/str_length", path: "/str_length",
name: "str_length", name: "str_length",
component: () => import("../views/strings/Length.vue") component: () => import("../views/strings/Length.vue"),
}, },
{ {
path: "/str_sort_lines", path: "/str_sort_lines",
name: "str_sort_lines", name: "str_sort_lines",
component: () => import("../views/strings/SortLines.vue") component: () => import("../views/strings/SortLines.vue"),
}, },
{ {
path: "/str_to_lower_upper", path: "/str_to_lower_upper",
name: "str_to_lower_upper", name: "str_to_lower_upper",
component: () => import("../views/strings/ToLowerUppper.vue") component: () => import("../views/strings/ToLowerUppper.vue"),
}, },
{ {
path: "/str_remove_duplicate_lines", path: "/str_remove_duplicate_lines",
name: "str_remove_duplicate_lines", name: "str_remove_duplicate_lines",
component: () => import("../views/strings/RemoveDuplicateLines.vue") component: () => import("../views/strings/RemoveDuplicateLines.vue"),
}, },
{ {
path: "/str_pad", path: "/str_pad",
name: "str_pad", name: "str_pad",
component: () => import("../views/strings/Pad.vue") component: () => import("../views/strings/Pad.vue"),
}, },
{ {
path: "/str_numeronym", path: "/str_numeronym",
name: "str_numeronym", name: "str_numeronym",
component: () => import("../views/strings/Numeronym.vue") component: () => import("../views/strings/Numeronym.vue"),
}, },
{ {
path: "/str_to_nato_alphabet", path: "/str_to_nato_alphabet",
name: "str_to_nato_alphabet", name: "str_to_nato_alphabet",
component: () => import("../views/strings/NATOAlphabet.vue") component: () => import("../views/strings/NATOAlphabet.vue"),
}, },
{ {
path: "/url_encode_decode", path: "/url_encode_decode",
name: "url_encode_decode", name: "url_encode_decode",
component: () => import("../views/strings/UrlEncodeDecode.vue") component: () => import("../views/strings/UrlEncodeDecode.vue"),
}, },
{ {
path: "/url_query_viewer", path: "/url_query_viewer",
name: "url_query_viewer", name: "url_query_viewer",
component: () => import("../views/strings/UrlQueryViewer.vue") component: () => import("../views/strings/UrlQueryViewer.vue"),
}, },
{ {
path: "/fix_ru_en_keyboard", path: "/fix_ru_en_keyboard",
name: "fix_ru_en_keyboard", name: "fix_ru_en_keyboard",
component: () => import("../views/strings/FixRuEnKeyboard.vue") component: () => import("../views/strings/FixRuEnKeyboard.vue"),
}, },
{ {
path: "/iban_generator", path: "/iban_generator",
name: "iban_generator", name: "iban_generator",
component: () => import("../views/generators/IbanGenerator.vue") component: () => import("../views/generators/IbanGenerator.vue"),
}, },
/** /**
@ -127,17 +127,17 @@ const router = createRouter({
{ {
path: "/str_to_php_array", path: "/str_to_php_array",
name: "str_to_php_array", name: "str_to_php_array",
component: () => import("../views/php/StrToPHPArray.vue") component: () => import("../views/php/StrToPHPArray.vue"),
}, },
{ {
path: "/php_array_to_json", path: "/php_array_to_json",
name: "php_array_to_json", name: "php_array_to_json",
component: () => import("../views/php/PHPArrayToJson.vue") component: () => import("../views/php/PHPArrayToJson.vue"),
}, },
{ {
path: "/php_serialize", path: "/php_serialize",
name: "php_serialize", name: "php_serialize",
component: () => import("../views/php/Serialize.vue") component: () => import("../views/php/Serialize.vue"),
}, },
/** /**
@ -146,12 +146,12 @@ const router = createRouter({
{ {
path: "/json_formatter", path: "/json_formatter",
name: "json_formatter", name: "json_formatter",
component: () => import("../views/json/JSONFormatter.vue") component: () => import("../views/json/JSONFormatter.vue"),
}, },
{ {
path: "/json_minifier", path: "/json_minifier",
name: "json_minifier", name: "json_minifier",
component: () => import("../views/json/JSONMinifier.vue") component: () => import("../views/json/JSONMinifier.vue"),
}, },
/** /**
@ -160,12 +160,12 @@ const router = createRouter({
{ {
path: "/go_json_to_struct", path: "/go_json_to_struct",
name: "go_json_to_struct", name: "go_json_to_struct",
component: () => import("../views/go/JSONToStruct.vue") component: () => import("../views/go/JSONToStruct.vue"),
}, },
{ {
path: "/sql_tables_to_struct", path: "/sql_tables_to_struct",
name: "sql_tables_to_struct", name: "sql_tables_to_struct",
component: () => import("../views/go/SQLTablesToStruct.vue") component: () => import("../views/go/SQLTablesToStruct.vue"),
}, },
/** /**
@ -174,7 +174,7 @@ const router = createRouter({
{ {
path: "/docker_rename_volume", path: "/docker_rename_volume",
name: "docker_rename_volume", name: "docker_rename_volume",
component: () => import("../views/docker/RenameVolume.vue") component: () => import("../views/docker/RenameVolume.vue"),
}, },
/** /**
@ -183,14 +183,23 @@ const router = createRouter({
{ {
path: "/sql_split_in", path: "/sql_split_in",
name: "sql_split_in", name: "sql_split_in",
component: () => import("../views/sql/SplitInView.vue") component: () => import("../views/sql/SplitInView.vue"),
}, },
{ {
path: "/sql_formatter", path: "/sql_formatter",
name: "sql_formatter", name: "sql_formatter",
component: () => import("../views/sql/Formatter.vue") component: () => import("../views/sql/Formatter.vue"),
} },
]
/**
* Other
*/
{
path: "/phpinfo",
name: "phpinfo",
component: () => import("../views/PHPInfo.vue"),
},
],
}); });
export default router; export default router;

@ -1,4 +1,4 @@
import { defineStore } from 'pinia' import { defineStore } from "pinia";
function sortMenuRoutes(routes) { function sortMenuRoutes(routes) {
const sortedRoutes = {}; const sortedRoutes = {};
@ -17,61 +17,61 @@ function sortMenuRoutes(routes) {
return sortedRoutes; return sortedRoutes;
} }
export const useToolsStore = defineStore('tools', { export const useToolsStore = defineStore("tools", {
state: () => ({ state: () => ({
tools: sortMenuRoutes({ tools: sortMenuRoutes({
'-': { "-": {
'table_to_markdown_table': 'Table to Markdown table', table_to_markdown_table: "Table to Markdown table",
'table_to_mediawiki_table': 'Table to Mediawiki table', table_to_mediawiki_table: "Table to Mediawiki table",
'humans_txt': 'humans.txt generator', humans_txt: "humans.txt generator",
}, },
'Docker': { Docker: {
'docker_rename_volume': 'Rename volume', 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',
}, },
'JSON': { JSON: {
'json_minifier': 'JSON minifier', json_minifier: "JSON minifier",
'json_formatter': 'JSON formatter', json_formatter: "JSON formatter",
}, },
'PHP': { PHP: {
'str_to_php_array': 'Str to PHP array', str_to_php_array: "Str to PHP array",
'php_array_to_json': 'PHP array to Json', php_array_to_json: "PHP array to Json",
'php_serialize': 'PHP serialize', php_serialize: "PHP serialize",
}, },
'SQL': { SQL: {
'sql_formatter': 'SQL formatter', sql_formatter: "SQL formatter",
'sql_split_in': 'SQL split IN', sql_split_in: "SQL split IN",
}, },
'Strings': { Strings: {
'fix_ru_en_keyboard': 'Fix ru-en keyboard', fix_ru_en_keyboard: "Fix ru-en keyboard",
'str_length': 'Str length', str_length: "Str length",
'str_sort_lines': 'Str sort lines', str_sort_lines: "Str sort lines",
'str_to_lower_upper': 'Str to lower/upper', str_to_lower_upper: "Str to lower/upper",
'str_remove_duplicate_lines': 'Str remove duplicate lines', str_remove_duplicate_lines: "Str remove duplicate lines",
'str_pad': 'Str pad', str_pad: "Str pad",
'str_numeronym': 'Str numeronym (i18n)', str_numeronym: "Str numeronym (i18n)",
'str_to_nato_alphabet': 'Str to NATO alphabet', str_to_nato_alphabet: "Str to NATO alphabet",
'url_encode_decode': 'URL encode/decode', url_encode_decode: "URL encode/decode",
'url_query_viewer': 'URL query viewer', url_query_viewer: "URL query viewer",
}, },
'Unix': { Unix: {
'explain_crontab': 'Explain crontab', explain_crontab: "Explain crontab",
'file_base64_encode_decode': 'File base64 encode/decode', file_base64_encode_decode: "File base64 encode/decode",
'unix_timestamp': 'Unix timestamp', unix_timestamp: "Unix timestamp",
'sed_generator': 'Sed generator', sed_generator: "Sed generator",
'htaccess_generator': '.htaccess generator', htaccess_generator: ".htaccess generator",
}, },
'Generators': { Generators: {
'qr_code': 'QR code', qr_code: "QR code",
'iban_generator': 'IBAN generator', iban_generator: "IBAN generator",
'dummy_image': 'Dummy image', dummy_image: "Dummy image",
}, },
}), }),
actions: { actions: {
// You can add actions here if needed, e.g., to update the tools // You can add actions here if needed, e.g., to update the tools
}, },
}), }),
}) });

@ -1,7 +1,5 @@
function unproxy(obj) { function unproxy(obj) {
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
} }
export { export { unproxy };
unproxy,
}

@ -1,36 +1,34 @@
import { ref, customRef } from 'vue' import { ref, customRef } from "vue";
const debounce = (fn, delay = 0, immediate = false) => { const debounce = (fn, delay = 0, immediate = false) => {
let timeout let timeout;
return (...args) => { return (...args) => {
if (immediate && !timeout) fn(...args) if (immediate && !timeout) fn(...args);
clearTimeout(timeout) clearTimeout(timeout);
timeout = setTimeout(() => { timeout = setTimeout(() => {
fn(...args) fn(...args);
}, delay) }, delay);
} };
} };
const useDebouncedRef = (initialValue, delay, immediate) => { const useDebouncedRef = (initialValue, delay, immediate) => {
const state = ref(initialValue) const state = ref(initialValue);
const debouncedRef = customRef((track, trigger) => ({ const debouncedRef = customRef((track, trigger) => ({
get() { get() {
track() track();
return state.value return state.value;
}, },
set: debounce( set: debounce(
value => { (value) => {
state.value = value state.value = value;
trigger() trigger();
}, },
delay, delay,
immediate immediate
), ),
})) }));
return debouncedRef return debouncedRef;
} };
export { export { useDebouncedRef };
useDebouncedRef,
}

@ -1,7 +1,13 @@
<template> <template>
<div class="container mx-auto p-4"> <div class="container mx-auto p-4">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-5"> <div
<div v-for="(category, categoryName) in tools" :key="categoryName" class="bg-white rounded-lg shadow-md p-4"> class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-5"
>
<div
v-for="(category, categoryName) in tools"
:key="categoryName"
class="bg-white rounded-lg shadow-md p-4"
>
<h2 class="text-xl font-semibold mb-3">{{ categoryName }}</h2> <h2 class="text-xl font-semibold mb-3">{{ categoryName }}</h2>
<div class="max-h-80 overflow-y-auto"> <div class="max-h-80 overflow-y-auto">
<ul class="space-y-2"> <ul class="space-y-2">
@ -19,22 +25,43 @@
</div> </div>
</div> </div>
<hr class="my-5"> <hr class="my-5" />
<div class="flex flex-col items-center justify-center p-4"> <div class="flex flex-col items-center justify-center p-4">
<div class="flex flex-wrap justify-center items-center gap-4 max-w-4xl"> <div class="flex flex-wrap justify-center items-center gap-4 max-w-4xl">
<a href="https://gist.stuzer.link/stuzer05/liked" class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"> <a
<img src="https://gist.stuzer.link/assets/opengist-85b89b9c.svg" alt="Gist Icon" class="w-12 h-12 mr-4"> href="https://gist.stuzer.link/stuzer05/liked"
class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"
>
<img
src="https://gist.stuzer.link/assets/opengist-85b89b9c.svg"
alt="Gist Icon"
class="w-12 h-12 mr-4"
/>
<span class="text-lg font-medium">Gist</span> <span class="text-lg font-medium">Gist</span>
</a> </a>
<a href="https://cyberchef.tools.stuzer.link/" class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"> <a
<img src="https://cyberchef.tools.stuzer.link/images/cyberchef-128x128.png" alt="Cyberchef Icon" class="w-12 h-12 mr-4"> href="https://cyberchef.tools.stuzer.link/"
class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"
>
<img
src="https://cyberchef.tools.stuzer.link/images/cyberchef-128x128.png"
alt="Cyberchef Icon"
class="w-12 h-12 mr-4"
/>
<span class="text-lg font-medium">Cyberchef</span> <span class="text-lg font-medium">Cyberchef</span>
</a> </a>
<a href="https://pdf.tools.stuzer.link/" class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"> <a
<img src="https://pdf.tools.stuzer.link/favicon.svg" alt="PDF Tools Icon" class="w-12 h-12 mr-4"> href="https://pdf.tools.stuzer.link/"
class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"
>
<img
src="https://pdf.tools.stuzer.link/favicon.svg"
alt="PDF Tools Icon"
class="w-12 h-12 mr-4"
/>
<span class="text-lg font-medium">PDF tools</span> <span class="text-lg font-medium">PDF tools</span>
</a> </a>
</div> </div>
@ -49,7 +76,7 @@ export default {
data() { data() {
return { return {
tools: {}, tools: {},
} };
}, },
setup() { setup() {
const router = useRouter(); const router = useRouter();
@ -62,10 +89,8 @@ export default {
}, },
mounted() { mounted() {
this.tools = useToolsStore().tools; this.tools = useToolsStore().tools;
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

55
src/views/PHPInfo.vue Normal file

@ -0,0 +1,55 @@
<template>
<div v-html="toolResult"></div>
</template>
<script>
import axios from "axios";
import { config } from "../../config";
export default {
data() {
return {
toolResult: "",
};
},
mounted() {
axios.post(`${config.APP_URL}/api/php/phpinfo.php`, {}).then((response) => {
const phpinfoHTML = response.data;
// Create a temporary DOM element
const tempDiv = document.createElement("div");
tempDiv.innerHTML = phpinfoHTML;
// Select all <style> tags
const styleTags = tempDiv.querySelectorAll("style");
styleTags.forEach((styleTag) => {
// Get the CSS content
let cssContent = styleTag.innerHTML;
// Prepend "main " to each selector
cssContent = cssContent.replace(/([^{}]+){/g, "main $1 {");
// Update the <style> tag's content
styleTag.innerHTML = cssContent;
});
// Make <hr> full width
tempDiv.innerHTML += `
<style>
main hr {
width: 100% !important;
}
</style>
`;
// Extract the modified HTML content
this.toolResult = tempDiv.innerHTML;
Promise.resolve(response);
});
},
};
</script>
<style lang="scss"></style>

@ -1,22 +1,36 @@
<template> <template>
<h2 class="tool-title">Docker rename volume</h2> <h2 class="tool-title">Docker rename volume</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="volume_name_old">Old volume name</label> <label for="volume_name_old">Old volume name</label>
<input id="volume_name_old" v-model="toolData.volumeNameOld" v-on:keyup="result" type="text"> <input
id="volume_name_old"
v-model="toolData.volumeNameOld"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="volume_name_new">New volume name</label> <label for="volume_name_new">New volume name</label>
<input id="volume_name_new" v-model="toolData.volumeNameNew" v-on:keyup="result" type="text"> <input
id="volume_name_new"
v-model="toolData.volumeNameNew"
v-on:keyup="result"
type="text"
/>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -25,15 +39,15 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
volumeNameOld: "", volumeNameOld: "",
volumeNameNew: "" volumeNameNew: "",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -48,11 +62,9 @@ export default {
} }
this.toolResult = `docker run --rm -v ${this.toolData.volumeNameOld}:/from -v ${this.toolData.volumeNameNew}:/to busybox cp -av /from/. /to`; this.toolResult = `docker run --rm -v ${this.toolData.volumeNameOld}:/from -v ${this.toolData.volumeNameNew}:/to busybox cp -av /from/. /to`;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,78 +1,174 @@
<template> <template>
<h2 class="tool-title">humans.txt generator</h2> <h2 class="tool-title">humans.txt generator</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label>Team <label
>Team
<button @click="addTeamGroup"></button> <button @click="addTeamGroup"></button>
</label> </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
<input class="input" v-model="field.value" v-on:keyup="result" placeholder="Value" type="text"> class="input"
v-model="field.key"
v-on:keyup="result"
placeholder="Key"
type="text"
/>
<input
class="input"
v-model="field.value"
v-on:keyup="result"
placeholder="Value"
type="text"
/>
<button @click="removeTeamField(groupIndex, fieldIndex)">🞩</button> <button @click="removeTeamField(groupIndex, fieldIndex)">🞩</button>
<button @click="moveTeamFieldUp(groupIndex, fieldIndex)" v-show="fieldIndex !== 0"></button> <button
<button @click="moveTeamFieldDown(groupIndex, fieldIndex)" v-show="fieldIndex !== group.length - 1"></button> @click="moveTeamFieldUp(groupIndex, fieldIndex)"
v-show="fieldIndex !== 0"
>
</button>
<button
@click="moveTeamFieldDown(groupIndex, fieldIndex)"
v-show="fieldIndex !== group.length - 1"
>
</button>
</div> </div>
<button @click="addTeamField(groupIndex)"></button> <button @click="addTeamField(groupIndex)"></button>
<button @click="removeTeamGroup(groupIndex)">🞩</button> <button @click="removeTeamGroup(groupIndex)">🞩</button>
<button @click="moveTeamGroupUp(groupIndex)" v-show="groupIndex !== 0"></button> <button @click="moveTeamGroupUp(groupIndex)" v-show="groupIndex !== 0">
<button @click="moveTeamGroupDown(groupIndex)" v-show="groupIndex !== toolData.team.length - 1"></button>
</button>
<button
@click="moveTeamGroupDown(groupIndex)"
v-show="groupIndex !== toolData.team.length - 1"
>
</button>
</div> </div>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label>Thanks <label
>Thanks
<button @click="addThanksGroup"></button> <button @click="addThanksGroup"></button>
</label> </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
<input class="input" v-model="field.value" v-on:keyup="result" placeholder="Value" type="text"> class="input"
v-model="field.key"
v-on:keyup="result"
placeholder="Key"
type="text"
/>
<input
class="input"
v-model="field.value"
v-on:keyup="result"
placeholder="Value"
type="text"
/>
<button @click="removeThanksField(groupIndex, fieldIndex)">🞩</button> <button @click="removeThanksField(groupIndex, fieldIndex)">🞩</button>
<button @click="moveThanksFieldUp(groupIndex, fieldIndex)" v-show="fieldIndex !== 0"></button> <button
<button @click="moveThanksFieldDown(groupIndex, fieldIndex)" v-show="fieldIndex !== group.length - 1"></button> @click="moveThanksFieldUp(groupIndex, fieldIndex)"
v-show="fieldIndex !== 0"
>
</button>
<button
@click="moveThanksFieldDown(groupIndex, fieldIndex)"
v-show="fieldIndex !== group.length - 1"
>
</button>
</div> </div>
<button @click="addThanksField(groupIndex)"></button> <button @click="addThanksField(groupIndex)"></button>
<button @click="removeThanksGroup(groupIndex)">🞩</button> <button @click="removeThanksGroup(groupIndex)">🞩</button>
<button @click="moveThanksGroupUp(groupIndex)" v-show="groupIndex !== 0"></button> <button @click="moveThanksGroupUp(groupIndex)" v-show="groupIndex !== 0">
<button @click="moveThanksGroupDown(groupIndex)" v-show="groupIndex !== toolData.thanks.length - 1"></button>
</button>
<button
@click="moveThanksGroupDown(groupIndex)"
v-show="groupIndex !== toolData.thanks.length - 1"
>
</button>
</div> </div>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label>Site info <label
>Site info
<button @click="addSite"></button> <button @click="addSite"></button>
</label> </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
<input class="input" v-model="info.value" v-on:keyup="result" placeholder="Value" type="text"> 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"
/>
<button @click="removeSiteField(fieldIndex)">🞩</button> <button @click="removeSiteField(fieldIndex)">🞩</button>
<button @click="moveSiteUp(fieldIndex)" v-show="fieldIndex !== 0"></button> <button @click="moveSiteUp(fieldIndex)" v-show="fieldIndex !== 0">
<button @click="moveSiteDown(fieldIndex)" v-show="fieldIndex !== toolData.site.length - 1"></button>
</button>
<button
@click="moveSiteDown(fieldIndex)"
v-show="fieldIndex !== toolData.site.length - 1"
>
</button>
</div> </div>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label>Import humans.txt <label
>Import humans.txt
<button @click="importHumans">Import</button> <button @click="importHumans">Import</button>
</label> </label>
<textarea v-model="toolData.importedHumansTxt" style="height: 250px"></textarea> <textarea
v-model="toolData.importedHumansTxt"
style="height: 250px"
></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -81,27 +177,17 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
team: [ team: [[{ key: "", value: "" }]],
[ thanks: [[{ key: "", value: "" }]],
{ key: "", value: "" } site: [{ key: "", value: "" }],
] importedHumansTxt: "",
],
thanks: [
[
{ key: "", value: "" }
]
],
site: [
{ key: "", value: "" }
],
importedHumansTxt: ""
}, },
toolResult: "" toolResult: "",
}; };
}, },
mounted() { mounted() {
@ -152,7 +238,8 @@ export default {
moveTeamFieldUp(groupIndex, fieldIndex) { moveTeamFieldUp(groupIndex, fieldIndex) {
if (fieldIndex > 0) { if (fieldIndex > 0) {
const temp = this.toolData.team[groupIndex][fieldIndex]; const temp = this.toolData.team[groupIndex][fieldIndex];
this.toolData.team[groupIndex][fieldIndex] = this.toolData.team[groupIndex][fieldIndex - 1]; this.toolData.team[groupIndex][fieldIndex] =
this.toolData.team[groupIndex][fieldIndex - 1];
this.toolData.team[groupIndex][fieldIndex - 1] = temp; this.toolData.team[groupIndex][fieldIndex - 1] = temp;
} }
@ -161,7 +248,8 @@ export default {
moveTeamFieldDown(groupIndex, fieldIndex) { moveTeamFieldDown(groupIndex, fieldIndex) {
if (fieldIndex < this.toolData.team[groupIndex].length - 1) { if (fieldIndex < this.toolData.team[groupIndex].length - 1) {
const temp = this.toolData.team[groupIndex][fieldIndex]; const temp = this.toolData.team[groupIndex][fieldIndex];
this.toolData.team[groupIndex][fieldIndex] = this.toolData.team[groupIndex][fieldIndex + 1]; this.toolData.team[groupIndex][fieldIndex] =
this.toolData.team[groupIndex][fieldIndex + 1];
this.toolData.team[groupIndex][fieldIndex + 1] = temp; this.toolData.team[groupIndex][fieldIndex + 1] = temp;
} }
@ -211,7 +299,8 @@ export default {
moveThanksFieldUp(groupIndex, fieldIndex) { moveThanksFieldUp(groupIndex, fieldIndex) {
if (fieldIndex > 0) { if (fieldIndex > 0) {
const temp = this.toolData.thanks[groupIndex][fieldIndex]; const temp = this.toolData.thanks[groupIndex][fieldIndex];
this.toolData.thanks[groupIndex][fieldIndex] = this.toolData.thanks[groupIndex][fieldIndex - 1]; this.toolData.thanks[groupIndex][fieldIndex] =
this.toolData.thanks[groupIndex][fieldIndex - 1];
this.toolData.thanks[groupIndex][fieldIndex - 1] = temp; this.toolData.thanks[groupIndex][fieldIndex - 1] = temp;
} }
@ -220,7 +309,8 @@ export default {
moveThanksFieldDown(groupIndex, fieldIndex) { moveThanksFieldDown(groupIndex, fieldIndex) {
if (fieldIndex < this.toolData.thanks[groupIndex].length - 1) { if (fieldIndex < this.toolData.thanks[groupIndex].length - 1) {
const temp = this.toolData.thanks[groupIndex][fieldIndex]; const temp = this.toolData.thanks[groupIndex][fieldIndex];
this.toolData.thanks[groupIndex][fieldIndex] = this.toolData.thanks[groupIndex][fieldIndex + 1]; this.toolData.thanks[groupIndex][fieldIndex] =
this.toolData.thanks[groupIndex][fieldIndex + 1];
this.toolData.thanks[groupIndex][fieldIndex + 1] = temp; this.toolData.thanks[groupIndex][fieldIndex + 1] = temp;
} }
@ -272,7 +362,9 @@ export default {
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";
@ -353,8 +445,8 @@ export default {
} }
this.toolResult = output; this.toolResult = output;
} },
} },
}; };
</script> </script>
@ -366,6 +458,4 @@ export default {
.humans-group:nth-child(odd) { .humans-group:nth-child(odd) {
background-color: #f7f7f7; background-color: #f7f7f7;
} }
</style> </style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Table to Markdown table</h2> <h2 class="tool-title">Table to Markdown table</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data (paste from excel)</label> <label for="data">Data (paste from excel)</label>
@ -20,16 +20,26 @@
<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 <input
for="transpose">transpose</label> id="transpose"
name="transpose"
v-model="toolData.transpose"
v-on:change="result"
type="checkbox"
/>
<label for="transpose">transpose</label>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -39,16 +49,16 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
selectedStyle: "", selectedStyle: "",
transpose: false transpose: false,
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -92,11 +102,9 @@ export default {
} }
this.toolResult = output; this.toolResult = output;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">Table to Mediawiki table</h2> <h2 class="tool-title">Table to Mediawiki table</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data (paste from excel)</label> <label for="data">Data (paste from excel)</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea> <textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -21,19 +25,19 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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++) {
@ -49,11 +53,9 @@ export default {
output += "|}"; output += "|}";
this.toolResult = output; this.toolResult = output;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,35 +1,63 @@
<template> <template>
<h2 class="tool-title">Dummy image</h2> <h2 class="tool-title">Dummy image</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<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" <input
type="number" style="width: 70px">px 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" <input
type="number" style="width: 70px">px 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>
<div class="input-group"> <div class="input-group">
<label for="result">Background colour</label> <label for="result">Background colour</label>
<input class="input" v-model="toolData.color_bg" v-on:change="result" type="color"> <input
class="input"
v-model="toolData.color_bg"
v-on:change="result"
type="color"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="result">Text colour</label> <label for="result">Text colour</label>
<input class="input" v-model="toolData.color_text" v-on:change="result" type="color"> <input
class="input"
v-model="toolData.color_text"
v-on:change="result"
type="color"
/>
</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">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" <canvas
style="max-width: 50vw; max-height: 50vh;"></canvas> ref="canvas"
:width="toolData.width"
:height="toolData.height"
style="max-width: 50vw; max-height: 50vh"
></canvas>
</div> </div>
</div> </div>
</template> </template>
@ -42,9 +70,9 @@ export default {
width: 500, width: 500,
height: 500, height: 500,
color_bg: "#000000", color_bg: "#000000",
color_text: "#ffffff" color_text: "#ffffff",
}, },
toolResult: "" toolResult: "",
}; };
}, },
mounted() { mounted() {
@ -68,11 +96,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"></style>
</style>

@ -1,24 +1,32 @@
<template> <template>
<h2 class="tool-title">IBAN generator</h2> <h2 class="tool-title">IBAN generator</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="style">Country</label> <label for="style">Country</label>
<div> <div>
<select id="style" v-model="toolData.country" v-on:change="result"> <select id="style" v-model="toolData.country" v-on:change="result">
<option value="">Select Country</option> <option value="">Select Country</option>
<option v-for="(structure, code) in ibanStructure" :key="code" :value="code"> <option
v-for="(structure, code) in ibanStructure"
:key="code"
:value="code"
>
{{ structure.country }} {{ structure.country }}
</option> </option>
</select> </select>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -34,8 +42,8 @@ function generateRandomNumber(length) {
} }
function generateRandomString(length) { function generateRandomString(length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result = ''; let result = "";
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length)); result += characters.charAt(Math.floor(Math.random() * characters.length));
} }
@ -45,26 +53,31 @@ function generateRandomString(length) {
function mod97(string) { function mod97(string) {
let checksum = string.slice(0, 2); let checksum = string.slice(0, 2);
for (let i = 2; i < string.length; i += 7) { for (let i = 2; i < string.length; i += 7) {
checksum = (parseInt(checksum + string.slice(i, i + 7), 10) % 97).toString().padStart(2, '0'); checksum = (parseInt(checksum + string.slice(i, i + 7), 10) % 97)
.toString()
.padStart(2, "0");
} }
return parseInt(checksum); return parseInt(checksum);
} }
function calculateCheckDigits(iban) { function calculateCheckDigits(iban) {
const rearranged = iban.slice(4) + iban.slice(0, 4); const rearranged = iban.slice(4) + iban.slice(0, 4);
const digits = rearranged.split('').map(char => { const digits = rearranged
if (char >= 'A' && char <= 'Z') { .split("")
return (char.charCodeAt(0) - 55).toString(); .map((char) => {
} if (char >= "A" && char <= "Z") {
return char; return (char.charCodeAt(0) - 55).toString();
}).join(''); }
return char;
})
.join("");
const remainder = mod97(digits); const remainder = mod97(digits);
return ('0' + (98 - remainder)).slice(-2); return ("0" + (98 - remainder)).slice(-2);
} }
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -74,9 +87,17 @@ export default {
toolResult: "", toolResult: "",
ibanStructure: { ibanStructure: {
AD: { country: "Andorra", length: 24, structure: "F04F04F12" }, AD: { country: "Andorra", length: 24, structure: "F04F04F12" },
AE: { country: "United Arab Emirates", length: 23, structure: "F03F16" }, AE: {
country: "United Arab Emirates",
length: 23,
structure: "F03F16",
},
AT: { country: "Austria", length: 20, structure: "F05F11" }, AT: { country: "Austria", length: 20, structure: "F05F11" },
BA: { country: "Bosnia and Herzegovina", length: 20, structure: "F03F03F08F02" }, BA: {
country: "Bosnia and Herzegovina",
length: 20,
structure: "F03F03F08F02",
},
BE: { country: "Belgium", length: 16, structure: "F03F07F02" }, BE: { country: "Belgium", length: 16, structure: "F03F07F02" },
BG: { country: "Bulgaria", length: 22, structure: "U04F04F02F08" }, BG: { country: "Bulgaria", length: 22, structure: "U04F04F02F08" },
BH: { country: "Bahrain", length: 22, structure: "U04F14" }, BH: { country: "Bahrain", length: 22, structure: "U04F14" },
@ -114,7 +135,11 @@ export default {
MK: { country: "North Macedonia", length: 19, structure: "F03U10F02" }, MK: { country: "North Macedonia", length: 19, structure: "F03U10F02" },
MR: { country: "Mauritania", length: 27, structure: "F05F05F11F02" }, MR: { country: "Mauritania", length: 27, structure: "F05F05F11F02" },
MT: { country: "Malta", length: 31, structure: "U04F05U18" }, MT: { country: "Malta", length: 31, structure: "U04F05U18" },
MU: { country: "Mauritius", length: 30, structure: "U04F02F02F12F03U03" }, MU: {
country: "Mauritius",
length: 30,
structure: "U04F02F02F12F03U03",
},
NL: { country: "Netherlands", length: 18, structure: "U04F10" }, NL: { country: "Netherlands", length: 18, structure: "U04F10" },
NO: { country: "Norway", length: 15, structure: "F04F06F01" }, NO: { country: "Norway", length: 15, structure: "F04F06F01" },
PK: { country: "Pakistan", length: 24, structure: "U04U16" }, PK: { country: "Pakistan", length: 24, structure: "U04U16" },
@ -137,17 +162,17 @@ export default {
methods: { methods: {
result() { result() {
if (!this.toolData.country.length) { if (!this.toolData.country.length) {
this.toolResult = 'Select a country'; this.toolResult = "Select a country";
return; return;
} }
const structure = this.ibanStructure[this.toolData.country]; const structure = this.ibanStructure[this.toolData.country];
if (!structure) { if (!structure) {
this.toolResult = 'Unsupported country'; this.toolResult = "Unsupported country";
return; return;
} }
let iban = this.toolData.country + '00'; // Add placeholder check digits let iban = this.toolData.country + "00"; // Add placeholder check digits
const parts = structure.structure.match(/([FU])(\d+)/g); const parts = structure.structure.match(/([FU])(\d+)/g);
for (const part of parts) { for (const part of parts) {
@ -155,10 +180,10 @@ export default {
const length = parseInt(part.slice(1)); const length = parseInt(part.slice(1));
switch (type) { switch (type) {
case 'F': case "F":
iban += generateRandomNumber(length); iban += generateRandomNumber(length);
break; break;
case 'U': case "U":
iban += generateRandomString(length); iban += generateRandomString(length);
break; break;
} }
@ -169,11 +194,9 @@ export default {
iban = iban.slice(0, 2) + checkDigits + iban.slice(4); iban = iban.slice(0, 2) + checkDigits + iban.slice(4);
this.toolResult = iban; this.toolResult = iban;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,34 +1,59 @@
<template> <template>
<h2 class="tool-title">QR code</h2> <h2 class="tool-title">QR code</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<!-- Type options --> <!-- Type options -->
<div class="input-group"> <div class="input-group">
<label for="text">Data:</label> <label for="text">Data:</label>
<textarea id="data" v-model="toolData.options.text" v-on:keyup="result"></textarea> <textarea
id="data"
v-model="toolData.options.text"
v-on:keyup="result"
></textarea>
</div> </div>
<!-- Basic options --> <!-- Basic options -->
<div class="input-group"> <div class="input-group">
<label for="width">Width:</label> <label for="width">Width:</label>
<input id="width" v-model.number="toolData.options.width" v-on:change="result" v-on:keyup="result" type="number"> <input
id="width"
v-model.number="toolData.options.width"
v-on:change="result"
v-on:keyup="result"
type="number"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="height">Height:</label> <label for="height">Height:</label>
<input id="height" v-model.number="toolData.options.height" v-on:change="result" v-on:keyup="result" type="number"> <input
id="height"
v-model.number="toolData.options.height"
v-on:change="result"
v-on:keyup="result"
type="number"
/>
</div> </div>
<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" <input
type="number"> 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">
<label for="correctLevel">Correct Level:</label> <label for="correctLevel">Correct Level:</label>
<div> <div>
<select id="correctLevel" v-model="toolData.options.correctLevel" v-on:change="result"> <select
id="correctLevel"
v-model="toolData.options.correctLevel"
v-on:change="result"
>
<option value="L">L</option> <option value="L">L</option>
<option value="M">M</option> <option value="M">M</option>
<option value="Q">Q</option> <option value="Q">Q</option>
@ -41,7 +66,13 @@
<div class="input-group"> <div class="input-group">
<label for="logoUpload">Logo Upload:</label> <label for="logoUpload">Logo Upload:</label>
<div> <div>
<input type="file" id="logoUpload" ref="logoUpload" @change="handleLogoUpload" accept="image/*"> <input
type="file"
id="logoUpload"
ref="logoUpload"
@change="handleLogoUpload"
accept="image/*"
/>
<button @click="removeLogo">🞩</button> <button @click="removeLogo">🞩</button>
</div> </div>
</div> </div>
@ -50,16 +81,29 @@
<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" <input
accept="image/*"> 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" <input
v-on:change="result" v-on:keyup="result" type="number"> 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>
<!-- <!--
@ -82,7 +126,7 @@
</div> </div>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label>Result</label> <label>Result</label>
@ -110,9 +154,9 @@ export default {
backgroundImage: "", backgroundImage: "",
backgroundImageAlpha: 1, backgroundImageAlpha: 1,
autoColor: true, autoColor: true,
drawer: "canvas" drawer: "canvas",
} },
} },
}; };
}, },
mounted() { mounted() {
@ -129,10 +173,10 @@ export default {
// 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);
@ -171,11 +215,9 @@ export default {
removeBackgroundImage() { removeBackgroundImage() {
this.toolData.options.backgroundImage = ""; this.toolData.options.backgroundImage = "";
this.result(); this.result();
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Go JSON to struct</h2> <h2 class="tool-title">Go JSON to struct</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -9,20 +9,36 @@
<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 <input
for="flatten">inline type definitions</label> 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 <input
for="omitempty">omitempty</label> id="omitempty"
name="omitempty"
v-model="toolData.omitempty"
v-on:change="result"
type="checkbox"
/>
<label for="omitempty">omitempty</label>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -30,7 +46,13 @@
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
// https://github.com/mholt/json-to-go // https://github.com/mholt/json-to-go
function jsonToGo(json, typename, flatten = true, example = false, allOmitempty = false) { function jsonToGo(
json,
typename,
flatten = true,
example = false,
allOmitempty = false
) {
let data; let data;
let scope; let scope;
let go = ""; let go = "";
@ -48,7 +70,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} catch (e) { } catch (e) {
return { return {
go: "", go: "",
error: e.message error: e.message,
}; };
} }
@ -58,12 +80,9 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
parseScope(scope); parseScope(scope);
return { return {
go: flatten go: flatten ? (go += accumulator) : go,
? go += accumulator
: go
}; };
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)) {
@ -72,23 +91,20 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
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;
} }
} }
const slice = flatten && ["struct", "slice"].includes(sliceType) const slice =
? `[]${parent}` flatten && ["struct", "slice"].includes(sliceType)
: `[]`; ? `[]${parent}`
: `[]`;
if (flatten && depth >= 2) if (flatten && depth >= 2) appender(slice);
appender(slice); else append(slice);
else
append(slice);
if (sliceType == "struct") { if (sliceType == "struct") {
const allFields = {}; const allFields = {};
@ -100,7 +116,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
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;
@ -115,7 +131,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
keyname = `${keyname}_${uuidv4()}`; keyname = `${keyname}_${uuidv4()}`;
allFields[keyname] = { allFields[keyname] = {
value: currentValue, value: currentValue,
count: 0 count: 0,
}; };
} }
} }
@ -126,9 +142,12 @@ 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;
@ -164,11 +183,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
function parseStruct(depth, innerTabs, scope, omitempty) { function parseStruct(depth, innerTabs, scope, omitempty) {
if (flatten) { if (flatten) {
stack.push( stack.push(depth >= 2 ? "\n" : "");
depth >= 2
? "\n"
: ""
);
} }
const seenTypeNames = []; const seenTypeNames = [];
@ -198,11 +213,11 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
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("}");
@ -218,25 +233,27 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
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 (
append("\" example:\"" + scope[keys[i]]); example &&
scope[keys[i]] !== "" &&
typeof scope[keys[i]] !== "object"
) {
append('" example:"' + scope[keys[i]]);
} }
append("\"`\n"); append('"`\n');
} }
indent(--tabs); indent(--tabs);
append("}"); append("}");
} }
if (flatten) if (flatten) 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) {
@ -244,8 +261,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} }
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) {
@ -274,7 +290,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
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]/gi, "");
if (!sanitized) { if (!sanitized) {
return "NAMING_FAILED"; return "NAMING_FAILED";
} }
@ -286,15 +302,20 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
// 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
function formatNumber(str) { function formatNumber(str) {
if (!str) if (!str) return "";
return ""; else if (str.match(/^\d+$/)) str = "Num" + str;
else if (str.match(/^\d+$/))
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_",
"4": "Four_", "5": "Five_", "6": "Six_", "7": "Seven_", 1: "One_",
"8": "Eight_", "9": "Nine_" 2: "Two_",
3: "Three_",
4: "Four_",
5: "Five_",
6: "Six_",
7: "Seven_",
8: "Eight_",
9: "Nine_",
}; };
str = numbers[str.charAt(0)] + str.substr(1); str = numbers[str.charAt(0)] + str.substr(1);
} }
@ -304,28 +325,22 @@ 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 return "int64";
else } else return "float64";
return "int64";
} else
return "float64";
case "boolean": case "boolean":
return "bool"; return "bool";
case "object": case "object":
if (Array.isArray(val)) if (Array.isArray(val)) return "slice";
return "slice";
return "struct"; return "struct";
default: default:
return "any"; return "any";
@ -334,14 +349,10 @@ 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") return typ1;
&& typ2.substr(0, 3) == "int") else if (typ1.substr(0, 3) == "int" && typ2.substr(0, 5) == "float")
return typ1;
else if (typ1.substr(0, 3) == "int"
&& typ2.substr(0, 5) == "float")
return typ2; return typ2;
else else return "any";
return "any";
} }
// Proper cases a string according to Go conventions // Proper cases a string according to Go conventions
@ -353,34 +364,73 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
// https://github.com/golang/lint/blob/5614ed5bae6fb75893070bdc0996a68765fdd275/lint.go#L771-L810 // https://github.com/golang/lint/blob/5614ed5bae6fb75893070bdc0996a68765fdd275/lint.go#L771-L810
const commonInitialisms = [ const commonInitialisms = [
"ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "ACL",
"HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA", "API",
"SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "UID", "UUID", "ASCII",
"URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS" "CPU",
"CSS",
"DNS",
"EOF",
"GUID",
"HTML",
"HTTP",
"HTTPS",
"ID",
"IP",
"JSON",
"LHS",
"QPS",
"RAM",
"RHS",
"RPC",
"SLA",
"SMTP",
"SQL",
"SSH",
"TCP",
"TLS",
"TTL",
"UDP",
"UI",
"UID",
"UUID",
"URI",
"URL",
"UTF8",
"VM",
"XML",
"XMPP",
"XSRF",
"XSS",
]; ];
return str.replace(/(^|[^a-zA-Z])([a-z]+)/g, function(unused, sep, frag) { return str
if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0) .replace(/(^|[^a-zA-Z])([a-z]+)/g, function (unused, sep, frag) {
return sep + frag.toUpperCase(); if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0)
else return sep + frag.toUpperCase();
return sep + frag[0].toUpperCase() + frag.substr(1).toLowerCase(); else return sep + frag[0].toUpperCase() + frag.substr(1).toLowerCase();
}).replace(/([A-Z])([a-z]+)/g, function(unused, sep, frag) { })
if (commonInitialisms.indexOf(sep + frag.toUpperCase()) >= 0) .replace(/([A-Z])([a-z]+)/g, function (unused, sep, frag) {
return (sep + frag).toUpperCase(); if (commonInitialisms.indexOf(sep + frag.toUpperCase()) >= 0)
else return (sep + frag).toUpperCase();
return sep + frag; else return sep + frag;
}); });
} }
function uuidv4() { function uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8); /[xy]/g,
return v.toString(16); function (c) {
}); var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
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) {
@ -394,8 +444,10 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
function compareObjects(objectA, objectB) { function compareObjects(objectA, objectB) {
const object = "[object Object]"; const object = "[object Object]";
return Object.prototype.toString.call(objectA) === object return (
&& Object.prototype.toString.call(objectB) === object; Object.prototype.toString.call(objectA) === object &&
Object.prototype.toString.call(objectB) === object
);
} }
function compareObjectKeys(itemAKeys, itemBKeys) { function compareObjectKeys(itemAKeys, itemBKeys) {
@ -403,16 +455,13 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
const lengthB = itemBKeys.length; const lengthB = itemBKeys.length;
// nothing to compare, probably identical // nothing to compare, probably identical
if (lengthA == 0 && lengthB == 0) if (lengthA == 0 && lengthB == 0) return true;
return true;
// duh // duh
if (lengthA != lengthB) if (lengthA != lengthB) return false;
return false;
for (let item of itemAKeys) { for (let item of itemAKeys) {
if (!itemBKeys.includes(item)) if (!itemBKeys.includes(item)) return false;
return false;
} }
return true; return true;
} }
@ -427,16 +476,16 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
flatten: false, flatten: false,
omitempty: false omitempty: false,
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -446,18 +495,22 @@ export default {
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"></style>
</style>

@ -1,27 +1,42 @@
<template> <template>
<h2 class="tool-title">SQL tables Go struct</h2> <h2 class="tool-title">SQL tables Go struct</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<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" <MonacoEditor
style="height: 500px"></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" <MonacoEditor
style="height: 500px"></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" <MonacoEditor
style="height: 500px"></MonacoEditor> name="dialects_oraclesql"
language="sql"
:value="toolData.dialects.oraclesql"
readonly="true"
style="height: 500px"
></MonacoEditor>
</div> </div>
</template> </template>
@ -30,7 +45,7 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -137,14 +152,12 @@ export default {
--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"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">JSON formatter</h2> <h2 class="tool-title">JSON formatter</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea> <textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -20,14 +24,14 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "" data: "",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -36,16 +40,18 @@ export default {
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"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">JSON Minifier</h2> <h2 class="tool-title">JSON Minifier</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="minify"></textarea> <textarea id="data" v-model="toolData.data" v-on:keyup="minify"></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -20,14 +24,14 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "" data: "",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -41,11 +45,9 @@ export default {
this.toolResult = "invalid syntax"; this.toolResult = "invalid syntax";
} }
} }
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">PHP array to Json</h2> <h2 class="tool-title">PHP array to Json</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -9,16 +9,26 @@
<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"> <input
id="minify_json"
name="minify_json"
v-model="toolData.minifyJson"
v-on:change="result"
type="checkbox"
/>
<label for="minify_json">minify json</label> <label for="minify_json">minify json</label>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -29,33 +39,32 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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
data: this.toolData.data, .post(`${config.APP_URL}/api/php/php_array_to_json.php`, {
minify_json: this.toolData.minifyJson ? true : false data: this.toolData.data,
}) minify_json: !!this.toolData.minifyJson,
})
.then((response) => { .then((response) => {
this.toolResult = response.data.data; this.toolResult = response.data.data;
Promise.resolve(response); Promise.resolve(response);
}); });
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">PHP serialize</h2> <h2 class="tool-title">PHP serialize</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -11,18 +11,36 @@
<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" <input
type="radio"> <label for="mode_serialize">serialize</label><br> id="mode_serialize"
<input id="mode_unserialize" value="unserialize" name="mode" v-model="toolData.mode" v-on:change="result" value="serialize"
type="radio"> <label for="mode_unserialize">unserialize</label><br> name="mode"
v-model="toolData.mode"
v-on:change="result"
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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -33,33 +51,32 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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
data: this.toolData.data, .post(`${config.APP_URL}/api/php/php_serialize.php`, {
mode: this.toolData.mode data: this.toolData.data,
}) mode: this.toolData.mode,
})
.then((response) => { .then((response) => {
this.toolResult = response.data; this.toolResult = response.data;
Promise.resolve(response); Promise.resolve(response);
}); });
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Str to PHP array</h2> <h2 class="tool-title">Str to PHP array</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -9,20 +9,36 @@
<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" <input
:disabled="toolData.dataIsJson"> 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"> <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> <label for="data_is_json">is json</label>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="php" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="php"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -33,35 +49,34 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
dataDelimiter: "", dataDelimiter: "",
dataIsJson: false dataIsJson: false,
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
result() { result() {
axios.post(`${config.APP_URL}/api/php/str_to_php_array.php`, { axios
data: this.toolData.data, .post(`${config.APP_URL}/api/php/str_to_php_array.php`, {
delimiter: this.toolData.dataDelimiter, data: this.toolData.data,
mode: this.toolData.dataIsJson ? "json" : null delimiter: this.toolData.dataDelimiter,
}) mode: this.toolData.dataIsJson ? "json" : null,
})
.then((response) => { .then((response) => {
this.toolResult = response.data; this.toolResult = response.data;
Promise.resolve(response); Promise.resolve(response);
}); });
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">SQL formatter</h2> <h2 class="tool-title">SQL formatter</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea> <textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="sql" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="sql"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -21,15 +25,15 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
minifyJson: "" minifyJson: "",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -46,20 +50,18 @@ export default {
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"></style>
</style>

@ -1,10 +1,16 @@
<template> <template>
<h2 class="tool-title">SQL split IN</h2> <h2 class="tool-title">SQL split IN</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="field_name">Field name</label> <label for="field_name">Field name</label>
<input id="field_name" v-model="toolData.fieldName" v-on:keyup="result" placeholder="D.ID" type="text"> <input
id="field_name"
v-model="toolData.fieldName"
v-on:keyup="result"
placeholder="D.ID"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
@ -14,32 +20,70 @@
<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" v-on:keyup="result" placeholder="," type="text"> <input
id="data_delimiter"
v-model="toolData.dataDelimiter"
v-on:keyup="result"
placeholder=","
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<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" <input
type="radio"> <label for="wrap_in_quotes_no">No</label><br> id="wrap_in_quotes_no"
<input id="wrap_in_quotes_single" value="single" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" value=""
v-on:change="result" type="radio"> <label for="wrap_in_quotes_single">Single</label><br> name="wrap_in_quotes"
<input id="wrap_in_quotes_double" value="double" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-model="toolData.wrapInQuotes"
v-on:change="result" type="radio"> <label for="wrap_in_quotes_double">Double</label> v-on:change="result"
type="radio"
/>
<label for="wrap_in_quotes_no">No</label><br />
<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>
<div class="input-group"> <div class="input-group">
<label for="chunk_by">Chunk by</label> <label for="chunk_by">Chunk by</label>
<input id="chunk_by" v-model="toolData.chunkBy" v-on:keyup="result" placeholder="900" min="1" type="number"> <input
id="chunk_by"
v-model="toolData.chunkBy"
v-on:keyup="result"
placeholder="900"
min="1"
type="number"
/>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="sql" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="sql"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -57,7 +101,7 @@ function arrayChunk(arr, chunkSize) {
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -66,15 +110,16 @@ export default {
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(
.split(this.toolData.dataDelimiter ? this.toolData.dataDelimiter : "\n"); 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];
@ -84,7 +129,7 @@ export default {
value = "'" + value.replace("'", "\\'") + "'"; value = "'" + value.replace("'", "\\'") + "'";
break; break;
case "double": case "double":
value = "\"" + value.replace("\"", "\\\"") + "\""; value = '"' + value.replace('"', '\\"') + '"';
break; break;
} }
@ -100,12 +145,15 @@ export default {
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"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Fix ru-en keyboard</h2> <h2 class="tool-title">Fix ru-en keyboard</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -11,18 +11,36 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="keyboard_mode_en_ru" value="en-ru" name="keyboard_mode" v-model="toolData.keyboardMode" <input
v-on:change="result" type="radio"> <label for="keyboard_mode_en_ru">en -> ru</label><br> id="keyboard_mode_en_ru"
<input id="keyboard_mode_ru_en" value="ru-en" name="keyboard_mode" v-model="toolData.keyboardMode" value="en-ru"
v-on:change="result" type="radio"> <label for="keyboard_mode_ru_en">ru -> en</label> 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_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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -32,19 +50,21 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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":
"ru-en": "ёЁ!\"№;%:?йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ," "`~!@#$%^&qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?",
"ru-en":
'ёЁ!"№;%:?йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,',
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -52,7 +72,10 @@ export default {
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]);
@ -62,11 +85,9 @@ export default {
} }
this.toolResult = data.join(""); this.toolResult = data.join("");
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Str length</h2> <h2 class="tool-title">Str length</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -9,24 +9,57 @@
<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" 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" <input
v-on:change="result" :disabled="toolData.dataDelimiter.length" type="radio"> <label id="count_mode_characters"
for="count_mode_characters">characters</label><br> value="characters"
<input id="count_mode_words" value="words" name="count_mode" v-model="toolData.countMode" v-on:change="result" name="count_mode"
:disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_words">words</label><br> v-model="toolData.countMode"
<input id="count_mode_lines" value="lines" name="count_mode" v-model="toolData.countMode" v-on:change="result" v-on:change="result"
:disabled="toolData.dataDelimiter.length" type="radio"> <label for="count_mode_lines">lines</label> :disabled="toolData.dataDelimiter.length"
type="radio"
/>
<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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -35,16 +68,16 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
dataDelimiter: "", dataDelimiter: "",
countMode: "characters" countMode: "characters",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -52,7 +85,9 @@ export default {
if (!this.toolData.data.length) { if (!this.toolData.data.length) {
this.toolResult = 0; this.toolResult = 0;
} else if (this.toolData.dataDelimiter.length) { } else if (this.toolData.dataDelimiter.length) {
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":
@ -66,11 +101,9 @@ export default {
break; break;
} }
} }
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">Str to NATO alphabet</h2> <h2 class="tool-title">Str to NATO alphabet</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<input id="data" v-model="toolData.data" v-on:keyup="result" type="text"> <input id="data" v-model="toolData.data" v-on:keyup="result" type="text" />
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="php" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="php"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -22,34 +26,55 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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",
"E": "Echo", "F": "Foxtrot", "G": "Golf", "H": "Hotel", B: "Bravo",
"I": "India", "J": "Juliett", "K": "Kilo", "L": "Lima", C: "Charlie",
"M": "Mike", "N": "November", "O": "Oscar", "P": "Papa", D: "Delta",
"Q": "Quebec", "R": "Romeo", "S": "Sierra", "T": "Tango", E: "Echo",
"U": "Uniform", "V": "Victor", "W": "Whiskey", "X": "X-ray", F: "Foxtrot",
"Y": "Yankee", "Z": "Zulu" G: "Golf",
H: "Hotel",
I: "India",
J: "Juliett",
K: "Kilo",
L: "Lima",
M: "Mike",
N: "November",
O: "Oscar",
P: "Papa",
Q: "Quebec",
R: "Romeo",
S: "Sierra",
T: "Tango",
U: "Uniform",
V: "Victor",
W: "Whiskey",
X: "X-ray",
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"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">Str numeronym</h2> <h2 class="tool-title">Str numeronym</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<input id="data" v-model="toolData.data" v-on:keyup="result" type="text"> <input id="data" v-model="toolData.data" v-on:keyup="result" type="text" />
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -21,14 +25,14 @@ import { unproxy } from "../../utils/unproxy";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "" data: "",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -45,11 +49,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"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Str pad</h2> <h2 class="tool-title">Str pad</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -9,21 +9,49 @@
<div class="input-group"> <div class="input-group">
<label for="data">Symbol</label> <label for="data">Symbol</label>
<input id="data" class="input" v-model="toolData.padSymbol" v-on:keyup="result" placeholder="0" type="text"> <input
id="data"
class="input"
v-model="toolData.padSymbol"
v-on:keyup="result"
placeholder="0"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="data">Pad count / Fixed length</label> <label for="data">Pad count / Fixed length</label>
<input id="data" class="input" v-model="toolData.padCount" v-on:keyup="result" placeholder="0" type="text"> <input
id="data"
class="input"
v-model="toolData.padCount"
v-on:keyup="result"
placeholder="0"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<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" <input
type="radio"> <label for="pad_pos_begin">begin</label><br> id="pad_pos_begin"
<input id="pad_pos_end" value="end" name="pad_pos" v-model="toolData.padPos" v-on:change="result" type="radio"> 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_end"
value="end"
name="pad_pos"
v-model="toolData.padPos"
v-on:change="result"
type="radio"
/>
<label for="pad_pos_end">end</label> <label for="pad_pos_end">end</label>
</div> </div>
</div> </div>
@ -32,18 +60,36 @@
<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" <input
type="radio"> <label for="pad_by_repeat_symbol">repeat symbol</label><br> id="pad_by_repeat_symbol"
<input id="pad_by_string_length" value="string_length" name="pad_by" v-model="toolData.padBy" v-on:change="result" value="repeat_symbol"
type="radio"> <label for="pad_by_string_length">to string length</label> 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_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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -52,7 +98,7 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -61,9 +107,9 @@ export default {
padSymbol: "0", padSymbol: "0",
padCount: 3, padCount: 3,
padPos: "begin", padPos: "begin",
padBy: "string_length" padBy: "string_length",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -81,7 +127,9 @@ export default {
return line + padding; return line + padding;
} }
} 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;
@ -92,11 +140,9 @@ export default {
}); });
this.toolResult = paddedLines.join("\n"); this.toolResult = paddedLines.join("\n");
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,17 +1,21 @@
<template> <template>
<h2 class="tool-title">Str remove duplicate lines</h2> <h2 class="tool-title">Str remove duplicate lines</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea> <textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -24,24 +28,25 @@ function arrayUnique(value, index, array) {
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Str sort lines</h2> <h2 class="tool-title">Str sort lines</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -11,25 +11,64 @@
<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" <input
type="radio"> <label for="sort_mode_alpha">alphabetically</label><br> id="sort_mode_alpha"
<input id="sort_mode_numerically" value="numerically" name="sort_mode" v-model="toolData.sortMode" value="alpha"
v-on:change="result" type="radio"> <label for="sort_mode_numerically">numerically</label><br> name="sort_mode"
<input id="sort_mode_by_length" value="by_length" name="sort_mode" v-model="toolData.sortMode" v-model="toolData.sortMode"
v-on:change="result" type="radio"> <label for="sort_mode_by_length">by length</label><br> v-on:change="result"
<input id="sort_mode_random" value="random" name="sort_mode" v-model="toolData.sortMode" v-on:change="result" type="radio"
type="radio"> <label for="sort_mode_random">random</label><br> />
<br> <label for="sort_mode_alpha">alphabetically</label><br />
<input id="sort_mode_reverse" value="random" name="sort_mode_reverse" v-model="toolData.sortModeReverse" <input
v-on:change="result" type="checkbox"> <label for="sort_mode_reverse">reverse</label> 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 />
<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 />
<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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -38,16 +77,16 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
sortMode: "alpha", sortMode: "alpha",
sortModeReverse: false sortModeReverse: false,
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -57,25 +96,25 @@ export default {
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() - 0.5;
}); });
break; break;
} }
@ -85,11 +124,9 @@ export default {
} }
this.toolResult = result.join("\n"); this.toolResult = result.join("\n");
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">Str to lower/upper</h2> <h2 class="tool-title">Str to lower/upper</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -11,18 +11,36 @@
<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" <input
type="radio"> <label for="case_mode_lower">to lower</label><br> id="case_mode_lower"
<input id="case_mode_upper" value="upper" name="case_mode" v-model="toolData.caseMode" v-on:change="result" value="lower"
type="radio"> <label for="case_mode_upper">to upper</label> 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_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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -31,15 +49,15 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
caseMode: "upper" caseMode: "upper",
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -52,11 +70,9 @@ export default {
this.toolResult = this.toolData.data.toLocaleUpperCase(); this.toolResult = this.toolData.data.toLocaleUpperCase();
break; break;
} }
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">URL encode/decode</h2> <h2 class="tool-title">URL encode/decode</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
@ -11,18 +11,36 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="encode_mode_encode" value="encode" name="encode_mode" v-model="toolData.encodeMode" <input
v-on:change="result" type="radio"> <label for="encode_mode_encode">encode</label><br> id="encode_mode_encode"
<input id="encode_mode_decode" value="decode" name="encode_mode" v-model="toolData.encodeMode" value="encode"
v-on:change="result" type="radio"> <label for="encode_mode_decode">decode</label> 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_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>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -31,32 +49,36 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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"></style>
</style>

@ -1,22 +1,31 @@
<template> <template>
<h2 class="tool-title">URL query viewer</h2> <h2 class="tool-title">URL query viewer</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<input id="data" v-model="toolData.data" v-on:keyup="result" type="url"> <input id="data" v-model="toolData.data" v-on:keyup="result" type="url" />
</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">Result</label> <label for="result">Result</label>
<table> <table>
<tbody> <tbody>
<tr v-for="row in toolData.queryParts"> <tr v-for="row in toolData.queryParts">
<td><input :value="row.key" style="width: 100%;" type="text" readonly></td> <td>
<td><input :value="row.value" style="width: 100%;" type="text" readonly></td> <input :value="row.key" style="width: 100%" type="text" readonly />
</tr> </td>
<td>
<input
:value="row.value"
style="width: 100%"
type="text"
readonly
/>
</td>
</tr>
</tbody> </tbody>
</table> </table>
<p v-if="!toolData.queryParts.length">invalid url</p> <p v-if="!toolData.queryParts.length">invalid url</p>
@ -41,9 +50,9 @@ export default {
return { return {
toolData: { toolData: {
data: "", data: "",
queryParts: [] queryParts: [],
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -63,15 +72,14 @@ 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>

@ -1,17 +1,28 @@
<template> <template>
<h2 class="tool-title">Explain crontab</h2> <h2 class="tool-title">Explain crontab</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="data">Data</label> <label for="data">Data</label>
<input id="data" class="input" v-model="toolData.data" v-on:keyup="result" placeholder="* * * * *" type="text"> <input
id="data"
class="input"
v-model="toolData.data"
v-on:keyup="result"
placeholder="* * * * *"
type="text"
/>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -21,20 +32,20 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
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,16 +53,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"></style>
</style>

@ -1,6 +1,6 @@
<template> <template>
<h2 class="tool-title">File base64 encode/decode</h2> <h2 class="tool-title">File base64 encode/decode</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group" v-if="toolData.base64Mode === 'encode'"> <div class="input-group" v-if="toolData.base64Mode === 'encode'">
<label for="data">Data</label> <label for="data">Data</label>
@ -15,8 +15,14 @@
<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 <input
for="strip_mime">strip mime</label> 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>
@ -24,18 +30,34 @@
<label>Mode</label> <label>Mode</label>
<div> <div>
<input id="base64_mode_encode" value="encode" name="base64_mode" v-model="toolData.base64Mode" type="radio"> <input
<label for="base64_mode_encode">file -> base64</label><br> id="base64_mode_encode"
<input id="base64_mode_decode" value="decode" name="base64_mode" v-model="toolData.base64Mode" type="radio"> value="encode"
name="base64_mode"
v-model="toolData.base64Mode"
type="radio"
/>
<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> <label for="base64_mode_decode">base64 -> file</label>
</div> </div>
</div> </div>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group" v-if="toolData.base64Mode === 'encode'"> <div class="input-group" v-if="toolData.base64Mode === 'encode'">
<label for="result">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
<div class="input-group" v-if="toolData.base64Mode === 'decode'"> <div class="input-group" v-if="toolData.base64Mode === 'decode'">
<label for="result">Result</label> <label for="result">Result</label>
@ -48,16 +70,16 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
toolData: { toolData: {
data: "", data: "",
base64Mode: "encode", base64Mode: "encode",
stripMime: true stripMime: true,
}, },
toolResult: "" toolResult: "",
}; };
}, },
methods: { methods: {
@ -78,7 +100,9 @@ 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
@ -94,11 +118,9 @@ export default {
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"></style>
</style>

@ -1,15 +1,27 @@
<template> <template>
<h2 class="tool-title">.htaccess User Entry Generator</h2> <h2 class="tool-title">.htaccess User Entry Generator</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="username">Username</label> <label for="username">Username</label>
<input id="username" class="input" v-model="toolData.username" v-on:keyup="result" type="text"> <input
id="username"
class="input"
v-model="toolData.username"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="password">Password</label> <label for="password">Password</label>
<input id="password" class="input" v-model="toolData.password" v-on:keyup="result" type="text"> <input
id="password"
class="input"
v-model="toolData.password"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
@ -24,23 +36,27 @@
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
<script> <script>
import MonacoEditor from "@/components/MonacoEditor.vue"; import MonacoEditor from "@/components/MonacoEditor.vue";
import bcrypt from 'bcryptjs'; import bcrypt from "bcryptjs";
import md5 from 'md5'; import md5 from "md5";
import sha1 from 'sha1'; import sha1 from "sha1";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -58,30 +74,28 @@ export default {
methods: { methods: {
result() { result() {
if (!(this.toolData.username && this.toolData.password)) { if (!(this.toolData.username && this.toolData.password)) {
this.toolResult = ''; this.toolResult = "";
return; return;
} }
let encryptedPassword = ''; let encryptedPassword = "";
switch (this.toolData.algorithm) { switch (this.toolData.algorithm) {
case 'MD5': case "MD5":
encryptedPassword = md5(this.toolData.password); encryptedPassword = md5(this.toolData.password);
break; break;
case 'SHA1': case "SHA1":
encryptedPassword = sha1(this.toolData.password); encryptedPassword = sha1(this.toolData.password);
break; break;
case 'BCRYPT': case "BCRYPT":
encryptedPassword = bcrypt.hashSync(this.toolData.password, 10); // 10 salt rounds encryptedPassword = bcrypt.hashSync(this.toolData.password, 10); // 10 salt rounds
break; break;
} }
this.toolResult = `${this.toolData.username}:${encryptedPassword}`; this.toolResult = `${this.toolData.username}:${encryptedPassword}`;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,39 +1,73 @@
<template> <template>
<h2 class="tool-title">Sed Generator</h2> <h2 class="tool-title">Sed Generator</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="search">Search</label> <label for="search">Search</label>
<input id="search" class="input" v-model="toolData.search" v-on:keyup="result" type="text"> <input
id="search"
class="input"
v-model="toolData.search"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="replace">Replace</label> <label for="replace">Replace</label>
<input id="replace" class="input" v-model="toolData.replace" v-on:keyup="result" type="text"> <input
id="replace"
class="input"
v-model="toolData.replace"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="delimiter">Delimiter</label> <label for="delimiter">Delimiter</label>
<input id="delimiter" class="input" maxlength="1" v-model="toolData.delimiter" v-on:keyup="result" type="text"> <input
id="delimiter"
class="input"
maxlength="1"
v-model="toolData.delimiter"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<label for="filename">Filename</label> <label for="filename">Filename</label>
<input id="filename" class="input" v-model="toolData.filename" v-on:keyup="result" type="text"> <input
id="filename"
class="input"
v-model="toolData.filename"
v-on:keyup="result"
type="text"
/>
</div> </div>
<div class="input-group"> <div class="input-group">
<div> <div>
<input id="do_replace" type="checkbox" v-model="toolData.doReplace" v-on:change="result"> <input
id="do_replace"
type="checkbox"
v-model="toolData.doReplace"
v-on:change="result"
/>
<label for="do_replace"> replace in file</label> <label for="do_replace"> replace in file</label>
</div> </div>
</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">Result</label> <label for="result">Result</label>
<MonacoEditor name="result" language="bash" :value="toolResult"></MonacoEditor> <MonacoEditor
name="result"
language="bash"
:value="toolResult"
></MonacoEditor>
</div> </div>
</template> </template>
@ -42,7 +76,7 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default { export default {
components: { components: {
MonacoEditor MonacoEditor,
}, },
data() { data() {
return { return {
@ -61,9 +95,15 @@ export default {
}, },
methods: { methods: {
result() { result() {
if (!(this.toolData.search && this.toolData.replace && this.toolData.delimiter)) { if (
this.toolResult = ''; !(
return this.toolData.search &&
this.toolData.replace &&
this.toolData.delimiter
)
) {
this.toolResult = "";
return;
} }
let command = `sed`; let command = `sed`;
@ -72,8 +112,14 @@ export default {
} }
// Escape delimiter // Escape delimiter
const search = this.toolData.search.replace(new RegExp(`\\${this.toolData.delimiter}`, 'g'), `\\${this.toolData.delimiter}`); const search = this.toolData.search.replace(
const replace = this.toolData.replace.replace(new RegExp(`\\${this.toolData.delimiter}`, 'g'), `\\${this.toolData.delimiter}`); new RegExp(`\\${this.toolData.delimiter}`, "g"),
`\\${this.toolData.delimiter}`
);
const replace = this.toolData.replace.replace(
new RegExp(`\\${this.toolData.delimiter}`, "g"),
`\\${this.toolData.delimiter}`
);
command += ` 's${this.toolData.delimiter}${search}${this.toolData.delimiter}${replace}${this.toolData.delimiter}g' ${this.toolData.filename}`; command += ` 's${this.toolData.delimiter}${search}${this.toolData.delimiter}${replace}${this.toolData.delimiter}g' ${this.toolData.filename}`;
this.toolResult = command; this.toolResult = command;
@ -82,6 +128,4 @@ export default {
}; };
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

@ -1,33 +1,38 @@
<template> <template>
<h2 class="tool-title">Unix timestamp</h2> <h2 class="tool-title">Unix timestamp</h2>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<table> <table>
<thead> <thead>
<tr> <tr>
<th>Format</th> <th>Format</th>
<th>Date & Time</th> <th>Date & Time</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<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> <td>
<button @click="copyTimestamp(value)">📋</button> <button @click="copyTimestamp(value)">📋</button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<hr class="mt-5 mb-5"> <hr class="mt-5 mb-5" />
<div class="input-group"> <div class="input-group">
<label for="inputTimestamp">Enter timestamp</label> <label for="inputTimestamp">Enter timestamp</label>
<div> <div>
<input id="inputTimestamp" type="number" v-model="toolData.inputTimestamp" :placeholder="currentTimestamp"> <input
id="inputTimestamp"
type="number"
v-model="toolData.inputTimestamp"
:placeholder="currentTimestamp"
/>
<button @click="convertFromUnix">Convert </button> <button @click="convertFromUnix">Convert </button>
</div> </div>
</div> </div>
@ -38,28 +43,28 @@
<div> <div>
<table class="table-date-and-time"> <table class="table-date-and-time">
<thead> <thead>
<tr> <tr>
<th>Year</th> <th>Year</th>
<th>Month</th> <th>Month</th>
<th>Day</th> <th>Day</th>
<th>Hour (24)</th> <th>Hour (24)</th>
<th>Minute</th> <th>Minute</th>
<th>Second</th> <th>Second</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><input type="number" v-model="toolData.inputYear"></td> <td><input type="number" v-model="toolData.inputYear" /></td>
<td><input type="number" v-model="toolData.inputMonth"></td> <td><input type="number" v-model="toolData.inputMonth" /></td>
<td><input type="number" v-model="toolData.inputDay"></td> <td><input type="number" v-model="toolData.inputDay" /></td>
<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> <td>
<button @click="convertToUnix">Convert </button> <button @click="convertToUnix">Convert </button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
@ -79,10 +84,10 @@ export default {
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() {
@ -90,7 +95,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'),
@ -103,8 +108,10 @@ export default {
// '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()
"YYYY/DD/MM HH:MM:SS AM/PM": moment().format("YYYY/MM/DD HH:mm:ss A") .toISOString()
.replaceAll(/[ZT]|(\.[0-9]{3})/g, " "),
"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'),
}; };
}; };
@ -114,7 +121,9 @@ export default {
}, },
methods: { methods: {
convertFromUnix() { convertFromUnix() {
let timestamp = this.toolData.inputTimestamp.length ? this.toolData.inputTimestamp : this.currentTimestamp; let timestamp = this.toolData.inputTimestamp.length
? this.toolData.inputTimestamp
: this.currentTimestamp;
const date = moment.unix(timestamp); const date = moment.unix(timestamp);
@ -124,7 +133,6 @@ export default {
this.toolData.inputHour = date.hour(); this.toolData.inputHour = date.hour();
this.toolData.inputMinute = date.minute(); this.toolData.inputMinute = date.minute();
this.toolData.inputSecond = date.second(); this.toolData.inputSecond = date.second();
}, },
convertToUnix() { convertToUnix() {
const date = moment({ const date = moment({
@ -133,21 +141,22 @@ export default {
day: this.toolData.inputDay, day: this.toolData.inputDay,
hour: this.toolData.inputHour, hour: this.toolData.inputHour,
minute: this.toolData.inputMinute, minute: this.toolData.inputMinute,
second: this.toolData.inputSecond second: this.toolData.inputSecond,
}); });
this.toolData.inputTimestamp = date.unix(); this.toolData.inputTimestamp = date.unix();
}, },
copyTimestamp(text) { copyTimestamp(text) {
navigator.clipboard.writeText(text) navigator.clipboard
.writeText(text)
.then(() => { .then(() => {
// console.log('Timestamp copied to clipboard!'); // console.log('Timestamp copied to clipboard!');
}) })
.catch(err => { .catch((err) => {
// console.error('Failed to copy: ', err); // console.error('Failed to copy: ', err);
}); });
} },
} },
}; };
</script> </script>

@ -1,17 +1,17 @@
module.exports = { module.exports = {
content: [ content: [
"./index.html", "./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}", "./src/**/*.{vue,js,ts,jsx,tsx}",
// "./node_modules/flowbite/**/*.js", // "./node_modules/flowbite/**/*.js",
], ],
theme: { theme: {
extend: { extend: {
zIndex: { zIndex: {
'500': '500', 500: "500",
} },
}, },
}, },
plugins: [ plugins: [
// require('flowbite/plugin') // require('flowbite/plugin')
], ],
} };

@ -1,29 +1,29 @@
import {fileURLToPath, URL} from 'url' import { fileURLToPath, URL } from "url";
import {defineConfig} from 'vite' import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue' import vue from "@vitejs/plugin-vue";
function pathTo(path) { function pathTo(path) {
return fileURLToPath(new URL(path, import.meta.url)); return fileURLToPath(new URL(path, import.meta.url));
} }
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
'@': pathTo('./src', import.meta.url), "@": pathTo("./src", import.meta.url),
'@node_modules': pathTo('./node_modules'), "@node_modules": pathTo("./node_modules"),
} },
}, },
server: { server: {
host: true, host: true,
port: 3000, port: 3000,
cors: false, cors: false,
}, },
preview: { preview: {
host: true, host: true,
port: 3000, port: 3000,
cors: false, cors: false,
} },
}) });