@nemu.pm/tachiyomi-runtime 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.d.ts +49 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +8 -0
- package/dist/http.js.map +1 -0
- package/dist/image-codec.browser.d.ts +12 -0
- package/dist/image-codec.browser.d.ts.map +1 -0
- package/dist/image-codec.browser.js +133 -0
- package/dist/image-codec.browser.js.map +1 -0
- package/dist/image-codec.d.ts +6 -0
- package/dist/image-codec.d.ts.map +1 -0
- package/dist/image-codec.js +6 -0
- package/dist/image-codec.js.map +1 -0
- package/dist/image-codec.node.d.ts +12 -0
- package/dist/image-codec.node.d.ts.map +1 -0
- package/dist/image-codec.node.js +95 -0
- package/dist/image-codec.node.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/index.node.d.ts +12 -0
- package/dist/index.node.d.ts.map +1 -0
- package/dist/index.node.js +14 -0
- package/dist/index.node.js.map +1 -0
- package/dist/runtime.d.ts +87 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +184 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +169 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +46 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
- package/src/http.ts +53 -0
- package/src/image-codec.browser.ts +152 -0
- package/src/image-codec.node.ts +119 -0
- package/src/image-codec.ts +5 -0
- package/src/index.node.ts +50 -0
- package/src/index.ts +75 -0
- package/src/runtime.ts +314 -0
- package/src/types.ts +211 -0
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Bridge interface for Tachiyomi extensions
|
|
3
|
+
*
|
|
4
|
+
* Extensions use synchronous HTTP calls internally (via OkHttp shim).
|
|
5
|
+
* Consumers must provide an implementation that bridges to their environment.
|
|
6
|
+
*/
|
|
7
|
+
export interface HttpRequest {
|
|
8
|
+
url: string;
|
|
9
|
+
method: string;
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
body?: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface HttpResponse {
|
|
14
|
+
status: number;
|
|
15
|
+
statusText: string;
|
|
16
|
+
headers: Record<string, string>;
|
|
17
|
+
/** Response body as string. For binary responses, this should be base64 encoded. */
|
|
18
|
+
body: string;
|
|
19
|
+
/** If true, body is base64 encoded binary data */
|
|
20
|
+
isBinary?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* HTTP bridge that extensions call for network requests.
|
|
24
|
+
*
|
|
25
|
+
* IMPORTANT: Extensions expect SYNCHRONOUS responses.
|
|
26
|
+
* In browsers, this typically means running in a Web Worker with sync XHR.
|
|
27
|
+
*/
|
|
28
|
+
export interface HttpBridge {
|
|
29
|
+
/**
|
|
30
|
+
* Perform an HTTP request synchronously.
|
|
31
|
+
*
|
|
32
|
+
* @param request - The HTTP request to make
|
|
33
|
+
* @param wantBytes - If true, return body as base64-encoded binary
|
|
34
|
+
* @returns HTTP response (must be synchronous!)
|
|
35
|
+
*/
|
|
36
|
+
request(request: HttpRequest, wantBytes: boolean): HttpResponse;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Internal format used by Kotlin/JS extensions.
|
|
40
|
+
* The runtime converts between this and the public HttpBridge interface.
|
|
41
|
+
*/
|
|
42
|
+
export interface KotlinHttpResult {
|
|
43
|
+
status: number;
|
|
44
|
+
statusText: string;
|
|
45
|
+
headersJson: string;
|
|
46
|
+
body: string;
|
|
47
|
+
error: string | null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,YAAY,CAAC;CACjE;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB"}
|
package/dist/http.js
ADDED
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec for browser environments.
|
|
3
|
+
* Uses native OffscreenCanvas + createImageBitmap.
|
|
4
|
+
*/
|
|
5
|
+
export declare function decodeImageAsync(base64: string): Promise<{
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
pixels: string;
|
|
9
|
+
} | null>;
|
|
10
|
+
export declare function encodeImageAsync(pixelsBase64: string, width: number, height: number, format: string, quality: number): Promise<string | null>;
|
|
11
|
+
export declare function registerImageCodec(): void;
|
|
12
|
+
//# sourceMappingURL=image-codec.browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.browser.d.ts","sourceRoot":"","sources":["../src/image-codec.browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA0CxH;AAED,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6CxB;AA+CD,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec for browser environments.
|
|
3
|
+
* Uses native OffscreenCanvas + createImageBitmap.
|
|
4
|
+
*/
|
|
5
|
+
export async function decodeImageAsync(base64) {
|
|
6
|
+
try {
|
|
7
|
+
const binary = atob(base64);
|
|
8
|
+
const bytes = new Uint8Array(binary.length);
|
|
9
|
+
for (let i = 0; i < binary.length; i++) {
|
|
10
|
+
bytes[i] = binary.charCodeAt(i);
|
|
11
|
+
}
|
|
12
|
+
const blob = new Blob([bytes]);
|
|
13
|
+
const bitmap = await createImageBitmap(blob);
|
|
14
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
15
|
+
const ctx = canvas.getContext("2d");
|
|
16
|
+
if (!ctx)
|
|
17
|
+
return null;
|
|
18
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
19
|
+
const imageData = ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
|
20
|
+
// Convert RGBA to ARGB (Android Bitmap format)
|
|
21
|
+
const pixels = new Int32Array(bitmap.width * bitmap.height);
|
|
22
|
+
const rgba = imageData.data;
|
|
23
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
24
|
+
const r = rgba[i * 4];
|
|
25
|
+
const g = rgba[i * 4 + 1];
|
|
26
|
+
const b = rgba[i * 4 + 2];
|
|
27
|
+
const a = rgba[i * 4 + 3];
|
|
28
|
+
pixels[i] = ((a << 24) | (r << 16) | (g << 8) | b) | 0;
|
|
29
|
+
}
|
|
30
|
+
// Convert to base64
|
|
31
|
+
const pixelBuffer = new Uint8Array(pixels.buffer);
|
|
32
|
+
let pixelBase64 = "";
|
|
33
|
+
const CHUNK_SIZE = 32768;
|
|
34
|
+
for (let i = 0; i < pixelBuffer.length; i += CHUNK_SIZE) {
|
|
35
|
+
const chunk = pixelBuffer.subarray(i, Math.min(i + CHUNK_SIZE, pixelBuffer.length));
|
|
36
|
+
pixelBase64 += String.fromCharCode.apply(null, chunk);
|
|
37
|
+
}
|
|
38
|
+
return { width: bitmap.width, height: bitmap.height, pixels: btoa(pixelBase64) };
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
console.error("[ImageCodec] decode error:", e);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function encodeImageAsync(pixelsBase64, width, height, format, quality) {
|
|
46
|
+
try {
|
|
47
|
+
const binary = atob(pixelsBase64);
|
|
48
|
+
const pixelBuffer = new Uint8Array(binary.length);
|
|
49
|
+
for (let i = 0; i < binary.length; i++) {
|
|
50
|
+
pixelBuffer[i] = binary.charCodeAt(i);
|
|
51
|
+
}
|
|
52
|
+
const pixels = new Int32Array(pixelBuffer.buffer);
|
|
53
|
+
// Convert ARGB to RGBA
|
|
54
|
+
const rgba = new Uint8ClampedArray(width * height * 4);
|
|
55
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
56
|
+
const pixel = pixels[i];
|
|
57
|
+
rgba[i * 4] = (pixel >> 16) & 0xff;
|
|
58
|
+
rgba[i * 4 + 1] = (pixel >> 8) & 0xff;
|
|
59
|
+
rgba[i * 4 + 2] = pixel & 0xff;
|
|
60
|
+
rgba[i * 4 + 3] = (pixel >> 24) & 0xff;
|
|
61
|
+
}
|
|
62
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
63
|
+
const ctx = canvas.getContext("2d");
|
|
64
|
+
if (!ctx)
|
|
65
|
+
return null;
|
|
66
|
+
const imageData = new ImageData(rgba, width, height);
|
|
67
|
+
ctx.putImageData(imageData, 0, 0);
|
|
68
|
+
const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
|
|
69
|
+
const blob = await canvas.convertToBlob({
|
|
70
|
+
type: mimeType,
|
|
71
|
+
quality: format === "jpeg" ? quality / 100 : undefined,
|
|
72
|
+
});
|
|
73
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
74
|
+
const outputBytes = new Uint8Array(arrayBuffer);
|
|
75
|
+
let result = "";
|
|
76
|
+
const CHUNK_SIZE = 32768;
|
|
77
|
+
for (let i = 0; i < outputBytes.length; i += CHUNK_SIZE) {
|
|
78
|
+
const chunk = outputBytes.subarray(i, Math.min(i + CHUNK_SIZE, outputBytes.length));
|
|
79
|
+
result += String.fromCharCode.apply(null, chunk);
|
|
80
|
+
}
|
|
81
|
+
return btoa(result);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
console.error("[ImageCodec] encode error:", e);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Sync wrappers using XHR blocking trick (works in Web Workers)
|
|
89
|
+
function decodeImageSync(base64) {
|
|
90
|
+
try {
|
|
91
|
+
let result = null;
|
|
92
|
+
let done = false;
|
|
93
|
+
decodeImageAsync(base64).then(r => { result = r; done = true; }).catch(() => { done = true; });
|
|
94
|
+
const start = Date.now();
|
|
95
|
+
while (!done && Date.now() - start < 30000) {
|
|
96
|
+
const xhr = new XMLHttpRequest();
|
|
97
|
+
xhr.open("GET", "data:text/plain,", false);
|
|
98
|
+
try {
|
|
99
|
+
xhr.send();
|
|
100
|
+
}
|
|
101
|
+
catch { }
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function encodeImageSync(pixelsBase64, width, height, format, quality) {
|
|
110
|
+
try {
|
|
111
|
+
let result = null;
|
|
112
|
+
let done = false;
|
|
113
|
+
encodeImageAsync(pixelsBase64, width, height, format, quality).then(r => { result = r; done = true; }).catch(() => { done = true; });
|
|
114
|
+
const start = Date.now();
|
|
115
|
+
while (!done && Date.now() - start < 30000) {
|
|
116
|
+
const xhr = new XMLHttpRequest();
|
|
117
|
+
xhr.open("GET", "data:text/plain,", false);
|
|
118
|
+
try {
|
|
119
|
+
xhr.send();
|
|
120
|
+
}
|
|
121
|
+
catch { }
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export function registerImageCodec() {
|
|
130
|
+
globalThis.tachiyomiDecodeImage = decodeImageSync;
|
|
131
|
+
globalThis.tachiyomiEncodeImage = encodeImageSync;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=image-codec.browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.browser.js","sourceRoot":"","sources":["../src/image-codec.browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAEtE,+CAA+C;QAC/C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;QAED,oBAAoB;QACpB,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,KAAK,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;YACpF,WAAW,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAA4B,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;IACnF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAAoB,EACpB,KAAa,EACb,MAAc,EACd,MAAc,EACd,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;QAClC,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElD,uBAAuB;QACvB,MAAM,IAAI,GAAG,IAAI,iBAAiB,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;QACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;YACnC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;YACtC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACzC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACrD,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;QAChE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;YACtC,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS;SACvD,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,UAAU,GAAG,KAAK,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;YACpF,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAA4B,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,SAAS,eAAe,CAAC,MAAc;IACrC,IAAI,CAAC;QACH,IAAI,MAAM,GAA6D,IAAI,CAAC;QAC5E,IAAI,IAAI,GAAG,KAAK,CAAC;QAEjB,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC;gBAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAC9B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACtB,YAAoB,EACpB,KAAa,EACb,MAAc,EACd,MAAc,EACd,OAAe;IAEf,IAAI,CAAC;QACH,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,IAAI,IAAI,GAAG,KAAK,CAAC;QAEjB,gBAAgB,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAErI,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC;gBAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QAC9B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAC/B,UAAsC,CAAC,oBAAoB,GAAG,eAAe,CAAC;IAC9E,UAAsC,CAAC,oBAAoB,GAAG,eAAe,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec - re-exports browser implementation as default.
|
|
3
|
+
* Node.js users get the node version via conditional exports.
|
|
4
|
+
*/
|
|
5
|
+
export { decodeImageAsync, encodeImageAsync, registerImageCodec } from "./image-codec.browser.js";
|
|
6
|
+
//# sourceMappingURL=image-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.d.ts","sourceRoot":"","sources":["../src/image-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec - re-exports browser implementation as default.
|
|
3
|
+
* Node.js users get the node version via conditional exports.
|
|
4
|
+
*/
|
|
5
|
+
export { decodeImageAsync, encodeImageAsync, registerImageCodec } from "./image-codec.browser.js";
|
|
6
|
+
//# sourceMappingURL=image-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.js","sourceRoot":"","sources":["../src/image-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec for Node.js/Bun environments.
|
|
3
|
+
* Uses the `canvas` package (node-canvas).
|
|
4
|
+
*/
|
|
5
|
+
export declare function decodeImageAsync(base64: string): Promise<{
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
pixels: string;
|
|
9
|
+
} | null>;
|
|
10
|
+
export declare function encodeImageAsync(pixelsBase64: string, width: number, height: number, format: string, quality: number): Promise<string | null>;
|
|
11
|
+
export declare function registerImageCodec(): void;
|
|
12
|
+
//# sourceMappingURL=image-codec.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.node.d.ts","sourceRoot":"","sources":["../src/image-codec.node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAuCxH;AAED,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwCxB;AAoBD,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image codec for Node.js/Bun environments.
|
|
3
|
+
* Uses the `canvas` package (node-canvas).
|
|
4
|
+
*/
|
|
5
|
+
import { createCanvas, loadImage, ImageData } from "canvas";
|
|
6
|
+
export async function decodeImageAsync(base64) {
|
|
7
|
+
try {
|
|
8
|
+
const binary = atob(base64);
|
|
9
|
+
const bytes = new Uint8Array(binary.length);
|
|
10
|
+
for (let i = 0; i < binary.length; i++) {
|
|
11
|
+
bytes[i] = binary.charCodeAt(i);
|
|
12
|
+
}
|
|
13
|
+
const img = await loadImage(Buffer.from(bytes));
|
|
14
|
+
const canvas = createCanvas(img.width, img.height);
|
|
15
|
+
const ctx = canvas.getContext("2d");
|
|
16
|
+
ctx.drawImage(img, 0, 0);
|
|
17
|
+
const imageData = ctx.getImageData(0, 0, img.width, img.height);
|
|
18
|
+
// Convert RGBA to ARGB (Android Bitmap format)
|
|
19
|
+
const pixels = new Int32Array(img.width * img.height);
|
|
20
|
+
const rgba = imageData.data;
|
|
21
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
22
|
+
const r = rgba[i * 4];
|
|
23
|
+
const g = rgba[i * 4 + 1];
|
|
24
|
+
const b = rgba[i * 4 + 2];
|
|
25
|
+
const a = rgba[i * 4 + 3];
|
|
26
|
+
pixels[i] = ((a << 24) | (r << 16) | (g << 8) | b) | 0;
|
|
27
|
+
}
|
|
28
|
+
// Convert to base64
|
|
29
|
+
const pixelBuffer = new Uint8Array(pixels.buffer);
|
|
30
|
+
let pixelBase64 = "";
|
|
31
|
+
const CHUNK_SIZE = 32768;
|
|
32
|
+
for (let i = 0; i < pixelBuffer.length; i += CHUNK_SIZE) {
|
|
33
|
+
const chunk = pixelBuffer.subarray(i, Math.min(i + CHUNK_SIZE, pixelBuffer.length));
|
|
34
|
+
pixelBase64 += String.fromCharCode.apply(null, chunk);
|
|
35
|
+
}
|
|
36
|
+
return { width: img.width, height: img.height, pixels: btoa(pixelBase64) };
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.error("[ImageCodec] decode error:", e);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function encodeImageAsync(pixelsBase64, width, height, format, quality) {
|
|
44
|
+
try {
|
|
45
|
+
const binary = atob(pixelsBase64);
|
|
46
|
+
const pixelBuffer = new Uint8Array(binary.length);
|
|
47
|
+
for (let i = 0; i < binary.length; i++) {
|
|
48
|
+
pixelBuffer[i] = binary.charCodeAt(i);
|
|
49
|
+
}
|
|
50
|
+
const pixels = new Int32Array(pixelBuffer.buffer);
|
|
51
|
+
// Convert ARGB to RGBA
|
|
52
|
+
const rgba = new Uint8ClampedArray(width * height * 4);
|
|
53
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
54
|
+
const pixel = pixels[i];
|
|
55
|
+
rgba[i * 4] = (pixel >> 16) & 0xff;
|
|
56
|
+
rgba[i * 4 + 1] = (pixel >> 8) & 0xff;
|
|
57
|
+
rgba[i * 4 + 2] = pixel & 0xff;
|
|
58
|
+
rgba[i * 4 + 3] = (pixel >> 24) & 0xff;
|
|
59
|
+
}
|
|
60
|
+
const canvas = createCanvas(width, height);
|
|
61
|
+
const ctx = canvas.getContext("2d");
|
|
62
|
+
const imageData = new ImageData(rgba, width, height);
|
|
63
|
+
ctx.putImageData(imageData, 0, 0);
|
|
64
|
+
const buffer = format === "jpeg"
|
|
65
|
+
? canvas.toBuffer("image/jpeg", { quality: quality / 100 })
|
|
66
|
+
: canvas.toBuffer("image/png");
|
|
67
|
+
const outputBytes = new Uint8Array(buffer);
|
|
68
|
+
let result = "";
|
|
69
|
+
const CHUNK_SIZE = 32768;
|
|
70
|
+
for (let i = 0; i < outputBytes.length; i += CHUNK_SIZE) {
|
|
71
|
+
const chunk = outputBytes.subarray(i, Math.min(i + CHUNK_SIZE, outputBytes.length));
|
|
72
|
+
result += String.fromCharCode.apply(null, chunk);
|
|
73
|
+
}
|
|
74
|
+
return btoa(result);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
console.error("[ImageCodec] encode error:", e);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Sync wrappers - in Node we can't truly block, so these return null
|
|
82
|
+
// Tests should use async versions directly
|
|
83
|
+
function decodeImageSync(base64) {
|
|
84
|
+
console.warn("[ImageCodec] Sync decode not supported in Node.js, use decodeImageAsync instead");
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
function encodeImageSync(pixelsBase64, width, height, format, quality) {
|
|
88
|
+
console.warn("[ImageCodec] Sync encode not supported in Node.js, use encodeImageAsync instead");
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
export function registerImageCodec() {
|
|
92
|
+
globalThis.tachiyomiDecodeImage = decodeImageSync;
|
|
93
|
+
globalThis.tachiyomiEncodeImage = encodeImageSync;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=image-codec.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-codec.node.js","sourceRoot":"","sources":["../src/image-codec.node.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tachiyomi-js/runtime
|
|
3
|
+
*
|
|
4
|
+
* Runtime for loading and executing Tachiyomi extensions compiled to JavaScript.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createRuntime, type Manga, type MangasPage } from '@tachiyomi-js/runtime';
|
|
9
|
+
*
|
|
10
|
+
* // Create runtime with your HTTP implementation
|
|
11
|
+
* const runtime = createRuntime({
|
|
12
|
+
* request(req, wantBytes) {
|
|
13
|
+
* // Implement sync HTTP (e.g., XMLHttpRequest in a Web Worker)
|
|
14
|
+
* return { status: 200, statusText: 'OK', headers: {}, body: '...' };
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Load an extension
|
|
19
|
+
* const ext = runtime.loadExtension(extensionJsCode);
|
|
20
|
+
*
|
|
21
|
+
* // Get sources
|
|
22
|
+
* const sources = ext.getSources();
|
|
23
|
+
* console.log(sources[0].name); // "MangaDex"
|
|
24
|
+
*
|
|
25
|
+
* // Fetch manga
|
|
26
|
+
* const popular: MangasPage = ext.getPopularManga(sources[0].id, 1);
|
|
27
|
+
* console.log(popular.mangas[0].title);
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
export type { Manga, Chapter, Page, MangasPage, SourceInfo, ExtensionManifest, Author, FilterState, FilterHeader, FilterSeparator, FilterText, FilterCheckBox, FilterTriState, FilterSort, FilterSelect, FilterGroup, FilterStateUpdate, SettingsSchema, PreferenceSchema, } from './types';
|
|
33
|
+
export { MangaStatus, filterToStateUpdate, buildFilterStateJson } from './types';
|
|
34
|
+
export type { HttpBridge, HttpRequest, HttpResponse, } from './http';
|
|
35
|
+
export { TachiyomiRuntime, createRuntime, type ExtensionInstance, } from './runtime';
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAOH,YAAY,EACV,KAAK,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGjF,YAAY,EACV,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tachiyomi-js/runtime
|
|
3
|
+
*
|
|
4
|
+
* Runtime for loading and executing Tachiyomi extensions compiled to JavaScript.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createRuntime, type Manga, type MangasPage } from '@tachiyomi-js/runtime';
|
|
9
|
+
*
|
|
10
|
+
* // Create runtime with your HTTP implementation
|
|
11
|
+
* const runtime = createRuntime({
|
|
12
|
+
* request(req, wantBytes) {
|
|
13
|
+
* // Implement sync HTTP (e.g., XMLHttpRequest in a Web Worker)
|
|
14
|
+
* return { status: 200, statusText: 'OK', headers: {}, body: '...' };
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Load an extension
|
|
19
|
+
* const ext = runtime.loadExtension(extensionJsCode);
|
|
20
|
+
*
|
|
21
|
+
* // Get sources
|
|
22
|
+
* const sources = ext.getSources();
|
|
23
|
+
* console.log(sources[0].name); // "MangaDex"
|
|
24
|
+
*
|
|
25
|
+
* // Fetch manga
|
|
26
|
+
* const popular: MangasPage = ext.getPopularManga(sources[0].id, 1);
|
|
27
|
+
* console.log(popular.mangas[0].title);
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @packageDocumentation
|
|
31
|
+
*/
|
|
32
|
+
// Register browser image codec on import
|
|
33
|
+
import { registerImageCodec } from './image-codec.browser';
|
|
34
|
+
registerImageCodec();
|
|
35
|
+
// Enums and functions (exported as values)
|
|
36
|
+
export { MangaStatus, filterToStateUpdate, buildFilterStateJson } from './types';
|
|
37
|
+
// Runtime
|
|
38
|
+
export { TachiyomiRuntime, createRuntime, } from './runtime';
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,yCAAyC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,kBAAkB,EAAE,CAAC;AAyBrB,2CAA2C;AAC3C,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AASjF,UAAU;AACV,OAAO,EACL,gBAAgB,EAChB,aAAa,GAEd,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tachiyomi-js/runtime - Node.js/Bun entry point
|
|
3
|
+
*
|
|
4
|
+
* Uses the `canvas` package for image manipulation.
|
|
5
|
+
* Install with: npm install canvas@next
|
|
6
|
+
*/
|
|
7
|
+
export type { Manga, Chapter, Page, MangasPage, SourceInfo, ExtensionManifest, Author, FilterState, FilterHeader, FilterSeparator, FilterText, FilterCheckBox, FilterTriState, FilterSort, FilterSelect, FilterGroup, FilterStateUpdate, SettingsSchema, PreferenceSchema, } from './types';
|
|
8
|
+
export { MangaStatus, filterToStateUpdate, buildFilterStateJson } from './types';
|
|
9
|
+
export type { HttpBridge, HttpRequest, HttpResponse, } from './http';
|
|
10
|
+
export { TachiyomiRuntime, createRuntime, type ExtensionInstance, } from './runtime';
|
|
11
|
+
export { decodeImageAsync, encodeImageAsync } from './image-codec.node';
|
|
12
|
+
//# sourceMappingURL=index.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../src/index.node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,YAAY,EACV,KAAK,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEjF,YAAY,EACV,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tachiyomi-js/runtime - Node.js/Bun entry point
|
|
3
|
+
*
|
|
4
|
+
* Uses the `canvas` package for image manipulation.
|
|
5
|
+
* Install with: npm install canvas@next
|
|
6
|
+
*/
|
|
7
|
+
// Register node image codec on import
|
|
8
|
+
import { registerImageCodec } from './image-codec.node';
|
|
9
|
+
registerImageCodec();
|
|
10
|
+
export { MangaStatus, filterToStateUpdate, buildFilterStateJson } from './types';
|
|
11
|
+
export { TachiyomiRuntime, createRuntime, } from './runtime';
|
|
12
|
+
// Also export async image functions (useful for testing in Node)
|
|
13
|
+
export { decodeImageAsync, encodeImageAsync } from './image-codec.node';
|
|
14
|
+
//# sourceMappingURL=index.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.node.js","sourceRoot":"","sources":["../src/index.node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sCAAsC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,kBAAkB,EAAE,CAAC;AAyBrB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAQjF,OAAO,EACL,gBAAgB,EAChB,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tachiyomi Extension Runtime
|
|
3
|
+
*
|
|
4
|
+
* Provides a clean API for loading and executing Tachiyomi extensions.
|
|
5
|
+
*/
|
|
6
|
+
import type { HttpBridge } from './http';
|
|
7
|
+
import type { Manga, Chapter, Page, MangasPage, SourceInfo, FilterState, SettingsSchema } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* A loaded extension instance with methods to interact with sources.
|
|
10
|
+
*/
|
|
11
|
+
export interface ExtensionInstance {
|
|
12
|
+
/** Get all sources provided by this extension */
|
|
13
|
+
getSources(): SourceInfo[];
|
|
14
|
+
/** Get popular manga from a source */
|
|
15
|
+
getPopularManga(sourceId: string, page: number): MangasPage;
|
|
16
|
+
/** Get latest updates from a source */
|
|
17
|
+
getLatestUpdates(sourceId: string, page: number): MangasPage;
|
|
18
|
+
/** Search for manga */
|
|
19
|
+
searchManga(sourceId: string, page: number, query: string): MangasPage;
|
|
20
|
+
/** Get full manga details */
|
|
21
|
+
getMangaDetails(sourceId: string, manga: Pick<Manga, 'url'>): Manga;
|
|
22
|
+
/** Get chapter list for a manga */
|
|
23
|
+
getChapterList(sourceId: string, manga: Pick<Manga, 'url'>): Chapter[];
|
|
24
|
+
/** Get page list for a chapter */
|
|
25
|
+
getPageList(sourceId: string, chapter: Pick<Chapter, 'url'>): Page[];
|
|
26
|
+
/** Get available filters for a source */
|
|
27
|
+
getFilterList(sourceId: string): FilterState[];
|
|
28
|
+
/** Reset filters to default state */
|
|
29
|
+
resetFilters(sourceId: string): void;
|
|
30
|
+
/** Apply filter state (for stateful filters) */
|
|
31
|
+
applyFilterState(sourceId: string, filterState: FilterState[]): void;
|
|
32
|
+
/** Get settings schema for a source */
|
|
33
|
+
getSettingsSchema(sourceId: string): SettingsSchema | null;
|
|
34
|
+
/** Update a preference value */
|
|
35
|
+
setPreference(sourceId: string, key: string, value: unknown): void;
|
|
36
|
+
/** Get source headers (includes Referer from headersBuilder) */
|
|
37
|
+
getHeaders(sourceId: string): Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Fetch image through source's client with interceptors.
|
|
40
|
+
* Required for sources with image descrambling/protection.
|
|
41
|
+
* Returns base64-encoded image bytes.
|
|
42
|
+
*/
|
|
43
|
+
fetchImage(sourceId: string, pageUrl: string, imageUrl: string): string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Tachiyomi extension runtime.
|
|
47
|
+
*
|
|
48
|
+
* Create one runtime per application, then use it to load extensions.
|
|
49
|
+
*/
|
|
50
|
+
export declare class TachiyomiRuntime {
|
|
51
|
+
private httpBridge;
|
|
52
|
+
constructor(httpBridge: HttpBridge);
|
|
53
|
+
/**
|
|
54
|
+
* Install the HTTP bridge on globalThis for Kotlin/JS to call.
|
|
55
|
+
*/
|
|
56
|
+
private installHttpBridge;
|
|
57
|
+
/**
|
|
58
|
+
* Load an extension from its JavaScript code.
|
|
59
|
+
*
|
|
60
|
+
* @param code - The compiled extension JavaScript
|
|
61
|
+
* @returns An ExtensionInstance for interacting with the extension's sources
|
|
62
|
+
*/
|
|
63
|
+
loadExtension(code: string): ExtensionInstance;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a Tachiyomi runtime with the given HTTP bridge.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { createRuntime } from '@tachiyomi-js/runtime';
|
|
71
|
+
*
|
|
72
|
+
* const runtime = createRuntime({
|
|
73
|
+
* request(req, wantBytes) {
|
|
74
|
+
* // Your HTTP implementation here
|
|
75
|
+
* const xhr = new XMLHttpRequest();
|
|
76
|
+
* xhr.open(req.method, req.url, false);
|
|
77
|
+
* // ...
|
|
78
|
+
* return { status: 200, body: '...', headers: {}, statusText: 'OK' };
|
|
79
|
+
* }
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* const ext = runtime.loadExtension(extensionCode);
|
|
83
|
+
* const sources = ext.getSources();
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function createRuntime(httpBridge: HttpBridge): TachiyomiRuntime;
|
|
87
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,QAAQ,CAAC;AAC3D,OAAO,KAAK,EACV,KAAK,EACL,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACf,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,UAAU,IAAI,UAAU,EAAE,CAAC;IAE3B,sCAAsC;IACtC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAE5D,uCAAuC;IACvC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC;IAE7D,uBAAuB;IACvB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;IAEvE,6BAA6B;IAC7B,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;IAEpE,mCAAmC;IACnC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC;IAEvE,kCAAkC;IAClC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;IAErE,yCAAyC;IACzC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IAE/C,qCAAqC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,gDAAgD;IAChD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAErE,uCAAuC;IACvC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IAE3D,gCAAgC;IAChC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAEnE,gEAAgE;IAChE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CACzE;AAiDD;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,EAAE,UAAU;IAKlC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;CAuB/C;AA4FD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAEtE"}
|