Skip to content

Commit 46cd02f

Browse files
committed
add documentation and readme
1 parent aa5599f commit 46cd02f

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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**.

src/FormatHandler.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,61 @@
11
export interface FileFormat {
2+
/** Format description (long name) for displaying to the user. */
23
name: string;
4+
/** Short, "formal" name for displaying to the user. */
35
format: string;
6+
/** File extension. */
47
extension: string;
8+
/** MIME type. */
59
mime: string;
10+
/** Whether conversion **from** this format is supported. */
611
from: boolean;
12+
/** Whether conversion **to** this format is supported. */
713
to: boolean;
14+
/** Format identifier for the handler's internal reference. */
815
internal: string;
916
}
1017

1118
export interface FileData {
19+
/** File name with extension. */
1220
name: string;
21+
/**
22+
* File contents in bytes.
23+
*
24+
* **Please note:** _handlers_ are responsible for ensuring the lifetime
25+
* and consistency of this buffer. If you're not sure that your handler
26+
* won't modify it, wrap it in `new Uint8Array()`.
27+
*/
1328
readonly bytes: Uint8Array;
1429
}
1530

31+
/**
32+
* Establishes a common interface for converting between file formats.
33+
* Often a "wrapper" for existing tools.
34+
*/
1635
export interface FormatHandler {
36+
/** Name of the tool being wrapped (e.g. "FFmpeg"). */
1737
name: string;
38+
/** List of supported input/output {@link FileFormat}s. */
1839
supportedFormats?: FileFormat[];
40+
/**
41+
* Whether the handler is ready for use. Should be set in {@link init}.
42+
* If true, {@link doConvert} is expected to work.
43+
*/
1944
ready: boolean;
45+
/**
46+
* Initializes the handler if necessary.
47+
* Should set {@link ready} to true.
48+
*/
2049
init: () => Promise<void>;
50+
/**
51+
* Performs the actual file conversion.
52+
* @param inputFiles Array of {@link FileData} entries, one per input file.
53+
* @param inputFormat Input {@link FileFormat}, the same for all inputs.
54+
* @param outputFormat Output {@link FileFormat}, the same for all outputs.
55+
* @param args Optional arguments as a string array.
56+
* Can be used to perform recursion with different settings.
57+
* @returns Array of {@link FileData} entries, one per generated output file.
58+
*/
2159
doConvert: (
2260
inputFiles: FileData[],
2361
inputFormat: FileFormat,

0 commit comments

Comments
 (0)