module-tsx 0.0.0 → 0.0.2

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/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # module-tsx
2
+
3
+ Run TypeScript (and React) modules directly in the browser, without a build step.
4
+
5
+ ## Usage
6
+
7
+ ```html
8
+ <!-- Load this library -->
9
+ <script type="module" src="https://esm.sh/module-tsx"></script>
10
+
11
+ <div id="root"></div>
12
+
13
+ <!-- Write your TypeScript/TSX inline -->
14
+ <script type="module-tsx">
15
+ import React from "react"; // bare specifier → https://esm.sh/react
16
+ import { createRoot } from "react-dom/client";
17
+ import App from "./src/App.tsx"; // relative imports are fetched and compiled on the fly
18
+
19
+ const root = document.getElementById("root") as HTMLDivElement;
20
+ createRoot(root).render(
21
+ <React.StrictMode>
22
+ <App />
23
+ </React.StrictMode>
24
+ );
25
+ </script>
26
+
27
+ <!-- OR load an external file -->
28
+ <script type="module-tsx" src="./main.tsx"></script>
29
+ ```
30
+
31
+ You publish the **source code**, and users can run it directly in the browser **without any build step**.
32
+
33
+ ```tsx
34
+ // src/App.tsx
35
+ export default function App() {
36
+ return <div>Hello, module-tsx!</div>;
37
+ }
38
+ ```
39
+
40
+ ## Features
41
+
42
+ - **TypeScript & JSX/TSX** — transpiled on the fly using the TypeScript compiler
43
+ - **Bare specifier resolution** — `import "react"` is automatically rewritten to a CDN URL (defaults to `https://esm.sh/`)
44
+ - **Relative imports** — `.ts`/`.tsx` files are fetched and compiled recursively
45
+ - **CSS imports** — `import "./style.css"` injects a `<style>` tag; `import "./style.module.css"` returns a CSS Modules object
46
+ - **Import map support** — respects `<script type="importmap">` on the page for specifier overrides
47
+ - **Auto React import** — JSX is detected and `import React from "react"` is injected automatically if missing
48
+
49
+ ## Programmatic API
50
+
51
+ ```ts
52
+ import { ModuleTSX } from "module-tsx";
53
+
54
+ const m = new ModuleTSX({
55
+ baseUrl: location.href, // base for resolving relative specifiers
56
+ importMap: { imports: { react: "https://esm.sh/react" } }, // merged with page importmaps
57
+ resolveBareSpecifier: "https://cdn.jsdelivr.net/npm/", // string prefix or function
58
+ });
59
+
60
+ // Import a module by specifier
61
+ const react = await m.import("react");
62
+ const app = await m.import("./app.tsx");
63
+
64
+ // Import from an in-memory string
65
+ const { x } = await m.importCode(document.location.href, `export const x: number = 1`);
66
+
67
+ // Events
68
+ m.addEventListener("import", (e) => console.log("loading", e.detail.id));
69
+ m.addEventListener("import:error", (e) => console.error("failed", e.detail.id, e.detail.error));
70
+ m.addEventListener("transform", (e) => console.log("compiling", e.detail.sourceUrl));
71
+ m.addEventListener("transform:error", (e) => console.error("compile error", e.detail.sourceUrl, e.detail.error));
72
+ ```
73
+
74
+ ## Use with AI
75
+
76
+ module-tsx is well-suited for AI-generated pages — an AI can produce a single, self-contained HTML file that runs TypeScript and React directly in the browser with no build step or configuration.
77
+
78
+ To use the skill, run
79
+
80
+ ```sh
81
+ npx skills add yieldray/module-tsx
82
+ ```
83
+
84
+ ## CDN
85
+
86
+ ```html
87
+ <!-- ESM -->
88
+ <script type="module" src="https://esm.sh/module-tsx"></script>
89
+
90
+ <!-- ESM (self-contained, no external dependencies) -->
91
+ <script type="module" src="https://raw.esm.sh/module-tsx/dist/index.mjs"></script>
92
+
93
+ <!-- UMD (exposes window.ModuleTSX) -->
94
+ <script src="https://raw.esm.sh/module-tsx/dist/index.umd.js"></script>
95
+ ```
@@ -0,0 +1,105 @@
1
+ //#region src/importmap.d.ts
2
+ type ModuleSpecifierMap = Map<string, URL | null>;
3
+ interface SpecifierResolutionRecord {
4
+ serializedBaseURL: string;
5
+ specifier: string;
6
+ specifierAsURL: URL | null;
7
+ }
8
+ declare class ImportMap {
9
+ imports: ModuleSpecifierMap;
10
+ scopes: Map<string, ModuleSpecifierMap>;
11
+ integrity: Map<string, string>;
12
+ constructor(imports?: ModuleSpecifierMap, scopes?: Map<string, ModuleSpecifierMap>, integrity?: Map<string, string>);
13
+ /** Parse a JSON import map string against a base URL. */
14
+ static parse(input: string, baseURL: URL | string): ImportMap;
15
+ /** Build an ImportMap from a plain object (same shape as the JSON format). */
16
+ static of(json: object, baseURL: URL | string): ImportMap;
17
+ /** Merge newImportMap into oldImportMap in place (spec § "merge existing and new import maps"). */
18
+ static merge(oldImportMap: ImportMap, newImportMap: ImportMap, resolvedModuleSet?: ReadonlyArray<SpecifierResolutionRecord>): void;
19
+ /** Resolve a specifier against an import map (spec § "resolve a module specifier"). */
20
+ static resolve(specifier: string, importMap: ImportMap, baseURL: string | URL): {
21
+ url: string;
22
+ record: SpecifierResolutionRecord;
23
+ } | undefined;
24
+ /** Parse all <script type="importmap"> elements from the DOM. */
25
+ static fromDOM(): ImportMap;
26
+ }
27
+ //#endregion
28
+ //#region src/module-tsx.d.ts
29
+ interface ModuleTSXConfig {
30
+ /**
31
+ * The base URL to resolve relative module specifiers.
32
+ * This is typically the URL of the main script or the HTML page.
33
+ */
34
+ baseUrl?: string;
35
+ fetch?: (fullURL: string) => Promise<Response>;
36
+ importMap?: ImportMap;
37
+ /**
38
+ * Given a bare specifier, return a full URL to load the module.
39
+ * This can be used to convert for example import "react" to import "https://esm.sh/react".
40
+ * If not provided, it will default to using "https://esm.sh/" as the base URL for bare specifiers.
41
+ * @default "https://esm.sh/"
42
+ */
43
+ resolveBareSpecifier?: string | ((specifier: string) => string);
44
+ }
45
+ interface ModuleTSXEventMap {
46
+ /** Fired when an import starts. `id` is the original specifier as passed by the caller. */
47
+ import: CustomEvent<{
48
+ id: string;
49
+ }>;
50
+ /** Fired when an import fails. `id` is the specifier at the point of failure. */
51
+ "import:error": CustomEvent<{
52
+ id: string;
53
+ error: any;
54
+ }>;
55
+ /** Fired when a source file starts being transpiled. */
56
+ transform: CustomEvent<{
57
+ sourceUrl: string;
58
+ }>;
59
+ /** Fired when transpilation fails. */
60
+ "transform:error": CustomEvent<{
61
+ sourceUrl: string;
62
+ error: any;
63
+ }>;
64
+ }
65
+ interface IModuleTSX extends EventTarget {
66
+ addEventListener<T extends keyof ModuleTSXEventMap>(type: T, listener: (this: ModuleTSX, ev: ModuleTSXEventMap[T]) => any, options?: boolean | AddEventListenerOptions): void;
67
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
68
+ }
69
+ declare class ModuleTSX extends EventTarget implements IModuleTSX {
70
+ readonly baseUrl: string;
71
+ readonly importMap: ImportMap;
72
+ readonly fetch: (url: string) => Promise<Response>;
73
+ readonly resolveBareSpecifier: (specifier: string) => string;
74
+ private readonly resolvedModuleSet;
75
+ private readonly sourceTracker;
76
+ private readonly fetchText;
77
+ constructor(config?: ModuleTSXConfig);
78
+ /** Add a new import map, merging it into the existing one per the spec.
79
+ * Rules that conflict with already-resolved modules are silently dropped. */
80
+ addImportMap(newImportMap: ImportMap): void;
81
+ private emit;
82
+ import(id: string, options?: any): Promise<any>;
83
+ importCode(sourceUrl: string, code: string, options?: any): Promise<any>;
84
+ /** Transform module source code and return a blob URL with the transformed content */
85
+ private transformSourceModule;
86
+ private getLoaderByResourceType;
87
+ private tsxLoader;
88
+ private resolveLocalUrl;
89
+ private resolveSpecifier;
90
+ private resolveSpecifiers;
91
+ }
92
+ //#endregion
93
+ //#region src/error.d.ts
94
+ /** Custom error class for module-tsx */
95
+ declare class ModuleTSXError extends Error {
96
+ constructor(message?: string, options?: ErrorOptions);
97
+ }
98
+ //#endregion
99
+ //#region src/index.d.ts
100
+ /**
101
+ * The singleton global instance of ModuleTSX.
102
+ */
103
+ declare const instance: ModuleTSX;
104
+ //#endregion
105
+ export { ImportMap, ModuleTSX, ModuleTSXError, instance };