mirror of
https://github.com/C4illin/ConvertX.git
synced 2026-06-28 06:55:48 +00:00
fix download
This commit is contained in:
@@ -6,6 +6,24 @@ export const BaseHtml = ({ children, title = "ConvertX" }) => (
|
||||
<title>{title}</title>
|
||||
<link rel="stylesheet" href="/pico.lime.min.css" />
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/favicon-32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="/favicon-16x16.png"
|
||||
/>
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12" />
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
|
||||
@@ -4,7 +4,7 @@ export const Header = ({ loggedIn }: { loggedIn?: boolean }) => {
|
||||
rightNav = (
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/results">History</a>
|
||||
<a href="/history">History</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/logout">Logout</a>
|
||||
|
||||
@@ -73,8 +73,12 @@ export async function mainConverter(
|
||||
|
||||
const possibleConversions: { [key: string]: string[] } = {};
|
||||
|
||||
for (const from of [...propertiesImage.from, ...propertiesPandoc.from]) {
|
||||
possibleConversions[from] = [...propertiesImage.to, ...propertiesPandoc.to];
|
||||
for (const from of propertiesImage.from) {
|
||||
possibleConversions[from] = propertiesImage.to;
|
||||
}
|
||||
|
||||
for (const from of propertiesPandoc.from) {
|
||||
possibleConversions[from] = propertiesPandoc.to;
|
||||
}
|
||||
|
||||
export const getPossibleConversions = (from: string): string[] => {
|
||||
@@ -85,4 +89,4 @@ export const getPossibleConversions = (from: string): string[] => {
|
||||
|
||||
export const getAllTargets = () => {
|
||||
return [...propertiesImage.to, ...propertiesPandoc.to];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,16 +2,128 @@ import { exec } from "node:child_process";
|
||||
|
||||
export const properties = {
|
||||
from: [
|
||||
"md", "html", "docx", "pdf", "tex", "txt", "bibtex", "biblatex", "commonmark", "commonmark_x", "creole", "csljson", "csv", "tsv", "docbook", "dokuwiki", "endnotexml", "epub", "fb2", "gfm", "haddock", "ipynb", "jats", "jira", "json", "latex", "markdown", "markdown_mmd", "markdown_phpextra", "markdown_strict", "mediawiki", "man", "muse", "native", "odt", "opml", "org", "ris", "rtf", "rst", "t2t", "textile", "tikiwiki", "twiki", "vimwiki"
|
||||
"textile",
|
||||
"tikiwiki",
|
||||
"tsv",
|
||||
"twiki",
|
||||
"typst",
|
||||
"vimwiki",
|
||||
"biblatex",
|
||||
"bibtex",
|
||||
"bits",
|
||||
"commonmark",
|
||||
"commonmark_x",
|
||||
"creole",
|
||||
"csljson",
|
||||
"csv",
|
||||
"djot",
|
||||
"docbook",
|
||||
"docx",
|
||||
"dokuwiki",
|
||||
"endnotexml",
|
||||
"epub",
|
||||
"fb2",
|
||||
"gfm",
|
||||
"haddock",
|
||||
"html",
|
||||
"ipynb",
|
||||
"jats",
|
||||
"jira",
|
||||
"json",
|
||||
"latex",
|
||||
"man",
|
||||
"markdown",
|
||||
"markdown_mmd",
|
||||
"markdown_phpextra",
|
||||
"markdown_strict",
|
||||
"mediawiki",
|
||||
"muse",
|
||||
"pandoc native",
|
||||
"opml",
|
||||
"org",
|
||||
"ris",
|
||||
"rst",
|
||||
"rtf",
|
||||
"t2t",
|
||||
],
|
||||
to: [
|
||||
"asciidoc", "asciidoctor", "beamer", "bibtex", "biblatex", "commonmark", "commonmark_x", "context", "csljson", "docbook", "docbook4", "docbook5", "docx", "dokuwiki", "epub", "epub3", "epub2", "fb2", "gfm", "haddock", "html", "html5", "html4", "icml", "ipynb", "jats_archiving", "jats_articleauthoring", "jats_publishing", "jats", "jira", "json", "latex", "man", "markdown", "markdown_mmd", "markdown_phpextra", "markdown_strict", "markua", "mediawiki", "ms", "muse", "native", "odt", "opml", "opendocument", "org", "pdf", "plain", "pptx", "rst", "rtf", "texinfo", "textile", "slideous", "slidy", "dzslides", "revealjs", "s5", "tei", "xwiki", "zimwiki"
|
||||
]
|
||||
"tei",
|
||||
"texinfo",
|
||||
"textile",
|
||||
"typst",
|
||||
"xwiki",
|
||||
"zimwiki",
|
||||
"asciidoc",
|
||||
"asciidoc_legacy",
|
||||
"asciidoctor",
|
||||
"beamer",
|
||||
"biblatex",
|
||||
"bibtex",
|
||||
"chunkedhtml",
|
||||
"commonmark",
|
||||
"commonmark_x",
|
||||
"context",
|
||||
"csljson",
|
||||
"djot",
|
||||
"docbook",
|
||||
"docbook4",
|
||||
"docbook5",
|
||||
"docx",
|
||||
"dokuwiki",
|
||||
"dzslides",
|
||||
"epub",
|
||||
"epub2",
|
||||
"epub3",
|
||||
"fb2",
|
||||
"gfm",
|
||||
"haddock",
|
||||
"html",
|
||||
"html4",
|
||||
"html5",
|
||||
"icml",
|
||||
"ipynb",
|
||||
"jats",
|
||||
"jats_archiving",
|
||||
"jats_articleauthoring",
|
||||
"jats_publishing",
|
||||
"jira",
|
||||
"json",
|
||||
"latex",
|
||||
"man",
|
||||
"markdown",
|
||||
"markdown_mmd",
|
||||
"markdown_phpextra",
|
||||
"markdown_strict",
|
||||
"markua",
|
||||
"mediawiki",
|
||||
"ms",
|
||||
"muse",
|
||||
"pandoc native",
|
||||
"odt",
|
||||
"opendocument",
|
||||
"opml",
|
||||
"org",
|
||||
"pdf",
|
||||
"plain",
|
||||
"pptx",
|
||||
"revealjs",
|
||||
"rst",
|
||||
"rtf",
|
||||
"s5",
|
||||
"slideous",
|
||||
"slidy",
|
||||
],
|
||||
};
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
export function convert(filePath: string, fileType: string, convertTo: string, targetPath: string, options?: any) {
|
||||
export function convert(
|
||||
filePath: string,
|
||||
fileType: string,
|
||||
convertTo: string,
|
||||
targetPath: string,
|
||||
options?: any,
|
||||
) {
|
||||
return exec(
|
||||
`pandoc ${filePath} -f ${fileType} -t ${convertTo} -o ${targetPath}`,
|
||||
`pandoc "${filePath}" -f ${fileType} -t ${convertTo} -o "${targetPath}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,20 @@ const app = new Elysia()
|
||||
};
|
||||
},
|
||||
)
|
||||
.get("/login", () => {
|
||||
.get("/login", async ({ jwt, redirect, cookie: { auth } }) => {
|
||||
console.log("login handler");
|
||||
// if already logged in, redirect to home
|
||||
if (auth?.value) {
|
||||
const user = await jwt.verify(auth.value);
|
||||
console.log(user);
|
||||
|
||||
if (user) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
auth.remove();
|
||||
}
|
||||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Login">
|
||||
<Header />
|
||||
@@ -220,15 +233,6 @@ const app = new Elysia()
|
||||
.post(
|
||||
"/login",
|
||||
async function handler({ body, set, redirect, jwt, cookie: { auth } }) {
|
||||
// if already logged in, redirect to home
|
||||
if (auth?.value) {
|
||||
const user = await jwt.verify(auth.value);
|
||||
if (user) {
|
||||
return redirect("/");
|
||||
}
|
||||
auth.remove();
|
||||
}
|
||||
|
||||
const existingUser = (await db
|
||||
.query("SELECT * FROM users WHERE email = ?")
|
||||
.get(body.email)) as IUser;
|
||||
@@ -514,7 +518,7 @@ const app = new Elysia()
|
||||
return redirect(`/results/${jobId.value}`);
|
||||
},
|
||||
)
|
||||
.get("/histt", async ({ jwt, redirect, cookie: { auth } }) => {
|
||||
.get("/history", async ({ jwt, redirect, cookie: { auth } }) => {
|
||||
console.log("results page");
|
||||
if (!auth?.value) {
|
||||
console.log("no auth value");
|
||||
@@ -549,7 +553,7 @@ const app = new Elysia()
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Results">
|
||||
<Header loggedIn />
|
||||
<main class="container-fluid">
|
||||
<main class="container">
|
||||
<article>
|
||||
<h1>Results</h1>
|
||||
<table>
|
||||
@@ -619,7 +623,7 @@ const app = new Elysia()
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Result">
|
||||
<Header loggedIn />
|
||||
<main class="container-fluid">
|
||||
<main class="container">
|
||||
<article>
|
||||
<div class="grid">
|
||||
<h1>Results</h1>
|
||||
@@ -690,8 +694,12 @@ const app = new Elysia()
|
||||
if (!job) {
|
||||
return redirect("/results");
|
||||
}
|
||||
// parse from url encoded string
|
||||
const userId = decodeURIComponent(params.userId);
|
||||
const jobId = decodeURIComponent(params.jobId);
|
||||
const fileName = decodeURIComponent(params.fileName);
|
||||
|
||||
const filePath = `${outputDir}${params.userId}/${params.jobId}/${params.fileName}`;
|
||||
const filePath = `${outputDir}${userId}/${jobId}/${fileName}`;
|
||||
return Bun.file(filePath);
|
||||
},
|
||||
)
|
||||
|
||||
BIN
src/public/android-chrome-192x192.png
Normal file
BIN
src/public/android-chrome-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
BIN
src/public/android-chrome-512x512.png
Normal file
BIN
src/public/android-chrome-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
src/public/apple-touch-icon.png
Normal file
BIN
src/public/apple-touch-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
src/public/favicon-16x16.png
Normal file
BIN
src/public/favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 476 B |
BIN
src/public/favicon-32x32.png
Normal file
BIN
src/public/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 960 B |
BIN
src/public/favicon.ico
Normal file
BIN
src/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -28,9 +28,7 @@ fileInput.addEventListener("change", (e) => {
|
||||
fileType = file.name.split(".").pop();
|
||||
console.log(file.type);
|
||||
fileInput.setAttribute("accept", `.${fileType}`);
|
||||
|
||||
const title = document.querySelector("h1");
|
||||
title.textContent = `Convert .${fileType}`;
|
||||
setTitle();
|
||||
|
||||
fetch("/conversions", {
|
||||
method: "POST",
|
||||
@@ -57,6 +55,11 @@ fileInput.addEventListener("change", (e) => {
|
||||
uploadFiles(files);
|
||||
});
|
||||
|
||||
const setTitle = () => {
|
||||
const title = document.querySelector("h1");
|
||||
title.textContent = `Convert ${fileType ? `.${fileType}` : "___"}`;
|
||||
};
|
||||
|
||||
// Add a onclick for the delete button
|
||||
const deleteRow = (target) => {
|
||||
const filename = target.parentElement.parentElement.children[0].textContent;
|
||||
@@ -67,6 +70,13 @@ const deleteRow = (target) => {
|
||||
const index = fileNames.indexOf(filename);
|
||||
fileNames.splice(index, 1);
|
||||
|
||||
// if fileNames is empty, reset fileType
|
||||
if (fileNames.length === 0) {
|
||||
fileType = null;
|
||||
fileInput.removeAttribute("accept");
|
||||
setTitle();
|
||||
}
|
||||
|
||||
fetch("/delete", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ filename: filename }),
|
||||
|
||||
19
src/public/site.webmanifest
Normal file
19
src/public/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "ConvertX | Self Hosted File Converter",
|
||||
"short_name": "ConvertX",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#a5d601",
|
||||
"background_color": "#13171f",
|
||||
"display": "standalone"
|
||||
}
|
||||
Reference in New Issue
Block a user