@oh-my-pi/pi-natives 8.12.9 → 8.13.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/package.json +2 -2
- package/src/highlight/index.ts +55 -0
- package/src/html/index.ts +47 -0
- package/src/html/types.ts +25 -0
- package/src/html/worker.ts +40 -0
- package/src/image/index.ts +6 -3
- package/src/index.ts +22 -1
- package/src/pool.ts +92 -8
- package/wasm/pi_natives.d.ts +31 -0
- package/wasm/pi_natives.js +116 -0
- package/wasm/pi_natives_bg.wasm +0 -0
- package/wasm/pi_natives_bg.wasm.d.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-natives",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.13.0",
|
|
4
4
|
"description": "Native Rust functionality compiled to WebAssembly via wasm-bindgen",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"directory": "packages/natives"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@oh-my-pi/pi-utils": "8.
|
|
33
|
+
"@oh-my-pi/pi-utils": "8.13.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^25.0.10"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting powered by WASM (syntect).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as wasm from "../../wasm/pi_natives";
|
|
6
|
+
|
|
7
|
+
type WasmHighlightExports = typeof wasm & {
|
|
8
|
+
highlight_code: (code: string, lang: string | null | undefined, colors: HighlightColors) => string;
|
|
9
|
+
supports_language: (lang: string) => boolean;
|
|
10
|
+
get_supported_languages: () => string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const wasmHighlight = wasm as WasmHighlightExports;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Theme colors for syntax highlighting.
|
|
17
|
+
* Each color should be an ANSI escape sequence (e.g., "\x1b[38;2;255;0;0m").
|
|
18
|
+
*/
|
|
19
|
+
export interface HighlightColors {
|
|
20
|
+
comment: string;
|
|
21
|
+
keyword: string;
|
|
22
|
+
function: string;
|
|
23
|
+
variable: string;
|
|
24
|
+
string: string;
|
|
25
|
+
number: string;
|
|
26
|
+
type: string;
|
|
27
|
+
operator: string;
|
|
28
|
+
punctuation: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Highlight code with syntax coloring.
|
|
33
|
+
*
|
|
34
|
+
* @param code - The source code to highlight
|
|
35
|
+
* @param lang - Optional language identifier (e.g., "rust", "typescript", "python")
|
|
36
|
+
* @param colors - Theme colors as ANSI escape sequences
|
|
37
|
+
* @returns Highlighted code as a single string with ANSI color codes
|
|
38
|
+
*/
|
|
39
|
+
export function highlightCode(code: string, lang: string | undefined, colors: HighlightColors): string {
|
|
40
|
+
return wasmHighlight.highlight_code(code, lang, colors);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if a language is supported for highlighting.
|
|
45
|
+
*/
|
|
46
|
+
export function supportsLanguage(lang: string): boolean {
|
|
47
|
+
return wasmHighlight.supports_language(lang);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get list of all supported languages.
|
|
52
|
+
*/
|
|
53
|
+
export function getSupportedLanguages(): string[] {
|
|
54
|
+
return wasmHighlight.get_supported_languages();
|
|
55
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML to Markdown conversion powered by WASM.
|
|
3
|
+
*
|
|
4
|
+
* Conversion happens in a worker thread to avoid blocking the main thread.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { type RequestOptions, WorkerPool } from "../pool";
|
|
8
|
+
import type { HtmlRequest, HtmlResponse, HtmlToMarkdownOptions } from "./types";
|
|
9
|
+
|
|
10
|
+
export type { HtmlToMarkdownOptions } from "./types";
|
|
11
|
+
|
|
12
|
+
const pool = new WorkerPool<HtmlRequest, HtmlResponse>({
|
|
13
|
+
workerUrl: new URL("./worker.ts", import.meta.url).href,
|
|
14
|
+
maxWorkers: 2,
|
|
15
|
+
idleTimeoutMs: 30_000,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Convert HTML to Markdown.
|
|
20
|
+
*
|
|
21
|
+
* @param html - HTML content to convert
|
|
22
|
+
* @param options - Conversion options
|
|
23
|
+
* @returns Markdown text
|
|
24
|
+
*/
|
|
25
|
+
export async function htmlToMarkdown(
|
|
26
|
+
html: string,
|
|
27
|
+
options?: HtmlToMarkdownOptions,
|
|
28
|
+
req?: RequestOptions,
|
|
29
|
+
): Promise<string> {
|
|
30
|
+
const response = await pool.request<Extract<HtmlResponse, { type: "converted" }>>(
|
|
31
|
+
{
|
|
32
|
+
type: "convert",
|
|
33
|
+
html,
|
|
34
|
+
options,
|
|
35
|
+
},
|
|
36
|
+
req,
|
|
37
|
+
);
|
|
38
|
+
return response.markdown;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Terminate the HTML worker pool.
|
|
43
|
+
* Call this when shutting down to clean up resources.
|
|
44
|
+
*/
|
|
45
|
+
export function terminate(): void {
|
|
46
|
+
pool.terminate();
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for HTML to Markdown worker communication.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface HtmlToMarkdownOptions {
|
|
6
|
+
/** Remove navigation elements, forms, headers, footers */
|
|
7
|
+
cleanContent?: boolean;
|
|
8
|
+
/** Skip images during conversion */
|
|
9
|
+
skipImages?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type HtmlRequest =
|
|
13
|
+
| { type: "init"; id: number }
|
|
14
|
+
| { type: "destroy" }
|
|
15
|
+
| {
|
|
16
|
+
type: "convert";
|
|
17
|
+
id: number;
|
|
18
|
+
html: string;
|
|
19
|
+
options?: HtmlToMarkdownOptions;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type HtmlResponse =
|
|
23
|
+
| { type: "ready"; id: number }
|
|
24
|
+
| { type: "error"; id: number; error: string }
|
|
25
|
+
| { type: "converted"; id: number; markdown: string };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker for HTML to Markdown conversion.
|
|
3
|
+
* Uses WASM for actual conversion.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { html_to_markdown } from "../../wasm/pi_natives";
|
|
7
|
+
import type { HtmlRequest, HtmlResponse } from "./types";
|
|
8
|
+
|
|
9
|
+
declare const self: Worker;
|
|
10
|
+
|
|
11
|
+
function respond(msg: HtmlResponse): void {
|
|
12
|
+
self.postMessage(msg);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
self.addEventListener("message", (e: MessageEvent<HtmlRequest>) => {
|
|
16
|
+
const msg = e.data;
|
|
17
|
+
|
|
18
|
+
switch (msg.type) {
|
|
19
|
+
case "init":
|
|
20
|
+
respond({ type: "ready", id: msg.id });
|
|
21
|
+
break;
|
|
22
|
+
|
|
23
|
+
case "destroy":
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case "convert": {
|
|
27
|
+
try {
|
|
28
|
+
const markdown = html_to_markdown(msg.html, msg.options);
|
|
29
|
+
respond({ type: "converted", id: msg.id, markdown });
|
|
30
|
+
} catch (err) {
|
|
31
|
+
respond({
|
|
32
|
+
type: "error",
|
|
33
|
+
id: msg.id,
|
|
34
|
+
error: err instanceof Error ? err.message : String(err),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
package/src/image/index.ts
CHANGED
|
@@ -49,9 +49,12 @@ export class PhotonImage {
|
|
|
49
49
|
* The bytes are transferred to the worker (zero-copy).
|
|
50
50
|
*/
|
|
51
51
|
static async new_from_byteslice(bytes: Uint8Array): Promise<PhotonImage> {
|
|
52
|
-
const response = await pool.request<Extract<ImageResponse, { type: "loaded" }>>(
|
|
53
|
-
bytes
|
|
54
|
-
|
|
52
|
+
const response = await pool.request<Extract<ImageResponse, { type: "loaded" }>>(
|
|
53
|
+
{ type: "load", bytes },
|
|
54
|
+
{
|
|
55
|
+
transfer: [bytes.buffer],
|
|
56
|
+
},
|
|
57
|
+
);
|
|
55
58
|
return new PhotonImage(response.handle, response.width, response.height);
|
|
56
59
|
}
|
|
57
60
|
|
package/src/index.ts
CHANGED
|
@@ -146,8 +146,29 @@ export {
|
|
|
146
146
|
visibleWidth,
|
|
147
147
|
} from "./text/index";
|
|
148
148
|
|
|
149
|
+
// =============================================================================
|
|
150
|
+
// Syntax highlighting
|
|
151
|
+
// =============================================================================
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
getSupportedLanguages,
|
|
155
|
+
type HighlightColors,
|
|
156
|
+
highlightCode,
|
|
157
|
+
supportsLanguage,
|
|
158
|
+
} from "./highlight/index";
|
|
159
|
+
|
|
160
|
+
// =============================================================================
|
|
161
|
+
// HTML to Markdown
|
|
162
|
+
// =============================================================================
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
type HtmlToMarkdownOptions,
|
|
166
|
+
htmlToMarkdown,
|
|
167
|
+
terminate as terminateHtmlWorker,
|
|
168
|
+
} from "./html/index";
|
|
169
|
+
|
|
149
170
|
// =============================================================================
|
|
150
171
|
// Worker Pool (shared infrastructure)
|
|
151
172
|
// =============================================================================
|
|
152
173
|
|
|
153
|
-
export { type BaseRequest, type BaseResponse, WorkerPool, type WorkerPoolOptions } from "./pool";
|
|
174
|
+
export { type BaseRequest, type BaseResponse, type RequestOptions, WorkerPool, type WorkerPoolOptions } from "./pool";
|
package/src/pool.ts
CHANGED
|
@@ -27,6 +27,17 @@ export interface WorkerPoolOptions {
|
|
|
27
27
|
idleTimeoutMs?: number;
|
|
28
28
|
/** Timeout for worker initialization in ms (default: 10000). */
|
|
29
29
|
initTimeoutMs?: number;
|
|
30
|
+
/** Grace period after request timeout before force-terminating stuck workers (default: 5000). */
|
|
31
|
+
stuckGracePeriodMs?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RequestOptions {
|
|
35
|
+
/** Timeout for this request in ms. After this, the promise rejects but worker gets a grace period. */
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
/** Abort signal for this request. */
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
/** Transfer list for postMessage. */
|
|
40
|
+
transfer?: ArrayBufferLike[];
|
|
30
41
|
}
|
|
31
42
|
|
|
32
43
|
interface PooledWorker {
|
|
@@ -39,7 +50,8 @@ interface PooledWorker {
|
|
|
39
50
|
interface PendingRequest<T> {
|
|
40
51
|
resolve: (result: T) => void;
|
|
41
52
|
reject: (error: Error) => void;
|
|
42
|
-
|
|
53
|
+
worker?: PooledWorker;
|
|
54
|
+
dispose?: () => void;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
/**
|
|
@@ -62,26 +74,51 @@ export class WorkerPool<TReq extends BaseRequest, TRes extends BaseResponse> {
|
|
|
62
74
|
maxWorkers: options.maxWorkers ?? 4,
|
|
63
75
|
idleTimeoutMs: options.idleTimeoutMs ?? 30_000,
|
|
64
76
|
initTimeoutMs: options.initTimeoutMs ?? 10_000,
|
|
77
|
+
stuckGracePeriodMs: options.stuckGracePeriodMs ?? 5_000,
|
|
65
78
|
};
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
/**
|
|
69
82
|
* Send a request to a worker and wait for the response.
|
|
70
83
|
* Workers are acquired from the pool (or created if under limit).
|
|
84
|
+
*
|
|
85
|
+
* @param msg - Request message
|
|
86
|
+
* @param options - Request options (timeout, transfer)
|
|
71
87
|
*/
|
|
72
88
|
async request<T extends TRes = TRes>(
|
|
73
89
|
msg: TReq | (Omit<TReq, "id"> & { id?: number }),
|
|
74
|
-
|
|
90
|
+
options?: RequestOptions,
|
|
75
91
|
): Promise<T> {
|
|
92
|
+
const { timeoutMs, signal, transfer } = options ?? {};
|
|
93
|
+
signal?.throwIfAborted();
|
|
94
|
+
|
|
76
95
|
const worker = await this.#acquireWorker();
|
|
77
96
|
const id = msg.id ?? this.#nextRequestId++;
|
|
78
97
|
const fullMsg = { ...msg, id } as TReq;
|
|
79
98
|
|
|
80
99
|
const { promise, resolve, reject } = Promise.withResolvers<T>();
|
|
81
|
-
|
|
100
|
+
const pending: PendingRequest<T> = {
|
|
82
101
|
resolve: resolve as (result: TRes) => void,
|
|
83
102
|
reject,
|
|
84
|
-
|
|
103
|
+
worker,
|
|
104
|
+
};
|
|
105
|
+
this.#pending.set(id, pending as PendingRequest<TRes>);
|
|
106
|
+
|
|
107
|
+
const onAbort = () => {
|
|
108
|
+
this.#handleRequestAbort(id, worker);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (timeoutMs && timeoutMs > 0 && signal) {
|
|
112
|
+
const combined = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
|
|
113
|
+
combined.addEventListener("abort", onAbort, { once: true });
|
|
114
|
+
pending.dispose = () => combined.removeEventListener("abort", onAbort);
|
|
115
|
+
} else if (timeoutMs && timeoutMs > 0) {
|
|
116
|
+
const timer = setTimeout(onAbort, timeoutMs);
|
|
117
|
+
pending.dispose = () => clearTimeout(timer);
|
|
118
|
+
} else if (signal) {
|
|
119
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
120
|
+
pending.dispose = () => signal.removeEventListener("abort", onAbort);
|
|
121
|
+
}
|
|
85
122
|
|
|
86
123
|
worker.currentRequestId = id;
|
|
87
124
|
if (transfer) {
|
|
@@ -109,7 +146,7 @@ export class WorkerPool<TReq extends BaseRequest, TRes extends BaseResponse> {
|
|
|
109
146
|
|
|
110
147
|
for (const pending of this.#pending.values()) {
|
|
111
148
|
pending.reject(new Error("Worker pool terminated"));
|
|
112
|
-
|
|
149
|
+
void pending.dispose?.();
|
|
113
150
|
}
|
|
114
151
|
this.#pending.clear();
|
|
115
152
|
}
|
|
@@ -144,7 +181,7 @@ export class WorkerPool<TReq extends BaseRequest, TRes extends BaseResponse> {
|
|
|
144
181
|
if (!pending) return;
|
|
145
182
|
|
|
146
183
|
this.#pending.delete(msg.id);
|
|
147
|
-
|
|
184
|
+
void pending.dispose?.();
|
|
148
185
|
|
|
149
186
|
if (msg.type === "error" && "error" in msg) {
|
|
150
187
|
pending.reject(new Error(msg.error ?? "Unknown error"));
|
|
@@ -163,11 +200,58 @@ export class WorkerPool<TReq extends BaseRequest, TRes extends BaseResponse> {
|
|
|
163
200
|
const pending = this.#pending.get(id);
|
|
164
201
|
if (pending) {
|
|
165
202
|
this.#pending.delete(id);
|
|
166
|
-
|
|
203
|
+
void pending.dispose?.();
|
|
167
204
|
pending.reject(error);
|
|
168
205
|
}
|
|
169
206
|
}
|
|
170
207
|
|
|
208
|
+
#handleRequestAbort(id: number, worker: PooledWorker): void {
|
|
209
|
+
const pending = this.#pending.get(id);
|
|
210
|
+
if (!pending) return;
|
|
211
|
+
|
|
212
|
+
pending.dispose = undefined;
|
|
213
|
+
pending.reject(new Error("Request timeout"));
|
|
214
|
+
|
|
215
|
+
if (this.#options.stuckGracePeriodMs > 0) {
|
|
216
|
+
const timer = setTimeout(() => {
|
|
217
|
+
this.#terminateStuckWorker(id, worker);
|
|
218
|
+
}, this.#options.stuckGracePeriodMs);
|
|
219
|
+
|
|
220
|
+
pending.dispose = () => {
|
|
221
|
+
clearTimeout(timer);
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#terminateStuckWorker(id: number, worker: PooledWorker): void {
|
|
227
|
+
const pending = this.#pending.get(id);
|
|
228
|
+
if (pending) {
|
|
229
|
+
this.#pending.delete(id);
|
|
230
|
+
void pending.dispose?.();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (worker.currentRequestId !== id) return;
|
|
234
|
+
if (!this.#pool.includes(worker)) return;
|
|
235
|
+
|
|
236
|
+
this.#removeWorker(worker);
|
|
237
|
+
|
|
238
|
+
if (this.#pool.length === 0 && this.#waiters.length > 0) {
|
|
239
|
+
this.#replenishPool();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async #replenishPool(): Promise<void> {
|
|
244
|
+
const worker = this.#createWorker();
|
|
245
|
+
worker.busy = true;
|
|
246
|
+
this.#pool.push(worker);
|
|
247
|
+
try {
|
|
248
|
+
await this.#initializeWorker(worker);
|
|
249
|
+
this.#releaseWorker(worker);
|
|
250
|
+
} catch {
|
|
251
|
+
this.#removeWorker(worker);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
171
255
|
#removeWorker(pooledWorker: PooledWorker): void {
|
|
172
256
|
const idx = this.#pool.indexOf(pooledWorker);
|
|
173
257
|
if (idx !== -1) {
|
|
@@ -227,7 +311,7 @@ export class WorkerPool<TReq extends BaseRequest, TRes extends BaseResponse> {
|
|
|
227
311
|
this.#pending.set(id, {
|
|
228
312
|
resolve: () => resolve(),
|
|
229
313
|
reject,
|
|
230
|
-
timeout,
|
|
314
|
+
dispose: () => clearTimeout(timeout),
|
|
231
315
|
} as PendingRequest<TRes>);
|
|
232
316
|
|
|
233
317
|
pooledWorker.worker.postMessage({ type: "init", id } satisfies BaseRequest);
|
package/wasm/pi_natives.d.ts
CHANGED
|
@@ -77,11 +77,35 @@ export enum SamplingFilter {
|
|
|
77
77
|
*/
|
|
78
78
|
export function extract_segments(line: string, before_end: number, after_start: number, after_len: number, strict_after: boolean): any;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Get list of supported languages.
|
|
82
|
+
*/
|
|
83
|
+
export function get_supported_languages(): string[];
|
|
84
|
+
|
|
80
85
|
/**
|
|
81
86
|
* Quick check if content matches a pattern.
|
|
82
87
|
*/
|
|
83
88
|
export function has_match(content: string, pattern: string, ignore_case: boolean, multiline: boolean): boolean;
|
|
84
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Highlight code and return ANSI-colored lines.
|
|
92
|
+
*
|
|
93
|
+
* # Arguments
|
|
94
|
+
* * `code` - The source code to highlight
|
|
95
|
+
* * `lang` - Language identifier (e.g., "rust", "typescript", "python")
|
|
96
|
+
* * `colors` - Theme colors as ANSI escape sequences
|
|
97
|
+
*
|
|
98
|
+
* # Returns
|
|
99
|
+
* Highlighted code with ANSI color codes, or the original code if highlighting
|
|
100
|
+
* fails.
|
|
101
|
+
*/
|
|
102
|
+
export function highlight_code(code: string, lang: string | null | undefined, colors: any): string;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Convert HTML to Markdown.
|
|
106
|
+
*/
|
|
107
|
+
export function html_to_markdown(html: string, options: any): string;
|
|
108
|
+
|
|
85
109
|
/**
|
|
86
110
|
* Resize an image to the specified dimensions.
|
|
87
111
|
*/
|
|
@@ -98,6 +122,13 @@ export function search(content: string, options: any): any;
|
|
|
98
122
|
*/
|
|
99
123
|
export function slice_with_width(line: string, start_col: number, length: number, strict: boolean): any;
|
|
100
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Check if a language is supported for highlighting.
|
|
127
|
+
* Returns true if the language has either direct support or a fallback
|
|
128
|
+
* mapping.
|
|
129
|
+
*/
|
|
130
|
+
export function supports_language(lang: string): boolean;
|
|
131
|
+
|
|
101
132
|
/**
|
|
102
133
|
* Truncate text to a visible width, preserving ANSI codes.
|
|
103
134
|
*/
|
package/wasm/pi_natives.js
CHANGED
|
@@ -226,6 +226,24 @@ export function extract_segments(line, before_end, after_start, after_len, stric
|
|
|
226
226
|
return takeObject(ret);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Get list of supported languages.
|
|
231
|
+
* @returns {string[]}
|
|
232
|
+
*/
|
|
233
|
+
export function get_supported_languages() {
|
|
234
|
+
try {
|
|
235
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
236
|
+
wasm.get_supported_languages(retptr);
|
|
237
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
238
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
239
|
+
var v1 = getArrayJsValueFromWasm0(r0, r1).slice();
|
|
240
|
+
wasm.__wbindgen_export3(r0, r1 * 4, 4);
|
|
241
|
+
return v1;
|
|
242
|
+
} finally {
|
|
243
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
229
247
|
/**
|
|
230
248
|
* Quick check if content matches a pattern.
|
|
231
249
|
* @param {string} content
|
|
@@ -254,6 +272,76 @@ export function has_match(content, pattern, ignore_case, multiline) {
|
|
|
254
272
|
}
|
|
255
273
|
}
|
|
256
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Highlight code and return ANSI-colored lines.
|
|
277
|
+
*
|
|
278
|
+
* # Arguments
|
|
279
|
+
* * `code` - The source code to highlight
|
|
280
|
+
* * `lang` - Language identifier (e.g., "rust", "typescript", "python")
|
|
281
|
+
* * `colors` - Theme colors as ANSI escape sequences
|
|
282
|
+
*
|
|
283
|
+
* # Returns
|
|
284
|
+
* Highlighted code with ANSI color codes, or the original code if highlighting
|
|
285
|
+
* fails.
|
|
286
|
+
* @param {string} code
|
|
287
|
+
* @param {string | null | undefined} lang
|
|
288
|
+
* @param {any} colors
|
|
289
|
+
* @returns {string}
|
|
290
|
+
*/
|
|
291
|
+
export function highlight_code(code, lang, colors) {
|
|
292
|
+
let deferred3_0;
|
|
293
|
+
let deferred3_1;
|
|
294
|
+
try {
|
|
295
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
296
|
+
const ptr0 = passStringToWasm0(code, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
297
|
+
const len0 = WASM_VECTOR_LEN;
|
|
298
|
+
var ptr1 = isLikeNone(lang) ? 0 : passStringToWasm0(lang, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
299
|
+
var len1 = WASM_VECTOR_LEN;
|
|
300
|
+
wasm.highlight_code(retptr, ptr0, len0, ptr1, len1, addHeapObject(colors));
|
|
301
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
302
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
303
|
+
deferred3_0 = r0;
|
|
304
|
+
deferred3_1 = r1;
|
|
305
|
+
return getStringFromWasm0(r0, r1);
|
|
306
|
+
} finally {
|
|
307
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
308
|
+
wasm.__wbindgen_export3(deferred3_0, deferred3_1, 1);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Convert HTML to Markdown.
|
|
314
|
+
* @param {string} html
|
|
315
|
+
* @param {any} options
|
|
316
|
+
* @returns {string}
|
|
317
|
+
*/
|
|
318
|
+
export function html_to_markdown(html, options) {
|
|
319
|
+
let deferred3_0;
|
|
320
|
+
let deferred3_1;
|
|
321
|
+
try {
|
|
322
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
323
|
+
const ptr0 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
324
|
+
const len0 = WASM_VECTOR_LEN;
|
|
325
|
+
wasm.html_to_markdown(retptr, ptr0, len0, addHeapObject(options));
|
|
326
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
327
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
328
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
329
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
330
|
+
var ptr2 = r0;
|
|
331
|
+
var len2 = r1;
|
|
332
|
+
if (r3) {
|
|
333
|
+
ptr2 = 0; len2 = 0;
|
|
334
|
+
throw takeObject(r2);
|
|
335
|
+
}
|
|
336
|
+
deferred3_0 = ptr2;
|
|
337
|
+
deferred3_1 = len2;
|
|
338
|
+
return getStringFromWasm0(ptr2, len2);
|
|
339
|
+
} finally {
|
|
340
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
341
|
+
wasm.__wbindgen_export3(deferred3_0, deferred3_1, 1);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
257
345
|
/**
|
|
258
346
|
* Resize an image to the specified dimensions.
|
|
259
347
|
* @param {PhotonImage} image
|
|
@@ -297,6 +385,20 @@ export function slice_with_width(line, start_col, length, strict) {
|
|
|
297
385
|
return takeObject(ret);
|
|
298
386
|
}
|
|
299
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Check if a language is supported for highlighting.
|
|
390
|
+
* Returns true if the language has either direct support or a fallback
|
|
391
|
+
* mapping.
|
|
392
|
+
* @param {string} lang
|
|
393
|
+
* @returns {boolean}
|
|
394
|
+
*/
|
|
395
|
+
export function supports_language(lang) {
|
|
396
|
+
const ptr0 = passStringToWasm0(lang, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
397
|
+
const len0 = WASM_VECTOR_LEN;
|
|
398
|
+
const ret = wasm.supports_language(ptr0, len0);
|
|
399
|
+
return ret !== 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
300
402
|
/**
|
|
301
403
|
* Truncate text to a visible width, preserving ANSI codes.
|
|
302
404
|
* @param {string} text
|
|
@@ -382,6 +484,10 @@ function __wbg_get_imports() {
|
|
|
382
484
|
const ret = typeof(getObject(arg0)) === 'bigint';
|
|
383
485
|
return ret;
|
|
384
486
|
},
|
|
487
|
+
__wbg___wbindgen_is_null_ac34f5003991759a: function(arg0) {
|
|
488
|
+
const ret = getObject(arg0) === null;
|
|
489
|
+
return ret;
|
|
490
|
+
},
|
|
385
491
|
__wbg___wbindgen_is_object_5ae8e5880f2c1fbd: function(arg0) {
|
|
386
492
|
const val = getObject(arg0);
|
|
387
493
|
const ret = typeof(val) === 'object' && val !== null;
|
|
@@ -629,6 +735,16 @@ function dropObject(idx) {
|
|
|
629
735
|
heap_next = idx;
|
|
630
736
|
}
|
|
631
737
|
|
|
738
|
+
function getArrayJsValueFromWasm0(ptr, len) {
|
|
739
|
+
ptr = ptr >>> 0;
|
|
740
|
+
const mem = getDataViewMemory0();
|
|
741
|
+
const result = [];
|
|
742
|
+
for (let i = ptr; i < ptr + 4 * len; i += 4) {
|
|
743
|
+
result.push(takeObject(mem.getUint32(i, true)));
|
|
744
|
+
}
|
|
745
|
+
return result;
|
|
746
|
+
}
|
|
747
|
+
|
|
632
748
|
function getArrayU8FromWasm0(ptr, len) {
|
|
633
749
|
ptr = ptr >>> 0;
|
|
634
750
|
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
package/wasm/pi_natives_bg.wasm
CHANGED
|
Binary file
|
|
@@ -7,7 +7,10 @@ export const compiledpattern_has_match: (a: number, b: number, c: number) => num
|
|
|
7
7
|
export const compiledpattern_new: (a: number, b: number) => void;
|
|
8
8
|
export const compiledpattern_search: (a: number, b: number, c: number, d: number, e: number) => number;
|
|
9
9
|
export const extract_segments: (a: number, b: number, c: number, d: number, e: number, f: number) => number;
|
|
10
|
+
export const get_supported_languages: (a: number) => void;
|
|
10
11
|
export const has_match: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
12
|
+
export const highlight_code: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
13
|
+
export const html_to_markdown: (a: number, b: number, c: number, d: number) => void;
|
|
11
14
|
export const photonimage_get_bytes: (a: number, b: number) => void;
|
|
12
15
|
export const photonimage_get_bytes_jpeg: (a: number, b: number, c: number) => void;
|
|
13
16
|
export const photonimage_get_height: (a: number) => number;
|
|
@@ -16,6 +19,7 @@ export const photonimage_new_from_byteslice: (a: number, b: number, c: number) =
|
|
|
16
19
|
export const resize: (a: number, b: number, c: number, d: number) => number;
|
|
17
20
|
export const search: (a: number, b: number, c: number) => number;
|
|
18
21
|
export const slice_with_width: (a: number, b: number, c: number, d: number, e: number) => number;
|
|
22
|
+
export const supports_language: (a: number, b: number) => number;
|
|
19
23
|
export const truncate_to_width: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
20
24
|
export const visible_width: (a: number, b: number) => number;
|
|
21
25
|
export const compiledpattern_has_match_bytes: (a: number, b: number, c: number) => number;
|