|
| 1 | +# [Convert to it!](https://convert.to.it/) |
| 2 | +**Truly universal online file converter.** |
| 3 | + |
| 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_. |
| 5 | + |
| 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. |
| 7 | + |
| 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. |
| 9 | + |
| 10 | +## Usage |
| 11 | + |
| 12 | +1. Go to [convert.to.it](https://convert.to.it/) |
| 13 | +2. Click the big blue box to add your file (or just drag it on to the window). |
| 14 | +3. An input format should have been automatically selected. If it wasn't, yikes! Try searching for it, or [open an issue](https://github.com/p2r3/convert/issues/new) if it's really not there. |
| 15 | +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. |
| 16 | +5. Click **Convert**! |
| 17 | +6. Hopefully, after a bit (or a lot) of thinking, the program will spit out the file you wanted. If not, [open an issue](https://github.com/p2r3/convert/issues/new) or cope and seethe. |
| 18 | + |
| 19 | +## Deployment |
| 20 | + |
| 21 | +Here's how to deploy this project locally: |
| 22 | + |
| 23 | +1. Clone this repository. |
| 24 | +2. Install [Bun](https://bun.sh/). |
| 25 | +3. Run `bun install` to install dependencies. |
| 26 | +4. Run `bunx vite` to start the development server. |
| 27 | + |
| 28 | +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. |
| 29 | + |
| 30 | +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. |
| 31 | + |
| 32 | +## Contributing |
| 33 | + |
| 34 | +The best way to contribute is by adding support for new file formats (duh). Here's how that works: |
| 35 | + |
| 36 | +### Creating a handler |
| 37 | + |
| 38 | +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/). |
| 39 | + |
| 40 | +Below is a super barebones handler that does absolutely nothing. You can use this as a starting point for adding a new format: |
| 41 | + |
| 42 | +```ts |
| 43 | +// file: dummy.ts |
| 44 | + |
| 45 | +import type { FileData, FileFormat, FormatHandler } from "../FormatHandler.ts"; |
| 46 | + |
| 47 | +class dummyHandler implements FormatHandler { |
| 48 | + |
| 49 | + public name: string = "dummy"; |
| 50 | + public supportedFormats: FileFormat[]; |
| 51 | + public ready: boolean = false; |
| 52 | + |
| 53 | + async init () { |
| 54 | + this.supportedFormats = [ |
| 55 | + { |
| 56 | + name: "Portable Network Graphics", |
| 57 | + format: "png", |
| 58 | + extension: "png", |
| 59 | + mime: "image/png", |
| 60 | + from: false, |
| 61 | + to: false, |
| 62 | + internal: "png" |
| 63 | + }, |
| 64 | + ]; |
| 65 | + this.ready = true; |
| 66 | + } |
| 67 | + |
| 68 | + async doConvert ( |
| 69 | + inputFiles: FileData[], |
| 70 | + inputFormat: FileFormat, |
| 71 | + outputFormat: FileFormat |
| 72 | + ): Promise<FileData[]> { |
| 73 | + const outputFiles: FileData[] = []; |
| 74 | + return outputFiles; |
| 75 | + } |
| 76 | + |
| 77 | +} |
| 78 | + |
| 79 | +export default dummyHandler; |
| 80 | +``` |
| 81 | + |
| 82 | +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. |
| 83 | + |
| 84 | +There are a few additional things that I want to point out in particular: |
| 85 | + |
| 86 | +- 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`. |
| 87 | +- 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. |
| 88 | +- 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()`. |
| 89 | + |
| 90 | +### Adding dependencies |
| 91 | + |
| 92 | +If your tool requires an external dependency (which it likely does), there are currently two well-established ways of going about this: |
| 93 | + |
| 94 | +- If it's an `npm` package, just install it to the project like you normally would. |
| 95 | +- If it's a Git repository, add it as a submodule to [src/handlers](src/handlers). |
| 96 | + |
| 97 | +**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. |
| 98 | + |
| 99 | +- 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**. |
0 commit comments