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
View File

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

View File

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

View File

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

View File

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

View File

@ -1,71 +1,90 @@
<template>
<div
class="w-full flex flex-col sm:flex-row flex-grow"
:class="{ 'sidebar-toggle': sidebarToggle }">
<aside
class="hidden md:block h-screen overflow-y-auto no-scrollbar border-r">
<Sidebar/>
</aside>
<div
class="w-full flex flex-col sm:flex-row flex-grow"
:class="{ 'sidebar-toggle': sidebarToggle }"
>
<aside
class="hidden md:block h-screen overflow-y-auto no-scrollbar border-r"
>
<Sidebar />
</aside>
<main role="main" class="w-full h-full flex-grow overflow-auto p-3">
<RouterView/>
</main>
<main role="main" class="w-full h-full flex-grow overflow-auto p-3">
<RouterView />
</main>
<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>
</button>
</div>
<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>
</button>
</div>
</template>
<script>
import { RouterView } from 'vue-router'
import Sidebar from '@/components/Sidebar.vue';
import { RouterView } from "vue-router";
import Sidebar from "@/components/Sidebar.vue";
export default {
components: {
Sidebar,
RouterView,
},
data() {
return {
sidebarToggle: false,
};
},
methods: {
toggleSidebar() {
this.sidebarToggle = !this.sidebarToggle;
components: {
Sidebar,
RouterView,
},
data() {
return {
sidebarToggle: false,
};
},
methods: {
toggleSidebar() {
this.sidebarToggle = !this.sidebarToggle;
this.emitter.emit('sidebar.toggle');
},
},
}
this.emitter.emit("sidebar.toggle");
},
},
};
</script>
<style lang="scss">
aside {
width: 480px;
width: 480px;
}
@media (max-width: 768px) {
.sidebar-toggle {
aside {
display: block;
width: 100%;
max-width: initial;
}
.sidebar-toggle {
aside {
display: block;
width: 100%;
max-width: initial;
}
main {
display: none;
}
main {
display: none;
}
&-btn {
right: 10px;
bottom: 10px;
position: fixed;
z-index: 1000;
background-color: white;
border-radius: 5px;
padding: 2px;
}
}
&-btn {
right: 10px;
bottom: 10px;
position: fixed;
z-index: 1000;
background-color: white;
border-radius: 5px;
padding: 2px;
}
}
}
</style>
</style>

View File

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

View File

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

View File

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

View File

@ -9,57 +9,57 @@ const router = createRouter({
{
path: "/",
name: "home",
component: () => import("../views/HomeView.vue")
component: () => import("../views/HomeView.vue"),
},
{
path: "/explain_crontab",
name: "explain_crontab",
component: () => import("../views/unix/ExplainCrontab.vue")
component: () => import("../views/unix/ExplainCrontab.vue"),
},
{
path: "/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",
name: "table_to_mediawiki_table",
component: () => import("../views/general/TableToMediawikiTable.vue")
component: () => import("../views/general/TableToMediawikiTable.vue"),
},
{
path: "/dummy_image",
name: "dummy_image",
component: () => import("../views/generators/DummyImage.vue")
component: () => import("../views/generators/DummyImage.vue"),
},
{
path: "/humans_txt",
name: "humans_txt",
component: () => import("../views/general/HumansTxt.vue")
component: () => import("../views/general/HumansTxt.vue"),
},
{
path: "/qr_code",
name: "qr_code",
component: () => import("../views/generators/QRCode.vue")
component: () => import("../views/generators/QRCode.vue"),
},
{
path: "/unix_timestamp",
name: "unix_timestamp",
component: () => import("../views/unix/UnixTimestamp.vue")
component: () => import("../views/unix/UnixTimestamp.vue"),
},
{
path: "/file_base64_encode_decode",
name: "file_base64_encode_decode",
component: () => import("../views/unix/FileBase64EncodeDecode.vue")
component: () => import("../views/unix/FileBase64EncodeDecode.vue"),
},
{
path: "/sed_generator",
name: "sed_generator",
component: () => import("../views/unix/SedGenerator.vue")
component: () => import("../views/unix/SedGenerator.vue"),
},
{
path: "/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",
name: "str_length",
component: () => import("../views/strings/Length.vue")
component: () => import("../views/strings/Length.vue"),
},
{
path: "/str_sort_lines",
name: "str_sort_lines",
component: () => import("../views/strings/SortLines.vue")
component: () => import("../views/strings/SortLines.vue"),
},
{
path: "/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",
name: "str_remove_duplicate_lines",
component: () => import("../views/strings/RemoveDuplicateLines.vue")
component: () => import("../views/strings/RemoveDuplicateLines.vue"),
},
{
path: "/str_pad",
name: "str_pad",
component: () => import("../views/strings/Pad.vue")
component: () => import("../views/strings/Pad.vue"),
},
{
path: "/str_numeronym",
name: "str_numeronym",
component: () => import("../views/strings/Numeronym.vue")
component: () => import("../views/strings/Numeronym.vue"),
},
{
path: "/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",
name: "url_encode_decode",
component: () => import("../views/strings/UrlEncodeDecode.vue")
component: () => import("../views/strings/UrlEncodeDecode.vue"),
},
{
path: "/url_query_viewer",
name: "url_query_viewer",
component: () => import("../views/strings/UrlQueryViewer.vue")
component: () => import("../views/strings/UrlQueryViewer.vue"),
},
{
path: "/fix_ru_en_keyboard",
name: "fix_ru_en_keyboard",
component: () => import("../views/strings/FixRuEnKeyboard.vue")
component: () => import("../views/strings/FixRuEnKeyboard.vue"),
},
{
path: "/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",
name: "str_to_php_array",
component: () => import("../views/php/StrToPHPArray.vue")
component: () => import("../views/php/StrToPHPArray.vue"),
},
{
path: "/php_array_to_json",
name: "php_array_to_json",
component: () => import("../views/php/PHPArrayToJson.vue")
component: () => import("../views/php/PHPArrayToJson.vue"),
},
{
path: "/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",
name: "json_formatter",
component: () => import("../views/json/JSONFormatter.vue")
component: () => import("../views/json/JSONFormatter.vue"),
},
{
path: "/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",
name: "go_json_to_struct",
component: () => import("../views/go/JSONToStruct.vue")
component: () => import("../views/go/JSONToStruct.vue"),
},
{
path: "/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",
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",
name: "sql_split_in",
component: () => import("../views/sql/SplitInView.vue")
component: () => import("../views/sql/SplitInView.vue"),
},
{
path: "/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;

View File

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

View File

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

View File

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

View File

@ -1,7 +1,13 @@
<template>
<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 v-for="(category, categoryName) in tools" :key="categoryName" class="bg-white rounded-lg shadow-md p-4">
<div
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>
<div class="max-h-80 overflow-y-auto">
<ul class="space-y-2">
@ -19,22 +25,43 @@
</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-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">
<img src="https://gist.stuzer.link/assets/opengist-85b89b9c.svg" alt="Gist Icon" class="w-12 h-12 mr-4">
<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"
>
<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>
</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">
<img src="https://cyberchef.tools.stuzer.link/images/cyberchef-128x128.png" alt="Cyberchef Icon" class="w-12 h-12 mr-4">
<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"
>
<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>
</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">
<img src="https://pdf.tools.stuzer.link/favicon.svg" alt="PDF Tools Icon" class="w-12 h-12 mr-4">
<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"
>
<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>
</a>
</div>
@ -49,7 +76,7 @@ export default {
data() {
return {
tools: {},
}
};
},
setup() {
const router = useRouter();
@ -62,10 +89,8 @@ export default {
},
mounted() {
this.tools = useToolsStore().tools;
}
}
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

55
src/views/PHPInfo.vue Normal file
View 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>

View File

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

View File

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

View File

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

View File

@ -1,17 +1,21 @@
<template>
<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">
<label for="data">Data (paste from excel)</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -21,19 +25,19 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: ""
data: "",
},
toolResult: ""
toolResult: "",
};
},
methods: {
result() {
let output = "{| class=\"wikitable\"\n";
let output = '{| class="wikitable"\n';
const rows = unproxy(this.toolData.data).split("\n");
for (let i = 0; i < rows.length; i++) {
@ -49,11 +53,9 @@ export default {
output += "|}";
this.toolResult = output;
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,35 +1,63 @@
<template>
<h2 class="tool-title">Dummy image</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label>Dimensions</label>
<div style="display: flex">
<input class="input" v-model="toolData.width" v-on:keyup="result" v-on:change="result" placeholder="500"
type="number" style="width: 70px">px
<input
class="input"
v-model="toolData.width"
v-on:keyup="result"
v-on:change="result"
placeholder="500"
type="number"
style="width: 70px"
/>px
<span style="padding: 0 10px">x</span>
<input class="input" v-model="toolData.height" v-on:keyup="result" v-on:change="result" placeholder="500"
type="number" style="width: 70px">px
<input
class="input"
v-model="toolData.height"
v-on:keyup="result"
v-on:change="result"
placeholder="500"
type="number"
style="width: 70px"
/>px
</div>
</div>
<div class="input-group">
<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 class="input-group">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<div :style="{'width': toolData.width, 'height': toolData.height}">
<canvas ref="canvas" :width="toolData.width" :height="toolData.height"
style="max-width: 50vw; max-height: 50vh;"></canvas>
<div :style="{ width: toolData.width, height: toolData.height }">
<canvas
ref="canvas"
:width="toolData.width"
:height="toolData.height"
style="max-width: 50vw; max-height: 50vh"
></canvas>
</div>
</div>
</template>
@ -42,9 +70,9 @@ export default {
width: 500,
height: 500,
color_bg: "#000000",
color_text: "#ffffff"
color_text: "#ffffff",
},
toolResult: ""
toolResult: "",
};
},
mounted() {
@ -68,11 +96,9 @@ export default {
const x = (this.toolData.width - textWidth) / 2;
const y = this.toolData.height / 2 + 10;
ctx.fillText(text, x, y);
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,24 +1,32 @@
<template>
<h2 class="tool-title">IBAN generator</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="style">Country</label>
<div>
<select id="style" v-model="toolData.country" v-on:change="result">
<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 }}
</option>
</select>
</div>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -34,8 +42,8 @@ function generateRandomNumber(length) {
}
function generateRandomString(length) {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let result = '';
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result = "";
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
@ -45,26 +53,31 @@ function generateRandomString(length) {
function mod97(string) {
let checksum = string.slice(0, 2);
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);
}
function calculateCheckDigits(iban) {
const rearranged = iban.slice(4) + iban.slice(0, 4);
const digits = rearranged.split('').map(char => {
if (char >= 'A' && char <= 'Z') {
return (char.charCodeAt(0) - 55).toString();
}
return char;
}).join('');
const digits = rearranged
.split("")
.map((char) => {
if (char >= "A" && char <= "Z") {
return (char.charCodeAt(0) - 55).toString();
}
return char;
})
.join("");
const remainder = mod97(digits);
return ('0' + (98 - remainder)).slice(-2);
return ("0" + (98 - remainder)).slice(-2);
}
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
@ -74,9 +87,17 @@ export default {
toolResult: "",
ibanStructure: {
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" },
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" },
BG: { country: "Bulgaria", length: 22, structure: "U04F04F02F08" },
BH: { country: "Bahrain", length: 22, structure: "U04F14" },
@ -114,7 +135,11 @@ export default {
MK: { country: "North Macedonia", length: 19, structure: "F03U10F02" },
MR: { country: "Mauritania", length: 27, structure: "F05F05F11F02" },
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" },
NO: { country: "Norway", length: 15, structure: "F04F06F01" },
PK: { country: "Pakistan", length: 24, structure: "U04U16" },
@ -137,17 +162,17 @@ export default {
methods: {
result() {
if (!this.toolData.country.length) {
this.toolResult = 'Select a country';
this.toolResult = "Select a country";
return;
}
const structure = this.ibanStructure[this.toolData.country];
if (!structure) {
this.toolResult = 'Unsupported country';
this.toolResult = "Unsupported country";
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);
for (const part of parts) {
@ -155,10 +180,10 @@ export default {
const length = parseInt(part.slice(1));
switch (type) {
case 'F':
case "F":
iban += generateRandomNumber(length);
break;
case 'U':
case "U":
iban += generateRandomString(length);
break;
}
@ -169,11 +194,9 @@ export default {
iban = iban.slice(0, 2) + checkDigits + iban.slice(4);
this.toolResult = iban;
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,34 +1,59 @@
<template>
<h2 class="tool-title">QR code</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<!-- Type options -->
<div class="input-group">
<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>
<!-- Basic options -->
<div class="input-group">
<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 class="input-group">
<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 class="input-group">
<label for="height">White border:</label>
<input id="quietZone" v-model.number="toolData.options.quietZone" v-on:change="result" v-on:keyup="result"
type="number">
<input
id="quietZone"
v-model.number="toolData.options.quietZone"
v-on:change="result"
v-on:keyup="result"
type="number"
/>
</div>
<div class="input-group">
<label for="correctLevel">Correct Level:</label>
<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="M">M</option>
<option value="Q">Q</option>
@ -41,7 +66,13 @@
<div class="input-group">
<label for="logoUpload">Logo Upload:</label>
<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>
</div>
</div>
@ -50,16 +81,29 @@
<div class="input-group">
<label for="backgroundImageUpload">Background Image Upload:</label>
<div>
<input type="file" id="backgroundImageUpload" ref="backgroundImageUpload" @change="handleBackgroundImageUpload"
accept="image/*">
<input
type="file"
id="backgroundImageUpload"
ref="backgroundImageUpload"
@change="handleBackgroundImageUpload"
accept="image/*"
/>
<button @click="removeBackgroundImage">🞩</button>
</div>
</div>
<div class="input-group">
<label for="backgroundImageAlpha">Background Image Alpha:</label>
<input id="backgroundImageAlpha" v-model.number="toolData.options.backgroundImageAlpha" step="0.1" min="0" max="1"
v-on:change="result" v-on:keyup="result" type="number">
<input
id="backgroundImageAlpha"
v-model.number="toolData.options.backgroundImageAlpha"
step="0.1"
min="0"
max="1"
v-on:change="result"
v-on:keyup="result"
type="number"
/>
</div>
<!--
@ -82,7 +126,7 @@
</div>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label>Result</label>
@ -110,9 +154,9 @@ export default {
backgroundImage: "",
backgroundImageAlpha: 1,
autoColor: true,
drawer: "canvas"
}
}
drawer: "canvas",
},
},
};
},
mounted() {
@ -129,10 +173,10 @@ export default {
// convert correction levels
options.correctLevel = {
"L": QRCode.CorrectLevel.L,
"M": QRCode.CorrectLevel.M,
"Q": QRCode.CorrectLevel.Q,
"H": QRCode.CorrectLevel.H
L: QRCode.CorrectLevel.L,
M: QRCode.CorrectLevel.M,
Q: QRCode.CorrectLevel.Q,
H: QRCode.CorrectLevel.H,
}[options.correctLevel];
console.log(options.correctLevel);
@ -171,11 +215,9 @@ export default {
removeBackgroundImage() {
this.toolData.options.backgroundImage = "";
this.result();
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,6 +1,6 @@
<template>
<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">
<label for="data">Data</label>
@ -9,20 +9,36 @@
<div class="input-group">
<div>
<input id="flatten" name="flatten" v-model="toolData.flatten" v-on:change="result" type="checkbox"> <label
for="flatten">inline type definitions</label>
<input
id="flatten"
name="flatten"
v-model="toolData.flatten"
v-on:change="result"
type="checkbox"
/>
<label for="flatten">inline type definitions</label>
</div>
<div>
<input id="omitempty" name="omitempty" v-model="toolData.omitempty" v-on:change="result" type="checkbox"> <label
for="omitempty">omitempty</label>
<input
id="omitempty"
name="omitempty"
v-model="toolData.omitempty"
v-on:change="result"
type="checkbox"
/>
<label for="omitempty">omitempty</label>
</div>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -30,7 +46,13 @@
import MonacoEditor from "@/components/MonacoEditor.vue";
// 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 scope;
let go = "";
@ -48,7 +70,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
} catch (e) {
return {
go: "",
error: e.message
error: e.message,
};
}
@ -58,12 +80,9 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
parseScope(scope);
return {
go: flatten
? go += accumulator
: go
go: flatten ? (go += accumulator) : go,
};
function parseScope(scope, depth = 0) {
if (typeof scope === "object" && scope !== null) {
if (Array.isArray(scope)) {
@ -72,23 +91,20 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
for (let i = 0; i < scopeLength; i++) {
const thisType = goType(scope[i]);
if (!sliceType)
sliceType = thisType;
if (!sliceType) sliceType = thisType;
else if (sliceType != thisType) {
sliceType = mostSpecificPossibleGoType(thisType, sliceType);
if (sliceType == "any")
break;
if (sliceType == "any") break;
}
}
const slice = flatten && ["struct", "slice"].includes(sliceType)
? `[]${parent}`
: `[]`;
const slice =
flatten && ["struct", "slice"].includes(sliceType)
? `[]${parent}`
: `[]`;
if (flatten && depth >= 2)
appender(slice);
else
append(slice);
if (flatten && depth >= 2) appender(slice);
else append(slice);
if (sliceType == "struct") {
const allFields = {};
@ -100,7 +116,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
if (!(keyname in allFields)) {
allFields[keyname] = {
value: scope[i][keyname],
count: 0
count: 0,
};
} else {
const existingValue = allFields[keyname].value;
@ -115,7 +131,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
keyname = `${keyname}_${uuidv4()}`;
allFields[keyname] = {
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
// 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) {
const keyname = keys[k], elem = allFields[keyname];
const keyname = keys[k],
elem = allFields[keyname];
struct[keyname] = elem.value;
omitempty[keyname] = elem.count != scopeLength;
@ -164,11 +183,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
function parseStruct(depth, innerTabs, scope, omitempty) {
if (flatten) {
stack.push(
depth >= 2
? "\n"
: ""
);
stack.push(depth >= 2 ? "\n" : "");
}
const seenTypeNames = [];
@ -198,11 +213,11 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
appender(typename + " ");
parent = typename;
parseScope(scope[keys[i]], depth);
appender(" `json:\"" + keyname);
appender(' `json:"' + keyname);
if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) {
appender(",omitempty");
}
appender("\"`\n");
appender('"`\n');
}
indenter(--innerTabs);
appender("}");
@ -218,25 +233,27 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
append(typename + " ");
parent = typename;
parseScope(scope[keys[i]], depth);
append(" `json:\"" + keyname);
append(' `json:"' + keyname);
if (allOmitempty || (omitempty && omitempty[keys[i]] === true)) {
append(",omitempty");
}
if (example && scope[keys[i]] !== "" && typeof scope[keys[i]] !== "object") {
append("\" example:\"" + scope[keys[i]]);
if (
example &&
scope[keys[i]] !== "" &&
typeof scope[keys[i]] !== "object"
) {
append('" example:"' + scope[keys[i]]);
}
append("\"`\n");
append('"`\n');
}
indent(--tabs);
append("}");
}
if (flatten)
accumulator += stack.pop();
if (flatten) accumulator += stack.pop();
}
function indent(tabs) {
for (let i = 0; i < tabs; i++)
go += "\t";
for (let i = 0; i < tabs; i++) go += "\t";
}
function append(str) {
@ -244,8 +261,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
}
function indenter(tabs) {
for (let i = 0; i < tabs; i++)
stack[stack.length - 1] += "\t";
for (let i = 0; i < tabs; i++) stack[stack.length - 1] += "\t";
}
function appender(str) {
@ -274,7 +290,7 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
function format(str) {
str = formatNumber(str);
let sanitized = toProperCase(str).replace(/[^a-z0-9]/ig, "");
let sanitized = toProperCase(str).replace(/[^a-z0-9]/gi, "");
if (!sanitized) {
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
function formatNumber(str) {
if (!str)
return "";
else if (str.match(/^\d+$/))
str = "Num" + str;
if (!str) return "";
else if (str.match(/^\d+$/)) str = "Num" + str;
else if (str.charAt(0).match(/\d/)) {
const numbers = {
"0": "Zero_", "1": "One_", "2": "Two_", "3": "Three_",
"4": "Four_", "5": "Five_", "6": "Six_", "7": "Seven_",
"8": "Eight_", "9": "Nine_"
0: "Zero_",
1: "One_",
2: "Two_",
3: "Three_",
4: "Four_",
5: "Five_",
6: "Six_",
7: "Seven_",
8: "Eight_",
9: "Nine_",
};
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
function goType(val) {
if (val === null)
return "any";
if (val === null) return "any";
switch (typeof val) {
case "string":
if (/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(\+\d\d:\d\d|Z)$/.test(val))
return "time.Time";
else
return "string";
else return "string";
case "number":
if (val % 1 === 0) {
if (val > -2147483648 && val < 2147483647)
return "int";
else
return "int64";
} else
return "float64";
if (val > -2147483648 && val < 2147483647) return "int";
else return "int64";
} else return "float64";
case "boolean":
return "bool";
case "object":
if (Array.isArray(val))
return "slice";
if (Array.isArray(val)) return "slice";
return "struct";
default:
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
function mostSpecificPossibleGoType(typ1, typ2) {
if (typ1.substr(0, 5) == "float"
&& typ2.substr(0, 3) == "int")
return typ1;
else if (typ1.substr(0, 3) == "int"
&& typ2.substr(0, 5) == "float")
if (typ1.substr(0, 5) == "float" && typ2.substr(0, 3) == "int") return typ1;
else if (typ1.substr(0, 3) == "int" && typ2.substr(0, 5) == "float")
return typ2;
else
return "any";
else return "any";
}
// 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
const commonInitialisms = [
"ACL", "API", "ASCII", "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"
"ACL",
"API",
"ASCII",
"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) {
if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0)
return sep + frag.toUpperCase();
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)
return (sep + frag).toUpperCase();
else
return sep + frag;
});
return str
.replace(/(^|[^a-zA-Z])([a-z]+)/g, function (unused, sep, frag) {
if (commonInitialisms.indexOf(frag.toUpperCase()) >= 0)
return sep + frag.toUpperCase();
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)
return (sep + frag).toUpperCase();
else return sep + frag;
});
}
function uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
);
}
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;
if (unique.length >= uuidLength) {
@ -394,8 +444,10 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
function compareObjects(objectA, objectB) {
const object = "[object Object]";
return Object.prototype.toString.call(objectA) === object
&& Object.prototype.toString.call(objectB) === object;
return (
Object.prototype.toString.call(objectA) === object &&
Object.prototype.toString.call(objectB) === object
);
}
function compareObjectKeys(itemAKeys, itemBKeys) {
@ -403,16 +455,13 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
const lengthB = itemBKeys.length;
// nothing to compare, probably identical
if (lengthA == 0 && lengthB == 0)
return true;
if (lengthA == 0 && lengthB == 0) return true;
// duh
if (lengthA != lengthB)
return false;
if (lengthA != lengthB) return false;
for (let item of itemAKeys) {
if (!itemBKeys.includes(item))
return false;
if (!itemBKeys.includes(item)) return false;
}
return true;
}
@ -427,16 +476,16 @@ function jsonToGo(json, typename, flatten = true, example = false, allOmitempty
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: "",
flatten: false,
omitempty: false
omitempty: false,
},
toolResult: ""
toolResult: "",
};
},
methods: {
@ -446,18 +495,22 @@ export default {
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) {
this.toolResult = "invalid json";
return;
}
this.toolResult = json.go;
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,27 +1,42 @@
<template>
<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">
<label for="result">MariaDB</label>
<MonacoEditor name="dialects_mariadb" language="sql" :value="toolData.dialects.mariadb" readonly="true"
style="height: 500px"></MonacoEditor>
<MonacoEditor
name="dialects_mariadb"
language="sql"
:value="toolData.dialects.mariadb"
readonly="true"
style="height: 500px"
></MonacoEditor>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">PostgreSQL</label>
<MonacoEditor name="dialects_postgresql" language="sql" :value="toolData.dialects.postgresql" readonly="true"
style="height: 500px"></MonacoEditor>
<MonacoEditor
name="dialects_postgresql"
language="sql"
:value="toolData.dialects.postgresql"
readonly="true"
style="height: 500px"
></MonacoEditor>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">OracleSQL</label>
<MonacoEditor name="dialects_oraclesql" language="sql" :value="toolData.dialects.oraclesql" readonly="true"
style="height: 500px"></MonacoEditor>
<MonacoEditor
name="dialects_oraclesql"
language="sql"
:value="toolData.dialects.oraclesql"
readonly="true"
style="height: 500px"
></MonacoEditor>
</div>
</template>
@ -30,7 +45,7 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
@ -137,14 +152,12 @@ export default {
--WHERE type_info = 'UNKNOWN'
GROUP BY table_name)
--WHERE table_name = 'V8EventVw'
ORDER BY table_name`
}
}
ORDER BY table_name`,
},
},
};
}
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,21 @@
<template>
<h2 class="tool-title">SQL formatter</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="sql" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="sql"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -21,15 +25,15 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: "",
minifyJson: ""
minifyJson: "",
},
toolResult: ""
toolResult: "",
};
},
methods: {
@ -46,20 +50,18 @@ export default {
custom: [
{ regex: String.raw`\{\$?[\w\d\->\[\]]+\}` },
{ regex: String.raw`\$[\w\d\->\[\]]+` },
{ regex: String.raw`['"].*['"]` }
{ regex: String.raw`['"].*['"]` },
],
positional: true,
named: [":", "@"]
}
named: [":", "@"],
},
});
} catch (e) {
this.toolResult = "invalid syntax";
}
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,10 +1,16 @@
<template>
<h2 class="tool-title">SQL split IN</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<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 class="input-group">
@ -14,32 +20,70 @@
<div class="input-group">
<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 class="input-group">
<label>Wrap in quotes</label>
<div>
<input id="wrap_in_quotes_no" value="" name="wrap_in_quotes" v-model="toolData.wrapInQuotes" v-on:change="result"
type="radio"> <label for="wrap_in_quotes_no">No</label><br>
<input id="wrap_in_quotes_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>
<input
id="wrap_in_quotes_no"
value=""
name="wrap_in_quotes"
v-model="toolData.wrapInQuotes"
v-on:change="result"
type="radio"
/>
<label for="wrap_in_quotes_no">No</label><br />
<input
id="wrap_in_quotes_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 class="input-group">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="sql" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="sql"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -57,7 +101,7 @@ function arrayChunk(arr, chunkSize) {
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
@ -66,15 +110,16 @@ export default {
data: "",
dataDelimiter: "",
wrapInQuotes: "",
chunkBy: 900
chunkBy: 900,
},
toolResult: ""
toolResult: "",
};
},
methods: {
result() {
let data = this.toolData.data
.split(this.toolData.dataDelimiter ? this.toolData.dataDelimiter : "\n");
let data = this.toolData.data.split(
this.toolData.dataDelimiter ? this.toolData.dataDelimiter : "\n"
);
for (let i = 0; i < data.length; i++) {
let value = data[i];
@ -84,7 +129,7 @@ export default {
value = "'" + value.replace("'", "\\'") + "'";
break;
case "double":
value = "\"" + value.replace("\"", "\\\"") + "\"";
value = '"' + value.replace('"', '\\"') + '"';
break;
}
@ -100,12 +145,15 @@ export default {
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>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

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

View File

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

View File

@ -1,17 +1,21 @@
<template>
<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">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="php" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="php"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -22,34 +26,55 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: ""
data: "",
},
toolResult: ""
toolResult: "",
};
},
methods: {
result() {
const natoAlphabet = {
"A": "Alpha", "B": "Bravo", "C": "Charlie", "D": "Delta",
"E": "Echo", "F": "Foxtrot", "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"
A: "Alpha",
B: "Bravo",
C: "Charlie",
D: "Delta",
E: "Echo",
F: "Foxtrot",
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>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,17 +1,21 @@
<template>
<h2 class="tool-title">Str numeronym</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -21,14 +25,14 @@ import { unproxy } from "../../utils/unproxy";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: ""
data: "",
},
toolResult: ""
toolResult: "",
};
},
methods: {
@ -45,11 +49,9 @@ export default {
const numberOfLetters = word.length - 2;
this.toolResult = `${firstLetter}${numberOfLetters}${lastLetter}`;
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

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

View File

@ -1,17 +1,21 @@
<template>
<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">
<label for="data">Data</label>
<textarea id="data" v-model="toolData.data" v-on:keyup="result"></textarea>
</div>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -24,24 +28,25 @@ function arrayUnique(value, index, array) {
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: ""
data: "",
},
toolResult: ""
toolResult: "",
};
},
methods: {
result() {
this.toolResult = this.toolData.data.split("\n").filter(arrayUnique).join("\n");
}
}
this.toolResult = this.toolData.data
.split("\n")
.filter(arrayUnique)
.join("\n");
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

@ -1,6 +1,6 @@
<template>
<h2 class="tool-title">Str sort lines</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="data">Data</label>
@ -11,25 +11,64 @@
<label>Mode</label>
<div>
<input id="sort_mode_alpha" value="alpha" name="sort_mode" v-model="toolData.sortMode" v-on:change="result"
type="radio"> <label for="sort_mode_alpha">alphabetically</label><br>
<input id="sort_mode_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>
<input
id="sort_mode_alpha"
value="alpha"
name="sort_mode"
v-model="toolData.sortMode"
v-on:change="result"
type="radio"
/>
<label for="sort_mode_alpha">alphabetically</label><br />
<input
id="sort_mode_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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="text" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="text"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -38,16 +77,16 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: "",
sortMode: "alpha",
sortModeReverse: false
sortModeReverse: false,
},
toolResult: ""
toolResult: "",
};
},
methods: {
@ -57,25 +96,25 @@ export default {
switch (this.toolData.sortMode) {
case "alpha":
result = data.sort(function(a, b) {
result = data.sort(function (a, b) {
return a.localeCompare(b);
});
break;
case "numerically":
const collator = new Intl.Collator([], { numeric: true });
result = data.sort(function(a, b) {
result = data.sort(function (a, b) {
return collator.compare(a, b);
});
break;
case "by_length":
result = data.sort(function(a, b) {
result = data.sort(function (a, b) {
return a.length - b.length;
});
break;
case "random":
result = data.sort(function(a, b) {
return Math.random() - .5;
result = data.sort(function (a, b) {
return Math.random() - 0.5;
});
break;
}
@ -85,11 +124,9 @@ export default {
}
this.toolResult = result.join("\n");
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

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

View File

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

View File

@ -1,22 +1,31 @@
<template>
<h2 class="tool-title">URL query viewer</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<table>
<tbody>
<tr v-for="row in toolData.queryParts">
<td><input :value="row.key" style="width: 100%;" type="text" readonly></td>
<td><input :value="row.value" style="width: 100%;" type="text" readonly></td>
</tr>
<tr v-for="row in toolData.queryParts">
<td>
<input :value="row.key" style="width: 100%" type="text" readonly />
</td>
<td>
<input
:value="row.value"
style="width: 100%"
type="text"
readonly
/>
</td>
</tr>
</tbody>
</table>
<p v-if="!toolData.queryParts.length">invalid url</p>
@ -41,9 +50,9 @@ export default {
return {
toolData: {
data: "",
queryParts: []
queryParts: [],
},
toolResult: ""
toolResult: "",
};
},
methods: {
@ -63,15 +72,14 @@ export default {
for (let [key, value] of url.searchParams.entries()) {
queryParams.push({
key: key,
value: value
value: value,
});
}
this.toolData.queryParts = queryParams.sort((a, b) => {
return a.key.localeCompare(b.key);
});
}
}
},
},
};
</script>
@ -83,4 +91,4 @@ table tr:nth-child(even) input {
table tr:nth-child(odd) input {
background-color: #eee;
}
</style>
</style>

View File

@ -1,17 +1,28 @@
<template>
<h2 class="tool-title">Explain crontab</h2>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<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>
<hr class="mt-5 mb-5">
<hr class="mt-5 mb-5" />
<div class="input-group">
<label for="result">Result</label>
<MonacoEditor name="result" language="json" :value="toolResult"></MonacoEditor>
<MonacoEditor
name="result"
language="json"
:value="toolResult"
></MonacoEditor>
</div>
</template>
@ -21,20 +32,20 @@ import MonacoEditor from "@/components/MonacoEditor.vue";
export default {
components: {
MonacoEditor
MonacoEditor,
},
data() {
return {
toolData: {
data: "* * * * *"
data: "* * * * *",
},
toolResult: ""
toolResult: "",
};
},
mounted() {
this.toolResult = cronstrue.toString(this.toolData.data, {
use24HourTimeFormat: true,
verbose: true
verbose: true,
});
},
methods: {
@ -42,16 +53,14 @@ export default {
try {
this.toolResult = cronstrue.toString(this.toolData.data, {
use24HourTimeFormat: true,
verbose: true
verbose: true,
});
} catch (e) {
this.toolResult = "invalid syntax";
}
}
}
},
},
};
</script>
<style lang="scss">
</style>
<style lang="scss"></style>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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