Skip to content

Commit ec307df

Browse files
zardoycursoragent
andcommitted
UI fork: React converter, folder convert, PWA, shortcuts, README
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent f4b5aba commit ec307df

File tree

15 files changed

+1798
-173
lines changed

15 files changed

+1798
-173
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Fork Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: ["master", "main"]
6+
7+
permissions:
8+
contents: write
9+
10+
concurrency:
11+
group: "gh-fork-deploy"
12+
cancel-in-progress: true
13+
14+
jobs:
15+
deploy:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
with:
22+
submodules: recursive
23+
24+
- name: Setup Bun
25+
uses: oven-sh/setup-bun@v1
26+
with:
27+
bun-version: "latest"
28+
cache: true
29+
30+
- name: Install dependencies
31+
run: bun i --frozen-lockfile
32+
33+
- name: Build
34+
run: bun run build
35+
36+
- name: Generate cache
37+
run: bun run buildCache.js dist/cache.json
38+
39+
- name: Move assets into dist/convert
40+
run: bash external/post-build.sh
41+
42+
- name: Deploy to GitHub Pages
43+
uses: peaceiris/actions-gh-pages@v3
44+
with:
45+
github_token: ${{ secrets.GITHUB_TOKEN }}
46+
publish_dir: ./dist
47+
publish_branch: gh-pages
48+
force_orphan: true
49+
cname: fco.tools

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ node_modules
44
start.sh
55
dist
66
cache.json
7+
.DS_Store

README.md

Lines changed: 29 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,47 @@
1-
# [Convert to it!](https://convert.to.it/)
2-
**Truly universal online file converter.**
1+
# Convert it! — Test fork
32

4-
Many online file conversion tools are **boring** and **insecure**. They only allow conversion between two formats in the same medium (images to images, videos to videos, etc.), and they require that you _upload your files to some server_.
3+
> Rolling experimental improvements, opinionated features & workflows.
54
6-
This is not just terrible for privacy, it's also incredibly lame. What if you _really_ need to convert an AVI video to a PDF document? Try to find an online tool for that, I dare you.
5+
---
76

8-
[Convert.to.it](https://convert.to.it/) aims to be a tool that "just works". You're almost _guaranteed_ to get an output - perhaps not always the one you expected, but it'll try its best to not leave you hanging.
7+
## Features
98

10-
For a semi-technical overview of this tool, check out the video: https://youtu.be/btUbcsTbVA8
9+
- **Beautiful UI** — Dark theme, clear hierarchy, reskins planned.
10+
- **Open as folder & convert many files** — Use **In Folder Convert** and the File System Access API: pick a folder, choose formats, convert. Files are written **directly into that folder** — no download step. Optional: move originals into `_originals/` after conversion.
11+
- **Drag & drop** — Drop files or folders onto the page. **Ctrl+V** (or Cmd+V) to paste from clipboard.
12+
- **Quick shortcuts****Press `1`** with a single file loaded to convert to the first suggested format instantly. Type to filter formats, **Esc** to clear. Suggested formats are sorted by category and your **recently used** choices.
13+
- **Single-file workflow****Drag out** the converted file from the browser into any folder (no download clutter). Or use **Share** (Web Share API) or **Download**. Optional auto-download for single-file conversions.
14+
- **Batch options** — Convert multiple files without folder write access? **Download N files** or **Download as ZIP** (one archive).
15+
- **PWA** — Install as an app from the browser for a native-like launcher (no offline support in this fork).
1116

12-
## Usage
17+
---
1318

14-
1. Go to [convert.to.it](https://convert.to.it/)
15-
2. Click the big blue box to add your file (or just drag it on to the window).
16-
3. An input format should have been automatically selected. If it wasn't, yikes! Try searching for it, or if it's really not there, see the "Issues" section below.
17-
4. Select an output format from the second list. If you're on desktop, that's the one on the right side. If you're on mobile, it'll be somewhere lower down.
18-
5. Click **Convert**!
19-
6. Hopefully, after a bit (or a lot) of thinking, the program will spit out the file you wanted. If not, see the "Issues" section below.
19+
## Was this vibecoded?
2020

21-
## Issues
21+
**Yes.** (The scroll/filter perf probably gives it away.)
2222

23-
Ever since the YouTube video released, we've been getting spammed with issues suggesting the addition of all kinds of niche file formats. To keep things organized, I've decided to specify what counts as a valid issue and what doesn't.
23+
One goal was to push the limits of prompting: you still need solid knowledge of web APIs, browser gotchas, and power-user shortcuts to get a decent frontend. Without that, this UI wouldn’t exist.
2424

25-
> [!IMPORTANT]
26-
> **SIMPLY ASKING FOR A FILE FORMAT TO BE ADDED IS NOT A MEANINGFUL ISSUE!**
25+
---
2726

28-
There are thousands of file formats out there. It can take hours to add support for just one. The math is simple - we can't possibly support every single file. As such, simply listing your favorite file formats is not helpful. We already know that there are formats we don't support, we don't need tickets to tell us that.
27+
## Is that all?
2928

30-
When suggesting a file format, you must _at minimum_:
31-
- Make sure that there isn't already an issue about the same thing, and that we don't already support the format.
32-
- Explain what you expect the conversion to be like (what medium is it converting to/from). It's important to note here that simply parsing the underlying data is _not sufficient_. Imagine if we only treated SVG images as raw XML data and didn't support converting them to raster images - that would defeat the point.
33-
- Provide links to existing browser-based solutions if possible, or at the very least a reference for implementing the format, and make sure the license is compatible with GPL-2.0.
29+
**Mostly**. A few ideas didn’t pan out (yet):
3430

35-
If this seems like a lot, please remember - a developer will have to do 100x more work to actually implement the format. Doing a bit of research not only saves them precious time, it also weeds out "unserious" proposals that would only bloat our to-do list.
31+
**Copy to clipboard**
32+
Nice in theory, but many file MIME types can’t be written to the async Clipboard API without errors, so clipboard paste isn’t reliable for arbitrary converted files. We use **drag-out** instead.
3633

37-
**If you're submitting a bug report,** you only need to do step 1 - check if the problem isn't already reported by someone else. Bug reports are generally quite important otherwise.
34+
**Chrome extension**
35+
Still under consideration. A quick UI triggered from the extension could be handy, but you can already “install” the site as an app. Replacing file inputs on random sites with a custom converter UI doesn’t seem like a reliable workflow yet — need to understand real use cases better.
3836

39-
Though please note, "converting X to Y doesn't work" is **not** a bug report. However, "converting X to Y works but not how I expected" likely **is** a bug report.
37+
**Electron app**
38+
Under strong consideration. Using real FFmpeg in a desktop gives much better performance and also native explorer integration would be a big thing. Might happen in a few days if i dont forget of this repo.
4039

41-
## Deployment
40+
**Mobile native app**
41+
Out of scope for now; could be revisited later.
4242

43-
### Local development (Bun + Vite)
43+
---
4444

45-
1. Clone this repository ***WITH SUBMODULES***. You can use `git clone --recursive https://github.com/p2r3/convert` for that. Omitting submodules will leave you missing a few dependencies.
46-
2. Install [Bun](https://bun.sh/).
47-
3. Run `bun install` to install dependencies.
48-
4. Run `bunx vite` to start the development server.
45+
## Credits
4946

50-
_The following steps are optional, but recommended for performance:_
51-
52-
When you first open the page, it'll take a while to generate the list of supported formats for each tool. If you open the console, you'll see it complaining a bunch about missing caches.
53-
54-
After this is done (indicated by a `Built initial format list` message in the console), use `printSupportedFormatCache()` to get a JSON string with the cache data. You can then save this string to `cache.json` to skip that loading screen on startup.
55-
56-
### Docker (prebuilt image)
57-
58-
Docker compose files live in the `docker/` directory, so run compose with `-f` from the repository root:
59-
60-
```bash
61-
docker compose -f docker/docker-compose.yml up -d
62-
```
63-
64-
Alternatively download the `docker-compose.yml` separately and start it by executing `docker compose up -d` in the same directory.
65-
66-
This runs the container on `http://localhost:8080/convert/`.
67-
68-
### Docker (local build for development)
69-
70-
Use the override file to build the image locally:
71-
72-
```bash
73-
docker compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up --build -d
74-
```
75-
76-
The first Docker build is expected to be slow because Chromium and related system packages are installed in the build stage (needed for puppeteer in `buildCache.js`). Later builds are usually much faster due to Docker layer caching.
77-
78-
## Contributing
79-
80-
The best way to contribute is by adding support for new file formats (duh). Here's how that works:
81-
82-
### Creating a handler
83-
84-
Each "tool" used for conversion has to be normalized to a standard form - effectively a "wrapper" that abstracts away the internal processes. These wrappers are available in [src/handlers](src/handlers/).
85-
86-
Below is a super barebones handler that does absolutely nothing. You can use this as a starting point for adding a new format:
87-
88-
```ts
89-
// file: dummy.ts
90-
91-
import type { FileData, FileFormat, FormatHandler } from "../FormatHandler.ts";
92-
import CommonFormats from "src/CommonFormats.ts";
93-
94-
class dummyHandler implements FormatHandler {
95-
96-
public name: string = "dummy";
97-
public supportedFormats?: FileFormat[];
98-
public ready: boolean = false;
99-
100-
async init () {
101-
this.supportedFormats = [
102-
// Example PNG format, with both input and output disabled
103-
CommonFormats.PNG.builder("png")
104-
.markLossless()
105-
// .allowFrom()
106-
// .allowTo()
107-
];
108-
this.ready = true;
109-
}
110-
111-
async doConvert (
112-
inputFiles: FileData[],
113-
inputFormat: FileFormat,
114-
outputFormat: FileFormat
115-
): Promise<FileData[]> {
116-
const outputFiles: FileData[] = [];
117-
return outputFiles;
118-
}
119-
120-
}
121-
122-
export default dummyHandler;
123-
```
124-
125-
For more details on how all of these components work, refer to the doc comments in [src/FormatHandler.ts](src/FormatHandler.ts). You can also take a look at existing handlers to get a more practical example.
126-
127-
There are a few additional things that I want to point out in particular:
128-
129-
- Pay attention to the naming system. If your tool is called `dummy`, then the class should be called `dummyHandler`, and the file should be called `dummy.ts`.
130-
- The handler is responsible for setting the output file's name. This is done to allow for flexibility in rare cases where the _full_ file name matters. Of course, in most cases, you'll only have to swap the file extension.
131-
- The handler is also responsible for ensuring that any byte buffers that enter or exit the handler _do not get mutated_. If necessary, clone the buffer by wrapping it in `new Uint8Array()`.
132-
- When handling MIME types, run them through [normalizeMimeType](src/normalizeMimeType.ts) first. One file can have multiple valid MIME types, which isn't great when you're trying to match them algorithmically.
133-
- When implementing a new file format, please treat the file as the media that it represents, not the data that it contains. For example, if you were making an SVG handler, you should treat the file as an _image_, not as XML.
134-
135-
### Adding dependencies
136-
137-
If your tool requires an external dependency (which it likely does), there are currently two well-established ways of going about this:
138-
139-
- If it's an `npm` package, just install it to the project like you normally would.
140-
- If it's a Git repository, add it as a submodule to [src/handlers](src/handlers).
141-
142-
**Please try to avoid CDNs (Content Delivery Networks).** They're really cool on paper, but they don't work well with TypeScript, and each one introduces a tiny bit of instability. For a project that leans heavily on external dependencies, those bits of instability can add up fast.
143-
144-
- If you need to load a WebAssembly binary (or similar), add its path to [vite.config.js](vite.config.js) and target it under `/convert/wasm/`. **Do not link to node_modules**.
47+
**ORIGINAL MAINTAINER:** [p2r3/convert](https://github.com/p2r3/convert) — the universal in-browser converter.

0 commit comments

Comments
 (0)