Sfoglia il codice sorgente

chore: format and update deps

C4illin 10 mesi fa
parent
commit
4c747e8908
7 ha cambiato i file con 96 aggiunte e 83 eliminazioni
  1. BIN
      bun.lockb
  2. 6 4
      compose.yaml
  3. 13 2
      eslint.config.mjs
  4. 17 14
      package.json
  5. 10 16
      src/converters/main.ts
  6. 47 45
      src/index.tsx
  7. 3 2
      tailwind.config.js

BIN
bun.lockb


+ 6 - 4
compose.yaml

@@ -5,9 +5,11 @@ services:
       # dockerfile: Debian.Dockerfile
     volumes:
       - ./data:/app/data
-    environment:
-      - ACCOUNT_REGISTRATION=true
-      - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234
-      - ALLOW_UNAUTHENTICATED=true
+    environment: # Defaults are listed below. All are optional.
+      - ACCOUNT_REGISTRATION=true # true or false, doesn't matter for the first account (e.g. keep this to false if you only want one account)
+      - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
+      - HTTP_ALLOWED=true # setting this to true is unsafe, only set this to true locally
+      - ALLOW_UNAUTHENTICATED=true # allows anyone to use the service without logging in, only set this to true locally
+      - AUTO_DELETE_EVERY_N_HOURS=1 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
     ports:
       - 3000:3000

+ 13 - 2
eslint.config.mjs

@@ -2,16 +2,16 @@ import { fixupPluginRules } from "@eslint/compat";
 import tseslint from "typescript-eslint";
 import eslint from "@eslint/js";
 import deprecationPlugin from "eslint-plugin-deprecation";
-import eslintCommentsPlugin from "eslint-plugin-eslint-comments";
 import importPlugin from "eslint-plugin-import";
 import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
+import tailwind from "eslint-plugin-tailwindcss";
+import comments from "@eslint-community/eslint-plugin-eslint-comments/configs"
 
 export default tseslint.config(
   {
     plugins: {
       "@typescript-eslint": tseslint.plugin,
       deprecation: fixupPluginRules(deprecationPlugin),
-      "eslint-comments": eslintCommentsPlugin,
       import: fixupPluginRules(importPlugin),
       "simple-import-sort": simpleImportSortPlugin,
     },
@@ -20,8 +20,10 @@ export default tseslint.config(
     ignores: ["**/node_modules/**", "**/public/**"],
   },
   eslint.configs.recommended,
+  comments.recommended,
   ...tseslint.configs.recommendedTypeChecked,
   ...tseslint.configs.stylisticTypeChecked,
+  ...tailwind.configs["flat/recommended"],
   {
     languageOptions: {
       parserOptions: {
@@ -32,5 +34,14 @@ export default tseslint.config(
         project: ["./tsconfig.json"],
       },
     },
+    rules: {
+      "tailwindcss/no-custom-classname": [
+        "error", 
+        { 
+          "config": "./tailwind.config.js",
+          "whitelist": ['select_container', 'convert_to_popup', 'convert_to_group', 'target', 'convert_to_target']
+        }
+      ],
+    }
   },
 );

+ 17 - 14
package.json

@@ -16,7 +16,7 @@
     "@elysiajs/html": "1.0.2",
     "@elysiajs/jwt": "^1.1.1",
     "@elysiajs/static": "1.0.3",
-    "elysia": "^1.1.12"
+    "elysia": "^1.1.16"
   },
   "module": "src/index.tsx",
   "type": "module",
@@ -25,37 +25,40 @@
   },
   "devDependencies": {
     "@biomejs/biome": "1.9.2",
+    "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0",
     "@eslint/compat": "^1.1.1",
-    "@eslint/js": "^9.9.1",
+    "@eslint/js": "^9.11.1",
     "@ianvs/prettier-plugin-sort-imports": "^4.3.1",
-    "@kitajs/ts-html-plugin": "^4.0.2",
+    "@kitajs/ts-html-plugin": "^4.1.0",
     "@picocss/pico": "^2.0.6",
     "@total-typescript/ts-reset": "^0.6.1",
-    "@types/bun": "^1.1.8",
+    "@types/bun": "^1.1.10",
     "@types/eslint": "^9.6.1",
-    "@types/node": "^22.5.4",
-    "@typescript-eslint/eslint-plugin": "^8.4.0",
-    "@typescript-eslint/parser": "^8.4.0",
+    "@types/eslint-plugin-tailwindcss": "^3.17.0",
+    "@types/eslint__js": "^8.42.3",
+    "@types/node": "^22.6.1",
+    "@typescript-eslint/eslint-plugin": "^8.7.0",
+    "@typescript-eslint/parser": "^8.7.0",
     "autoprefixer": "^10.4.20",
     "cssnano": "^7.0.6",
-    "eslint": "^9.9.1",
+    "eslint": "^9.11.1",
     "eslint-config-prettier": "^9.1.0",
     "eslint-plugin-deprecation": "^3.0.0",
-    "eslint-plugin-eslint-comments": "^3.2.0",
     "eslint-plugin-import": "^2.30.0",
     "eslint-plugin-isaacscript": "^4.0.0",
     "eslint-plugin-prettier": "^5.2.1",
     "eslint-plugin-simple-import-sort": "^12.1.1",
-    "knip": "^5.29.2",
-    "npm-run-all2": "^6.2.2",
+    "eslint-plugin-tailwindcss": "^3.17.4",
+    "knip": "^5.30.5",
+    "npm-run-all2": "^6.2.3",
     "postcss": "^8.4.47",
     "postcss-cli": "^11.0.0",
     "postcss-lightningcss": "^1.0.1",
     "prettier": "^3.3.3",
     "tailwind-scrollbar": "^3.1.0",
-    "tailwindcss": "^3.4.12",
-    "typescript": "^5.5.4",
-    "typescript-eslint": "^8.4.0"
+    "tailwindcss": "^3.4.13",
+    "typescript": "^5.6.2",
+    "typescript-eslint": "^8.7.0"
   },
   "trustedDependencies": [
     "@biomejs/biome"

+ 10 - 16
src/converters/main.ts

@@ -34,20 +34,15 @@ import { normalizeFiletype } from "../helpers/normalizeFiletype";
 
 // This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular
 
-const properties: {
-  [key: string]: {
+const properties: Record<string, {
     properties: {
-      from: { [key: string]: string[] };
-      to: { [key: string]: string[] };
-      options?: {
-        [key: string]: {
-          [key: string]: {
+      from: Record<string, string[]>;
+      to: Record<string, string[]>;
+      options?: Record<string, Record<string, {
             description: string;
             type: string;
             default: number;
-          };
-        };
-      };
+          }>>;
     };
     converter: (
       filePath: string,
@@ -58,8 +53,7 @@ const properties: {
       options?: any,
       // biome-ignore lint/suspicious/noExplicitAny: <explanation>
     ) => any;
-  };
-} = {
+  }> = {
   libjxl: {
     properties: propertiesLibjxl,
     converter: convertLibjxl,
@@ -159,7 +153,7 @@ export async function mainConverter(
   }
 }
 
-const possibleTargets: { [key: string]: { [key: string]: string[] } } = {};
+const possibleTargets: Record<string, Record<string, string[]>> = {};
 
 for (const converterName in properties) {
   const converterProperties = properties[converterName]?.properties;
@@ -186,7 +180,7 @@ for (const converterName in properties) {
 
 export const getPossibleTargets = (
   from: string,
-): { [key: string]: string[] } => {
+): Record<string, string[]> => {
   const fromClean = normalizeFiletype(from);
 
   return possibleTargets[fromClean] || {};
@@ -214,7 +208,7 @@ const getPossibleInputs = () => {
   return possibleInputs;
 };
 
-const allTargets: { [key: string]: string[] } = {};
+const allTargets: Record<string, string[]> = {};
 
 for (const converterName in properties) {
   const converterProperties = properties[converterName]?.properties;
@@ -236,7 +230,7 @@ export const getAllTargets = () => {
   return allTargets;
 };
 
-const allInputs: { [key: string]: string[] } = {};
+const allInputs: Record<string, string[]> = {};
 for (const converterName in properties) {
   const converterProperties = properties[converterName]?.properties;
 

+ 47 - 45
src/index.tsx

@@ -138,8 +138,8 @@ const app = new Elysia({
 
     return (
       <BaseHtml title="ConvertX | Setup">
-        <main class="w-full mx-auto max-w-4xl px-4">
-          <h1 class="text-3xl my-8">Welcome to ConvertX!</h1>
+        <main class="mx-auto w-full max-w-4xl px-4">
+          <h1 class="my-8 text-3xl">Welcome to ConvertX!</h1>
           <article class="article p-0">
             <header class="w-full bg-gray-800 p-4">Create your account</header>
             <form method="post" action="/register" class="p-4">
@@ -172,7 +172,7 @@ const app = new Elysia({
             <footer class="p-4">
               Report any issues on{" "}
               <a
-                class="underline text-lime-500 hover:text-lime-400"
+                class="text-lime-500 underline hover:text-lime-400"
                 href="https://github.com/C4illin/ConvertX">
                 GitHub
               </a>
@@ -343,7 +343,7 @@ const app = new Elysia({
                 </fieldset>
                 <div role="group">
                   {ACCOUNT_REGISTRATION ? (
-                    <a href="/register" role="button" class="secondary">
+                    <a href="/register" role="button" class="btn-primary w-full">
                       Register an account
                     </a>
                   ) : null}
@@ -456,7 +456,12 @@ const app = new Elysia({
         }
       }
     } else if (ALLOW_UNAUTHENTICATED) {
-      const newUserId = String(randomInt(2 ** 24, Math.min(2 ** 48 + 2 ** 24 - 1,  Number.MAX_SAFE_INTEGER)));
+      const newUserId = String(
+        randomInt(
+          2 ** 24,
+          Math.min(2 ** 48 + 2 ** 24 - 1, Number.MAX_SAFE_INTEGER),
+        ),
+      );
       const accessToken = await jwt.sign({
         id: newUserId,
       });
@@ -515,15 +520,15 @@ const app = new Elysia({
           <main class="w-full px-4">
             <article class="article">
               <h1 class="mb-4 text-xl">Convert</h1>
-              <div class="max-h-[50vh] overflow-y-auto mb-4 scrollbar-thin">
+              <div class="mb-4 max-h-[50vh] overflow-y-auto scrollbar-thin">
                 <table
                   id="file-list"
-                  class="table-auto w-full bg-gray-900 [&_td]:p-4 rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_tr]:rounded"
+                  class="w-full table-auto rounded bg-gray-900 [&_td]:p-4 [&_tr]:rounded [&_tr]:border-b [&_tr]:border-gray-800"
                 />
               </div>
               <div
                 id="dropzone"
-                class="relative flex h-48 w-full items-center justify-center rounded border border-gray-700 border-dashed transition-all hover:border-gray-600 [&.dragover]:border-4 [&.dragover]:border-gray-500">
+                class="relative flex h-48 w-full items-center justify-center rounded border border-dashed border-gray-700 transition-all hover:border-gray-600 [&.dragover]:border-4 [&.dragover]:border-gray-500">
                 <span>
                   <b>Choose a file</b> or drag it here
                 </span>
@@ -538,7 +543,7 @@ const app = new Elysia({
             <form
               method="post"
               action="/convert"
-              class="relative w-full mx-auto max-w-4xl mb-[35vh]">
+              class="relative mx-auto mb-[35vh] w-full max-w-4xl">
               <input type="hidden" name="file_names" id="file_names" />
               <article class="article w-full">
                 <input
@@ -549,21 +554,21 @@ const app = new Elysia({
                   class="w-full rounded bg-gray-800 p-4"
                 />
                 <div class="select_container relative">
-                  <article class="convert_to_popup flex-col absolute z-[2] max-h-[50vh] h-[30vh] w-full overflow-y-auto m-0 overflow-x-hidden hidden bg-gray-800 sm:h-[30vh] rounded">
+                  <article class="convert_to_popup absolute z-[2] m-0 hidden h-[30vh] max-h-[50vh] w-full flex-col overflow-y-auto overflow-x-hidden rounded bg-gray-800 sm:h-[30vh]">
                     {Object.entries(getAllTargets()).map(
                       ([converter, targets]) => (
                         <article
-                          class="convert_to_group border-gray-700 border-b p-4 w-full"
+                          class="convert_to_group w-full border-b border-gray-700 p-4"
                           data-converter={converter}>
-                          <header class="text-xl font-bold w-full mb-2" safe>
+                          <header class="mb-2 w-full text-xl font-bold" safe>
                             {converter}
                           </header>
-                          <ul class="convert_to_target flex flex-row gap-1 flex-wrap">
+                          <ul class="convert_to_target flex flex-row flex-wrap gap-1">
                             {targets.map((target) => (
                               <button
                                 // https://stackoverflow.com/questions/121499/when-a-blur-event-occurs-how-can-i-find-out-which-element-focus-went-to#comment82388679_33325953
                                 tabindex={0}
-                                class="target p-1 text-base bg-gray-700 rounded hover:bg-gray-600"
+                                class="target rounded bg-gray-700 p-1 text-base hover:bg-gray-600"
                                 data-value={`${target},${converter}`}
                                 data-target={target}
                                 data-converter={converter}
@@ -614,21 +619,21 @@ const app = new Elysia({
     ({ body }) => {
       return (
         <>
-          <article class="convert_to_popup flex-col absolute z-[2] max-h-[50vh] h-[50vh] w-full overflow-y-auto m-0 overflow-x-hidden hidden bg-gray-800 sm:h-[30vh] rounded">
+          <article class="convert_to_popup absolute z-[2] m-0 hidden h-[50vh] max-h-[50vh] w-full flex-col overflow-y-auto overflow-x-hidden rounded bg-gray-800 sm:h-[30vh]">
             {Object.entries(getPossibleTargets(body.fileType)).map(
               ([converter, targets]) => (
                 <article
-                  class="convert_to_group border-gray-700 border-b p-4 w-full"
+                  class="convert_to_group w-full border-b border-gray-700 p-4"
                   data-converter={converter}>
-                  <header class="text-xl font-bold w-full mb-2" safe>
+                  <header class="mb-2 w-full text-xl font-bold" safe>
                     {converter}
                   </header>
-                  <ul class="convert_to_target flex flex-row gap-1 flex-wrap">
+                  <ul class="convert_to_target flex flex-row flex-wrap gap-1">
                     {targets.map((target) => (
                       <button
                         // https://stackoverflow.com/questions/121499/when-a-blur-event-occurs-how-can-i-find-out-which-element-focus-went-to#comment82388679_33325953
                         tabindex={0}
-                        class="target p-1 text-base bg-gray-700 rounded hover:bg-gray-600"
+                        class="target rounded bg-gray-700 p-1 text-base hover:bg-gray-600"
                         data-value={`${target},${converter}`}
                         data-target={target}
                         data-converter={converter}
@@ -875,8 +880,8 @@ const app = new Elysia({
           <Header loggedIn />
           <main class="w-full px-4">
             <article class="article">
-              <h1 class="text-xl mb-4">Results</h1>
-              <table class="table-auto w-full bg-gray-900 [&_td]:p-4 rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_tr]:rounded text-left">
+              <h1 class="mb-4 text-xl">Results</h1>
+              <table class="w-full table-auto rounded bg-gray-900 text-left [&_td]:p-4 [&_tr]:rounded [&_tr]:border-b [&_tr]:border-gray-800">
                 <thead>
                   <tr>
                     <th class="px-4 py-2">Time</th>
@@ -895,7 +900,7 @@ const app = new Elysia({
                       <td safe>{job.status}</td>
                       <td>
                         <a
-                          class="underline text-lime-500 hover:text-lime-400"
+                          class="text-lime-500 underline hover:text-lime-400"
                           href={`/results/${job.id}`}>
                           View
                         </a>
@@ -952,12 +957,12 @@ const app = new Elysia({
             <Header loggedIn />
             <main class="w-full px-4">
               <article class="article">
-                <div class="flex items-center justify-between mb-4">
+                <div class="mb-4 flex items-center justify-between">
                   <h1 class="text-xl">Results</h1>
                   <div>
                     <button
                       type="button"
-                      class="w-40 float-right btn-primary"
+                      class="btn-primary float-right w-40"
                       onclick="downloadAll()"
                       {...(files.length !== job.num_files
                         ? { disabled: true, "aria-busy": "true" }
@@ -971,9 +976,9 @@ const app = new Elysia({
                 <progress
                   max={job.num_files}
                   value={files.length}
-                  class="w-full rounded-full mb-4 h-2 border-0 inline-block appearance-none overflow-hidden bg-none bg-gray-700 text-lime-500 accent-lime-500 [&::-moz-progress-bar]:bg-gray-700 [&::-webkit-progress-value]:[ background:none] [&::-webkit-progress-value]:rounded-full [&[value]::-webkit-progress-value]:bg-lime-500 [&[value]::-webkit-progress-value]:transition-[inline-size]"
+                  class="mb-4 inline-block h-2 w-full appearance-none overflow-hidden rounded-full border-0 bg-gray-700 bg-none text-lime-500 accent-lime-500 [&::-moz-progress-bar]:bg-gray-700 [&::-webkit-progress-value]:rounded-full [&::-webkit-progress-value]:[background:none] [&[value]::-webkit-progress-value]:bg-lime-500 [&[value]::-webkit-progress-value]:transition-[inline-size]"
                 />
-                <table class="table-auto w-full bg-gray-900 [&_td]:p-4 rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_tr]:rounded text-left">
+                <table class="w-full table-auto rounded bg-gray-900 text-left [&_td]:p-4 [&_tr]:rounded [&_tr]:border-b [&_tr]:border-gray-800">
                   <thead>
                     <tr>
                       <th class="px-4 py-2">Converted File Name</th>
@@ -989,14 +994,14 @@ const app = new Elysia({
                         <td safe>{file.status}</td>
                         <td>
                           <a
-                            class="underline text-lime-500 hover:text-lime-400"
+                            class="text-lime-500 underline hover:text-lime-400"
                             href={`/download/${outputPath}${file.output_file_name}`}>
                             View
                           </a>
                         </td>
                         <td>
                           <a
-                            class="underline text-lime-500 hover:text-lime-400"
+                            class="text-lime-500 underline hover:text-lime-400"
                             href={`/download/${outputPath}${file.output_file_name}`}
                             download={file.output_file_name}>
                             Download
@@ -1052,12 +1057,12 @@ const app = new Elysia({
 
       return (
         <article class="article">
-          <div class="flex items-center justify-between mb-4">
+          <div class="mb-4 flex items-center justify-between">
             <h1 class="text-xl">Results</h1>
             <div>
               <button
                 type="button"
-                class="w-40 float-right btn-primary"
+                class="btn-primary float-right w-40"
                 onclick="downloadAll()"
                 {...(files.length !== job.num_files
                   ? { disabled: true, "aria-busy": "true" }
@@ -1071,9 +1076,9 @@ const app = new Elysia({
           <progress
             max={job.num_files}
             value={files.length}
-            class="w-full rounded-full mb-4 h-2 border-0 inline-block appearance-none overflow-hidden bg-none bg-gray-700 text-lime-500 accent-lime-500 [&::-moz-progress-bar]:bg-gray-700 [&::-webkit-progress-value]:[ background:none] [&::-webkit-progress-value]:rounded-full [&[value]::-webkit-progress-value]:bg-lime-500 [&[value]::-webkit-progress-value]:transition-[inline-size]"
+            class="mb-4 inline-block h-2 w-full appearance-none overflow-hidden rounded-full border-0 bg-gray-700 bg-none text-lime-500 accent-lime-500 [&::-moz-progress-bar]:bg-gray-700 [&::-webkit-progress-value]:rounded-full [&::-webkit-progress-value]:[background:none] [&[value]::-webkit-progress-value]:bg-lime-500 [&[value]::-webkit-progress-value]:transition-[inline-size]"
           />
-          <table class="table-auto w-full bg-gray-900 [&_td]:p-4 rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_tr]:rounded text-left">
+          <table class="w-full table-auto rounded bg-gray-900 text-left [&_td]:p-4 [&_tr]:rounded [&_tr]:border-b [&_tr]:border-gray-800">
             <thead>
               <tr>
                 <th class="px-4 py-2">Converted File Name</th>
@@ -1089,14 +1094,14 @@ const app = new Elysia({
                   <td safe>{file.status}</td>
                   <td>
                     <a
-                      class="underline text-lime-500 hover:text-lime-400"
+                      class="text-lime-500 underline hover:text-lime-400"
                       href={`/download/${outputPath}${file.output_file_name}`}>
                       View
                     </a>
                   </td>
                   <td>
                     <a
-                      class="underline text-lime-500 hover:text-lime-400"
+                      class="text-lime-500 underline hover:text-lime-400"
                       href={`/download/${outputPath}${file.output_file_name}`}
                       download={file.output_file_name}>
                       Download
@@ -1155,7 +1160,7 @@ const app = new Elysia({
           <main class="w-full px-4">
             <article class="article">
               <h1 class="mb-4 text-xl">Converters</h1>
-              <table class="table-auto w-full bg-gray-900 [&_td]:p-4 rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_tr]:rounded text-left [&_ul]:list-inside [&_ul]:list-disc">
+              <table class="w-full table-auto rounded bg-gray-900 text-left [&_td]:p-4 [&_tr]:rounded [&_tr]:border-b [&_tr]:border-gray-800 [&_ul]:list-inside [&_ul]:list-disc">
                 <thead>
                   <tr>
                     <th class="mx-4 my-2">Converter</th>
@@ -1230,19 +1235,16 @@ const app = new Elysia({
     // log.error(` ${request.method} ${request.url}`, code, error);
     console.error(error);
   });
-  
 
 if (process.env.NODE_ENV !== "production") {
-  await import("./helpers/tailwind").then(
-    async ({ generateTailwind }) => {
-      const result = await generateTailwind()
+  await import("./helpers/tailwind").then(async ({ generateTailwind }) => {
+    const result = await generateTailwind();
 
-      app.get("/style.css", ({ set }) => {
-        set.headers["content-type"] = "text/css";
-        return result;
-      });
-    },
-  );
+    app.get("/style.css", ({ set }) => {
+      set.headers["content-type"] = "text/css";
+      return result;
+    });
+  });
 }
 
 app.listen(3000);

+ 3 - 2
tailwind.config.js

@@ -1,9 +1,10 @@
 /** @type {import('tailwindcss').Config} */
+import scrollbar from 'tailwind-scrollbar';
 // eslint-disable-next-line no-undef
 module.exports = {
-  content: ["./src/**/*.{html,js,tsx}"],
+  content: ["./src/**/*.{html,js,tsx,jsx,cjs,mjs}"],
   theme: {
     extend: {},
   },
-  plugins: [import('tailwind-scrollbar')],
+  plugins: [scrollbar()],
 }