application-typescript 1.0.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/README.md +213 -0
- package/application-typescript.js +259 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# `application-typescript`
|
|
2
|
+
|
|
3
|
+
Run TypeScript in the browser without a bundler — add one `<script>` tag and serve static files.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
**`index.html`**
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<!DOCTYPE html>
|
|
13
|
+
<html lang="en">
|
|
14
|
+
<head>
|
|
15
|
+
<meta charset="utf-8" />
|
|
16
|
+
<title>Hello</title>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
|
|
20
|
+
<!-- app container -->
|
|
21
|
+
<div id="app"></div>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<!-- preact + htm application -->
|
|
25
|
+
<script type="application/typescript" src="./hello.ts"></script>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
<!-- esm.sh application-typescript runner -->
|
|
29
|
+
<script type="module" src="https://esm.sh/application-typescript"></script>
|
|
30
|
+
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**`hello.ts`**
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { html, render } from "htm/preact/standalone";
|
|
39
|
+
import { HelloApp } from "./hello.app";
|
|
40
|
+
|
|
41
|
+
const root = document.getElementById("app");
|
|
42
|
+
if (root) render(html`<${HelloApp} />`, root);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**`hello.app.ts`**
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { html } from "htm/preact/standalone";
|
|
49
|
+
|
|
50
|
+
export function HelloApp() {
|
|
51
|
+
return html`<h1>Hello World</h1>`;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Serve over HTTP (not `file://`), then open the page:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx -y serve . -l 5123 --no-port-switching # → http://localhost:5123/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
That's it. No build step, no config file.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## When to use
|
|
66
|
+
|
|
67
|
+
Good fit:
|
|
68
|
+
- Small UI prototypes with 10–15 components
|
|
69
|
+
- Static pages where you want real TypeScript without wiring a bundler
|
|
70
|
+
- Exploring an idea quickly before committing to Vite / esbuild
|
|
71
|
+
|
|
72
|
+
Not a good fit:
|
|
73
|
+
- Production apps (CDN dependency, no tree-shaking, no SSR)
|
|
74
|
+
- Large codebases (compile-on-demand cost adds up)
|
|
75
|
+
- Environments that block CDN traffic (esm.sh required for the compiler)
|
|
76
|
+
|
|
77
|
+
When you outgrow this, move the same `.ts` sources into Vite or esbuild — the module structure carries over.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Multi-file projects
|
|
82
|
+
|
|
83
|
+
Use relative imports between `.ts` files. The runner transpiles each file and rewrites `./` / `../` specifiers to blob URLs, so the full module graph loads correctly.
|
|
84
|
+
|
|
85
|
+
**`hello.ts`** (entry)
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { html, render } from "htm/preact/standalone";
|
|
89
|
+
import { HelloApp } from "./hello.app";
|
|
90
|
+
|
|
91
|
+
const root = document.getElementById("app");
|
|
92
|
+
if (root) render(html`<${HelloApp} />`, root);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**`hello.app.ts`** (component)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { html } from "htm/preact/standalone";
|
|
99
|
+
|
|
100
|
+
export function HelloApp() {
|
|
101
|
+
return html`<h1>Hello World</h1>`;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Keep imports acyclic.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Setup reference
|
|
110
|
+
|
|
111
|
+
### Entry marker
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<script type="application/typescript" src="./src/app.ts"></script>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- `src` is required. Scripts without `src` are ignored.
|
|
118
|
+
- `src` is resolved with `new URL(src, location.href)`. Use `./src/app.ts` under a subpath, `/src/app.ts` at the origin root.
|
|
119
|
+
- Multiple markers are processed in document order, one after another.
|
|
120
|
+
|
|
121
|
+
### Runner
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<script type="module" src="https://esm.sh/application-typescript"></script>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Must come **after** all `application/typescript` markers so the DOM query sees them.
|
|
128
|
+
|
|
129
|
+
### Import map (optional)
|
|
130
|
+
|
|
131
|
+
You can skip the import map entirely — bare specifiers like `"htm/preact/standalone"` fall back to `https://esm.sh/<specifier>` automatically.
|
|
132
|
+
|
|
133
|
+
Add an import map when you need to pin versions or use non-esm.sh URLs:
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<script type="importmap">
|
|
137
|
+
{
|
|
138
|
+
"imports": {
|
|
139
|
+
"preact": "https://esm.sh/preact@10.24.3",
|
|
140
|
+
"htm/preact/standalone": "https://esm.sh/htm@3.1.1/preact/standalone"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The runner merges all import maps on the page (later maps override keys). `scopes` are ignored.
|
|
147
|
+
|
|
148
|
+
### Serving
|
|
149
|
+
|
|
150
|
+
Use a static HTTP server. `file://` breaks `import`, `fetch`, and CORS.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npx -y serve . -l 5123 --no-port-switching
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Smoke test (bare imports)
|
|
157
|
+
|
|
158
|
+
This repo includes `test.html`, `test.ts`, and `test.app.ts`. `test.app.ts` imports `lodash/shuffle` so you can confirm bare specifiers resolve through esm.sh in the browser.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm test
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
That runs `npx -y serve .` (default port, usually 3000, with automatic fallback). Open `/test.html` and check the page text and console.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## How it works
|
|
169
|
+
|
|
170
|
+
For each `<script type="application/typescript" src="…">`, the runner:
|
|
171
|
+
|
|
172
|
+
1. Resolves `src` against `location.href`
|
|
173
|
+
2. Fetches the source (`cache: "no-cache"`)
|
|
174
|
+
3. Transpiles with `typescript.transpileModule` (target ES2022, module ESNext, no type-checking)
|
|
175
|
+
4. Rewrites relative imports (`./`, `../`) to blob URLs of the transpiled dependency files (recursive, cached)
|
|
176
|
+
5. Rewrites bare imports to absolute URLs: import map match first, otherwise `https://esm.sh/<specifier>`
|
|
177
|
+
6. Creates a `Blob`, calls `URL.createObjectURL`, and `import()`s the result as a real ES module
|
|
178
|
+
|
|
179
|
+
Each source URL is cached to one blob URL. Parallel loads of the same module share one in-flight promise.
|
|
180
|
+
|
|
181
|
+
The TypeScript compiler itself is loaded from `https://esm.sh/typescript@6.0.3` on first run.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Limitations
|
|
186
|
+
|
|
187
|
+
- **Type-checking** — none at runtime; use `tsc --noEmit` / your IDE
|
|
188
|
+
- **Inline `<script>` bodies** — not supported; `src` attribute is required
|
|
189
|
+
- **Dynamic `import()` with non-literal specifier** — not rewritten
|
|
190
|
+
- **Import map `scopes`** — ignored
|
|
191
|
+
- **Compiler version** — pinned to `typescript@6.0.3` in the runner source
|
|
192
|
+
- **CDN dependency** — requires network access to esm.sh on first load
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Security
|
|
197
|
+
|
|
198
|
+
Treat every fetched `.ts` URL as executable code. Only point `src` at same-origin files or hosts you fully trust. The runner does not sandbox transpiled output.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Contributing
|
|
203
|
+
|
|
204
|
+
When changing the runner (selectors, transpiler options, CDN URLs, logging), update this README in the same commit.
|
|
205
|
+
|
|
206
|
+
### Release
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npm version patch # or minor / major
|
|
210
|
+
npm publish --access public
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The unversioned `https://esm.sh/application-typescript` URL always resolves to the latest published release.
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-browser TypeScript runner: finds every
|
|
3
|
+
* <script type="application/typescript" src="./path.ts"></script>
|
|
4
|
+
* (`src` is required — inline body without `src` is ignored). Fetches each URL,
|
|
5
|
+
* transpiles with the `typescript` package from esm.sh, then `import()` a blob URL
|
|
6
|
+
* so the result is a real ES module (top-level `import` works; no eval).
|
|
7
|
+
*
|
|
8
|
+
* Relative imports like `import { x } from "./foo"` work: each file is transpiled
|
|
9
|
+
* separately and specifiers are rewritten to blob URLs (import base is otherwise
|
|
10
|
+
* the blob, so `./foo` would not resolve). Circular relative imports can deadlock.
|
|
11
|
+
*
|
|
12
|
+
* Bare specifiers (`import from "lodash"`) are rewritten to absolute URLs: first
|
|
13
|
+
* match against merged top-level `imports` from every `<script type="importmap">`,
|
|
14
|
+
* otherwise `https://esm.sh/<specifier>`. (Blob modules often ignore import maps;
|
|
15
|
+
* rewriting makes bare imports reliable.) Scoped packages and subpaths work on
|
|
16
|
+
* esm.sh, e.g. `lodash/debounce`.
|
|
17
|
+
*/
|
|
18
|
+
import ts from "https://esm.sh/typescript@6.0.3";
|
|
19
|
+
|
|
20
|
+
(async function () {
|
|
21
|
+
const SELECTOR = 'script[type="application/typescript"][src]';
|
|
22
|
+
|
|
23
|
+
/** @type {Record<string, string> | null} */
|
|
24
|
+
let cachedImportsMap = null;
|
|
25
|
+
|
|
26
|
+
/** @type {Map<string, string>} */
|
|
27
|
+
const blobUrlByTsUrl = new Map();
|
|
28
|
+
/** @type {Map<string, Promise<string>>} */
|
|
29
|
+
const inflightBlobUrl = new Map();
|
|
30
|
+
|
|
31
|
+
function showError(msg, cause) {
|
|
32
|
+
if (cause !== undefined) {
|
|
33
|
+
console.error("[application-typescript]", msg, cause);
|
|
34
|
+
} else {
|
|
35
|
+
console.error("[application-typescript]", msg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getTs() {
|
|
40
|
+
return ts?.default ?? ts;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function transpileModuleSource(fileName, sourceText) {
|
|
44
|
+
const t = getTs();
|
|
45
|
+
const { outputText } = t.transpileModule(sourceText, {
|
|
46
|
+
compilerOptions: {
|
|
47
|
+
target: t.ScriptTarget.ES2022,
|
|
48
|
+
module: t.ModuleKind.ESNext,
|
|
49
|
+
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
50
|
+
skipLibCheck: true,
|
|
51
|
+
isolatedModules: true,
|
|
52
|
+
},
|
|
53
|
+
fileName,
|
|
54
|
+
});
|
|
55
|
+
return outputText;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a relative module specifier to an absolute .ts URL (same-origin fetch).
|
|
60
|
+
* @param {string} containingTsUrl absolute URL of the current module
|
|
61
|
+
* @param {string} specifier e.g. ./ok ./ok.js ../lib/x
|
|
62
|
+
*/
|
|
63
|
+
function resolveTsDependencyUrl(containingTsUrl, specifier) {
|
|
64
|
+
const baseDir = new URL(".", containingTsUrl);
|
|
65
|
+
let spec = specifier;
|
|
66
|
+
if (spec.endsWith(".js")) spec = spec.slice(0, -3);
|
|
67
|
+
if (spec.endsWith(".jsx")) spec = spec.slice(0, -4);
|
|
68
|
+
const u = new URL(spec, baseDir);
|
|
69
|
+
if (!/(?:\.[cm]?ts|\.tsx)$/.test(u.pathname)) {
|
|
70
|
+
u.pathname = u.pathname.endsWith("/") ? `${u.pathname}index.ts` : `${u.pathname}.ts`;
|
|
71
|
+
}
|
|
72
|
+
return u.href;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Collect relative specifiers as they appear in emitted JS (./ ../ only).
|
|
77
|
+
* @param {string} js
|
|
78
|
+
*/
|
|
79
|
+
function collectRelativeSpecifiersInJs(js) {
|
|
80
|
+
const specs = new Set();
|
|
81
|
+
const fromRe = /\bfrom\s*["'](\.\.?\/[^"']+)["']/g;
|
|
82
|
+
const dynRe = /\bimport\s*\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g;
|
|
83
|
+
for (const re of [fromRe, dynRe]) {
|
|
84
|
+
for (const m of js.matchAll(re)) {
|
|
85
|
+
specs.add(m[1]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return [...specs];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Merge `imports` from all import map scripts (later maps override keys).
|
|
93
|
+
* Only top-level `imports` is used (not `scopes`).
|
|
94
|
+
*/
|
|
95
|
+
function mergeDocumentImportMaps() {
|
|
96
|
+
/** @type {Record<string, string>} */
|
|
97
|
+
const out = {};
|
|
98
|
+
for (const el of document.querySelectorAll('script[type="importmap"]')) {
|
|
99
|
+
try {
|
|
100
|
+
const j = JSON.parse(el.textContent || "{}");
|
|
101
|
+
if (j.imports && typeof j.imports === "object") {
|
|
102
|
+
Object.assign(out, j.imports);
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.warn("[application-typescript] skipped invalid importmap", e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getImportsMap() {
|
|
112
|
+
if (!cachedImportsMap) cachedImportsMap = mergeDocumentImportMaps();
|
|
113
|
+
return cachedImportsMap;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {string} spec
|
|
118
|
+
*/
|
|
119
|
+
function isBareModuleSpecifier(spec) {
|
|
120
|
+
if (!spec || typeof spec !== "string") return false;
|
|
121
|
+
if (spec.startsWith(".") || spec.startsWith("/")) return false;
|
|
122
|
+
if (/^(https?:|data:|blob:)/i.test(spec)) return false;
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Collect bare specifiers in emitted JS (not ./ ../ not URLs).
|
|
128
|
+
* @param {string} js
|
|
129
|
+
*/
|
|
130
|
+
function collectBareSpecifiersInJs(js) {
|
|
131
|
+
const specs = new Set();
|
|
132
|
+
const fromRe = /\bfrom\s*["']([^"']+)["']/g;
|
|
133
|
+
const dynRe = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
|
|
134
|
+
for (const m of js.matchAll(fromRe)) {
|
|
135
|
+
if (isBareModuleSpecifier(m[1])) specs.add(m[1]);
|
|
136
|
+
}
|
|
137
|
+
for (const m of js.matchAll(dynRe)) {
|
|
138
|
+
if (isBareModuleSpecifier(m[1])) specs.add(m[1]);
|
|
139
|
+
}
|
|
140
|
+
return [...specs];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {string} spec bare specifier, e.g. lodash or @scope/pkg
|
|
145
|
+
* @param {Record<string, string>} importsMap
|
|
146
|
+
*/
|
|
147
|
+
function resolveBareModuleSpecifier(spec, importsMap) {
|
|
148
|
+
const mapped = importsMap[spec];
|
|
149
|
+
if (mapped) {
|
|
150
|
+
try {
|
|
151
|
+
return new URL(mapped, location.href).href;
|
|
152
|
+
} catch {
|
|
153
|
+
return mapped;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return `https://esm.sh/${spec}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {string} js
|
|
161
|
+
* @param {string} fromSpec specifier as in source/emitted string
|
|
162
|
+
* @param {string} toBlobUrl
|
|
163
|
+
*/
|
|
164
|
+
function rewriteSpecifier(js, fromSpec, toBlobUrl) {
|
|
165
|
+
const esc = fromSpec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
166
|
+
const to = JSON.stringify(toBlobUrl);
|
|
167
|
+
let out = js.replace(
|
|
168
|
+
new RegExp(`(\\bfrom\\s*)["']${esc}["']`, "g"),
|
|
169
|
+
`$1${to}`,
|
|
170
|
+
);
|
|
171
|
+
out = out.replace(
|
|
172
|
+
new RegExp(`(\\bimport\\s*\\(\\s*)["']${esc}["']`, "g"),
|
|
173
|
+
`$1${to}`,
|
|
174
|
+
);
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Transpile a TypeScript module and its relative dependency tree; return a blob URL.
|
|
180
|
+
* @param {string} resolvedTsUrl
|
|
181
|
+
*/
|
|
182
|
+
async function getBlobUrlForTsModule(resolvedTsUrl) {
|
|
183
|
+
const cached = blobUrlByTsUrl.get(resolvedTsUrl);
|
|
184
|
+
if (cached) return cached;
|
|
185
|
+
|
|
186
|
+
const pending = inflightBlobUrl.get(resolvedTsUrl);
|
|
187
|
+
if (pending) return pending;
|
|
188
|
+
|
|
189
|
+
const p = (async () => {
|
|
190
|
+
const res = await fetch(resolvedTsUrl, { cache: "no-cache" });
|
|
191
|
+
if (!res.ok) {
|
|
192
|
+
throw new Error(`${resolvedTsUrl}: HTTP ${res.status}`);
|
|
193
|
+
}
|
|
194
|
+
const source = await res.text();
|
|
195
|
+
let js = await transpileModuleSource(resolvedTsUrl, source);
|
|
196
|
+
|
|
197
|
+
const relSpecs = collectRelativeSpecifiersInJs(js).sort(
|
|
198
|
+
(a, b) => b.length - a.length,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
for (const spec of relSpecs) {
|
|
202
|
+
const depTsUrl = resolveTsDependencyUrl(resolvedTsUrl, spec);
|
|
203
|
+
const depBlob = await getBlobUrlForTsModule(depTsUrl);
|
|
204
|
+
js = rewriteSpecifier(js, spec, depBlob);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const importsMap = getImportsMap();
|
|
208
|
+
const bareSpecs = collectBareSpecifiersInJs(js).sort(
|
|
209
|
+
(a, b) => b.length - a.length,
|
|
210
|
+
);
|
|
211
|
+
for (const spec of bareSpecs) {
|
|
212
|
+
const url = resolveBareModuleSpecifier(spec, importsMap);
|
|
213
|
+
js = rewriteSpecifier(js, spec, url);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const label = resolvedTsUrl.replace(/\n/g, " ");
|
|
217
|
+
const blob = new Blob([`${js}\n//# sourceURL=${label}\n`], {
|
|
218
|
+
type: "text/javascript",
|
|
219
|
+
});
|
|
220
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
221
|
+
blobUrlByTsUrl.set(resolvedTsUrl, blobUrl);
|
|
222
|
+
return blobUrl;
|
|
223
|
+
})();
|
|
224
|
+
|
|
225
|
+
inflightBlobUrl.set(resolvedTsUrl, p);
|
|
226
|
+
try {
|
|
227
|
+
return await p;
|
|
228
|
+
} finally {
|
|
229
|
+
inflightBlobUrl.delete(resolvedTsUrl);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function runOneScript(el) {
|
|
234
|
+
const src = el.getAttribute("src");
|
|
235
|
+
if (!src) return;
|
|
236
|
+
const resolved = new URL(src, location.href).href;
|
|
237
|
+
const entryBlobUrl = await getBlobUrlForTsModule(resolved);
|
|
238
|
+
await import(entryBlobUrl);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const scripts = [...document.querySelectorAll(SELECTOR)];
|
|
242
|
+
if (scripts.length === 0) {
|
|
243
|
+
showError(
|
|
244
|
+
`No matching scripts. Add e.g. <script type="application/typescript" src="/src/app.ts"></script> before the <script type="module"> that loads this runner (from esm.sh or your host).`,
|
|
245
|
+
);
|
|
246
|
+
} else {
|
|
247
|
+
for (const el of scripts) {
|
|
248
|
+
try {
|
|
249
|
+
await runOneScript(el);
|
|
250
|
+
} catch (e) {
|
|
251
|
+
showError(
|
|
252
|
+
`TypeScript runner: ${e instanceof Error ? e.message : String(e)}`,
|
|
253
|
+
e,
|
|
254
|
+
);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
})().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "application-typescript",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Browser loader: run TypeScript from script[type=application/typescript][src] without a bundler",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./application-typescript.js",
|
|
7
|
+
"module": "./application-typescript.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"browser": "./application-typescript.js",
|
|
11
|
+
"default": "./application-typescript.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"sideEffects": true,
|
|
15
|
+
"engines": {
|
|
16
|
+
"browser": "*"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"application-typescript.js",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"typescript",
|
|
24
|
+
"browser",
|
|
25
|
+
"esm",
|
|
26
|
+
"loader",
|
|
27
|
+
"transpile",
|
|
28
|
+
"no-bundler",
|
|
29
|
+
"prototype",
|
|
30
|
+
"cdn",
|
|
31
|
+
"esm.sh",
|
|
32
|
+
"runtime",
|
|
33
|
+
"browser-only",
|
|
34
|
+
"transpiler",
|
|
35
|
+
"blob-url",
|
|
36
|
+
"import-map"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/slavahatnuke/application-typescript.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/slavahatnuke/application-typescript/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/slavahatnuke/application-typescript#readme",
|
|
47
|
+
"scripts": {
|
|
48
|
+
"serve": "npx -y serve . -l 5123 --no-port-switching",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"test": "npx -y serve ."
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/lodash": "^4.17.16",
|
|
54
|
+
"htm": "3.1.1",
|
|
55
|
+
"preact": "10.24.3",
|
|
56
|
+
"typescript": "5.7"
|
|
57
|
+
}
|
|
58
|
+
}
|