tjs-lang 0.2.8 → 0.3.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/demo/docs.json +20 -14
- package/demo/src/examples.ts +23 -83
- package/demo/src/playground-shared.ts +666 -0
- package/demo/src/tjs-playground.ts +52 -528
- package/demo/src/ts-examples.ts +5 -4
- package/demo/src/ts-playground.ts +50 -414
- package/dist/index.js +58 -23
- package/dist/index.js.map +9 -9
- package/dist/src/lang/types.d.ts +1 -1
- package/dist/src/types/Type.d.ts +3 -1
- package/dist/tjs-full.js +58 -23
- package/dist/tjs-full.js.map +9 -9
- package/dist/tjs-transpiler.js +55 -20
- package/dist/tjs-transpiler.js.map +7 -7
- package/dist/tjs-vm.js +14 -14
- package/dist/tjs-vm.js.map +5 -5
- package/docs/index.js +740 -1010
- package/docs/index.js.map +9 -8
- package/editors/codemirror/ajs-language.ts +27 -1
- package/editors/codemirror/autocomplete.test.ts +3 -3
- package/package.json +1 -1
- package/src/lang/codegen.test.ts +11 -11
- package/src/lang/emitters/from-ts.ts +1 -1
- package/src/lang/emitters/js.ts +74 -0
- package/src/lang/inference.ts +40 -8
- package/src/lang/lang.test.ts +154 -16
- package/src/lang/runtime.ts +7 -0
- package/src/lang/types.ts +2 -0
- package/src/lang/typescript-syntax.test.ts +6 -4
- package/src/types/Type.test.ts +64 -0
- package/src/types/Type.ts +22 -1
- package/src/use-cases/transpiler-integration.test.ts +10 -10
- package/src/vm/atoms/batteries.ts +2 -0
package/docs/index.js
CHANGED
|
@@ -18702,6 +18702,41 @@ function runAllTests(tests, mocks, sigTestInfos, transpiledCode, resolvedImports
|
|
|
18702
18702
|
if (!__deepEqual(actual, expected)) {
|
|
18703
18703
|
throw new Error('Expected ' + __format(expected) + ' but got ' + __format(actual))
|
|
18704
18704
|
}
|
|
18705
|
+
},
|
|
18706
|
+
toContain(item) {
|
|
18707
|
+
if (!Array.isArray(actual) || !actual.some(function(v) { return __deepEqual(v, item) })) {
|
|
18708
|
+
throw new Error('Expected ' + __format(actual) + ' to contain ' + __format(item))
|
|
18709
|
+
}
|
|
18710
|
+
},
|
|
18711
|
+
toBeTruthy() {
|
|
18712
|
+
if (!actual) {
|
|
18713
|
+
throw new Error('Expected ' + __format(actual) + ' to be truthy')
|
|
18714
|
+
}
|
|
18715
|
+
},
|
|
18716
|
+
toBeFalsy() {
|
|
18717
|
+
if (actual) {
|
|
18718
|
+
throw new Error('Expected ' + __format(actual) + ' to be falsy')
|
|
18719
|
+
}
|
|
18720
|
+
},
|
|
18721
|
+
toBeNull() {
|
|
18722
|
+
if (actual !== null) {
|
|
18723
|
+
throw new Error('Expected null but got ' + __format(actual))
|
|
18724
|
+
}
|
|
18725
|
+
},
|
|
18726
|
+
toBeUndefined() {
|
|
18727
|
+
if (actual !== undefined) {
|
|
18728
|
+
throw new Error('Expected undefined but got ' + __format(actual))
|
|
18729
|
+
}
|
|
18730
|
+
},
|
|
18731
|
+
toBeGreaterThan(n) {
|
|
18732
|
+
if (!(actual > n)) {
|
|
18733
|
+
throw new Error('Expected ' + __format(actual) + ' to be greater than ' + n)
|
|
18734
|
+
}
|
|
18735
|
+
},
|
|
18736
|
+
toBeLessThan(n) {
|
|
18737
|
+
if (!(actual < n)) {
|
|
18738
|
+
throw new Error('Expected ' + __format(actual) + ' to be less than ' + n)
|
|
18739
|
+
}
|
|
18705
18740
|
}
|
|
18706
18741
|
}
|
|
18707
18742
|
}
|
|
@@ -236035,7 +236070,7 @@ var examples = [
|
|
|
236035
236070
|
description: "Fetch weather data (no API key needed)",
|
|
236036
236071
|
group: "api",
|
|
236037
236072
|
code: `function getWeather({ lat = 37.7749, lon = -122.4194 }) {
|
|
236038
|
-
let url =
|
|
236073
|
+
let url = 'https://api.open-meteo.com/v1/forecast?latitude=' + lat + '&longitude=' + lon + '¤t_weather=true'
|
|
236039
236074
|
let response = httpFetch({ url, cache: 1800 })
|
|
236040
236075
|
let weather = response.current_weather
|
|
236041
236076
|
return { weather }
|
|
@@ -236046,7 +236081,7 @@ var examples = [
|
|
|
236046
236081
|
description: "Search Apple iTunes catalog",
|
|
236047
236082
|
group: "api",
|
|
236048
236083
|
code: `function searchMusic({ query = 'Beatles', limit = 5 }) {
|
|
236049
|
-
let url =
|
|
236084
|
+
let url = 'https://itunes.apple.com/search?term=' + query + '&limit=' + limit + '&media=music'
|
|
236050
236085
|
let response = httpFetch({ url, cache: 3600 })
|
|
236051
236086
|
let tracks = response.results.map(x => ({
|
|
236052
236087
|
artist: x.artistName,
|
|
@@ -236061,7 +236096,7 @@ var examples = [
|
|
|
236061
236096
|
description: "Search GitHub repositories",
|
|
236062
236097
|
group: "api",
|
|
236063
236098
|
code: `function searchRepos({ query = 'tosijs', perPage = 5 }) {
|
|
236064
|
-
let url =
|
|
236099
|
+
let url = 'https://api.github.com/search/repositories?q=' + query + '&per_page=' + perPage + '&sort=stars'
|
|
236065
236100
|
let response = httpFetch({ url, cache: 300 })
|
|
236066
236101
|
let repos = response.items.map(x => ({
|
|
236067
236102
|
name: x.full_name,
|
|
@@ -236090,12 +236125,10 @@ var examples = [
|
|
|
236090
236125
|
code: `function summarize({ source = 'coffee-origins' }) {
|
|
236091
236126
|
// Fetch text from our sample documents
|
|
236092
236127
|
// Options: 'coffee-origins', 'ai-history', 'renewable-energy'
|
|
236093
|
-
let url =
|
|
236128
|
+
let url = '/texts/' + source + '.txt'
|
|
236094
236129
|
let text = httpFetch({ url })
|
|
236095
236130
|
|
|
236096
|
-
let prompt =
|
|
236097
|
-
|
|
236098
|
-
\${text}\`
|
|
236131
|
+
let prompt = 'Summarize the following text in 2-3 sentences:\\n\\n' + text
|
|
236099
236132
|
let summary = llmPredict({ prompt })
|
|
236100
236133
|
return { source, summary }
|
|
236101
236134
|
}`
|
|
@@ -236115,7 +236148,7 @@ var examples = [
|
|
|
236115
236148
|
hobbies: ['']
|
|
236116
236149
|
})
|
|
236117
236150
|
|
|
236118
|
-
let prompt =
|
|
236151
|
+
let prompt = 'Extract person info from this text: ' + text
|
|
236119
236152
|
let response = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
236120
236153
|
let person = JSON.parse(response)
|
|
236121
236154
|
return { person }
|
|
@@ -236129,12 +236162,12 @@ var examples = [
|
|
|
236129
236162
|
code: `function findCovers({ song = 'Yesterday', artist = 'Beatles' }) {
|
|
236130
236163
|
// Search iTunes for the song
|
|
236131
236164
|
let query = song + ' ' + artist
|
|
236132
|
-
let url =
|
|
236165
|
+
let url = 'https://itunes.apple.com/search?term=' + query + '&limit=25&media=music'
|
|
236133
236166
|
let response = httpFetch({ url, cache: 3600 })
|
|
236134
236167
|
|
|
236135
236168
|
// Format results for LLM analysis
|
|
236136
236169
|
let results = response.results || []
|
|
236137
|
-
let tracks = results.map(x =>
|
|
236170
|
+
let tracks = results.map(x => '"' + x.trackName + '" by ' + x.artistName + ' (' + x.collectionName + ')')
|
|
236138
236171
|
let trackList = tracks.join('\\n')
|
|
236139
236172
|
|
|
236140
236173
|
// Schema.response from example - much cleaner!
|
|
@@ -236142,11 +236175,7 @@ var examples = [
|
|
|
236142
236175
|
covers: [{ track: '', artist: '', album: '' }]
|
|
236143
236176
|
})
|
|
236144
236177
|
|
|
236145
|
-
let prompt =
|
|
236146
|
-
|
|
236147
|
-
\${trackList}
|
|
236148
|
-
|
|
236149
|
-
List cover versions (tracks NOT by \${artist}).\`
|
|
236178
|
+
let prompt = 'Search results for "' + song + '" by ' + artist + ':\\n\\n' + trackList + '\\n\\nList cover versions (tracks NOT by ' + artist + ').'
|
|
236150
236179
|
|
|
236151
236180
|
let llmResponse = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
236152
236181
|
let parsed = JSON.parse(llmResponse)
|
|
@@ -236160,19 +236189,15 @@ List cover versions (tracks NOT by \${artist}).\`
|
|
|
236160
236189
|
requiresApi: true,
|
|
236161
236190
|
code: `function mathAssistant({ question = 'What is 23 * 47 + 156?' }) {
|
|
236162
236191
|
// First, ask LLM to extract the calculation
|
|
236163
|
-
let extractPrompt =
|
|
236164
|
-
Question: \${question}\`
|
|
236192
|
+
let extractPrompt = 'Extract the math expression from this question. Return ONLY the expression, nothing else.\\nQuestion: ' + question
|
|
236165
236193
|
let expression = llmPredict({ prompt: extractPrompt })
|
|
236166
236194
|
|
|
236167
236195
|
// Evaluate the expression (simple eval simulation)
|
|
236168
|
-
let calcPrompt =
|
|
236169
|
-
Return ONLY the numeric result.\`
|
|
236196
|
+
let calcPrompt = 'Calculate: ' + expression + '\\nReturn ONLY the numeric result.'
|
|
236170
236197
|
let calcResult = llmPredict({ prompt: calcPrompt })
|
|
236171
236198
|
|
|
236172
236199
|
// Format the answer
|
|
236173
|
-
let answerPrompt =
|
|
236174
|
-
The calculated result is: \${calcResult}
|
|
236175
|
-
Write a brief, friendly response with the answer.\`
|
|
236200
|
+
let answerPrompt = 'The user asked: "' + question + '"\\nThe calculated result is: ' + calcResult + '\\nWrite a brief, friendly response with the answer.'
|
|
236176
236201
|
let answer = llmPredict({ prompt: answerPrompt })
|
|
236177
236202
|
|
|
236178
236203
|
return { question, expression: expression.trim(), result: calcResult.trim(), answer }
|
|
@@ -236185,26 +236210,15 @@ Write a brief, friendly response with the answer.\`
|
|
|
236185
236210
|
requiresApi: true,
|
|
236186
236211
|
code: `function collaborativeWriting({ topic = 'the future of renewable energy' }) {
|
|
236187
236212
|
// Agent 1: Research Agent - generates key points
|
|
236188
|
-
let researchPrompt =
|
|
236189
|
-
Format as a numbered list. Be concise.\`
|
|
236213
|
+
let researchPrompt = 'You are a research agent. Generate 3 key facts or points about: ' + topic + '\\nFormat as a numbered list. Be concise.'
|
|
236190
236214
|
let research = llmPredict({ prompt: researchPrompt })
|
|
236191
236215
|
|
|
236192
236216
|
// Agent 2: Writer Agent - creates content from research
|
|
236193
|
-
let writerPrompt =
|
|
236194
|
-
|
|
236195
|
-
\${research}
|
|
236196
|
-
|
|
236197
|
-
Write a short, engaging paragraph (2-3 sentences) about \${topic}.
|
|
236198
|
-
Make it informative and accessible.\`
|
|
236217
|
+
let writerPrompt = 'You are a writer agent. Using these research points:\\n\\n' + research + '\\n\\nWrite a short, engaging paragraph (2-3 sentences) about ' + topic + '.\\nMake it informative and accessible.'
|
|
236199
236218
|
let article = llmPredict({ prompt: writerPrompt })
|
|
236200
236219
|
|
|
236201
236220
|
// Agent 3: Editor Agent - reviews and improves
|
|
236202
|
-
let editorPrompt =
|
|
236203
|
-
|
|
236204
|
-
"\${article}"
|
|
236205
|
-
|
|
236206
|
-
Suggest one specific improvement. Then provide the improved version.
|
|
236207
|
-
Format: "Suggestion: [your suggestion]\\n\\nImproved: [improved text]"\`
|
|
236221
|
+
let editorPrompt = 'You are an editor agent. Review this draft:\\n\\n"' + article + '"\\n\\nSuggest one specific improvement. Then provide the improved version.\\nFormat: "Suggestion: [your suggestion]\\n\\nImproved: [improved text]"'
|
|
236208
236222
|
let edited = llmPredict({ prompt: editorPrompt })
|
|
236209
236223
|
|
|
236210
236224
|
return {
|
|
@@ -236290,36 +236304,16 @@ Format: "Suggestion: [your suggestion]\\n\\nImproved: [improved text]"\`
|
|
|
236290
236304
|
requiresApi: true,
|
|
236291
236305
|
code: `function solveWithCode({ problem = 'Calculate the 10th Fibonacci number' }) {
|
|
236292
236306
|
// System prompt with AsyncJS rules and example
|
|
236293
|
-
let systemContext =
|
|
236294
|
-
|
|
236295
|
-
RULES:
|
|
236296
|
-
- NO: async, await, new, class, this, var, for loops
|
|
236297
|
-
- Use let for variables, while for loops
|
|
236298
|
-
- Return an object: return { result }
|
|
236299
|
-
|
|
236300
|
-
EXAMPLE (factorial):
|
|
236301
|
-
function solve() {
|
|
236302
|
-
let result = 1
|
|
236303
|
-
let i = 5
|
|
236304
|
-
while (i > 1) {
|
|
236305
|
-
result = result * i
|
|
236306
|
-
i = i - 1
|
|
236307
|
-
}
|
|
236308
|
-
return { result }
|
|
236309
|
-
}
|
|
236310
|
-
|
|
236311
|
-
Return ONLY the function code, nothing else.\`
|
|
236307
|
+
let systemContext = 'You write AsyncJS code. AsyncJS is a JavaScript subset.\\n\\nRULES:\\n- NO: async, await, new, class, this, var, for loops\\n- Use let for variables, while for loops\\n- Return an object: return { result }\\n\\nEXAMPLE (factorial):\\nfunction solve() {\\n let result = 1\\n let i = 5\\n while (i > 1) {\\n result = result * i\\n i = i - 1\\n }\\n return { result }\\n}\\n\\nReturn ONLY the function code, nothing else.'
|
|
236312
236308
|
|
|
236313
|
-
let prompt =
|
|
236314
|
-
|
|
236315
|
-
Write a function called "solve" that: \${problem}\`
|
|
236309
|
+
let prompt = systemContext + '\\n\\nWrite a function called "solve" that: ' + problem
|
|
236316
236310
|
|
|
236317
236311
|
let response = llmPredict({ prompt })
|
|
236318
236312
|
|
|
236319
236313
|
// Clean up code - remove markdown fences, fix escapes, extract function
|
|
236320
236314
|
let code = response
|
|
236321
|
-
code = code.replace(
|
|
236322
|
-
code = code.replace(/\\n
|
|
236315
|
+
code = code.replace(/\\\`\\\`\\\`(?:javascript|js|asyncjs)?\\n?/g, '')
|
|
236316
|
+
code = code.replace(/\\n?\\\`\\\`\\\`/g, '')
|
|
236323
236317
|
code = code.replace(/\\\\n/g, '\\n')
|
|
236324
236318
|
code = code.replace(/\\\\t/g, '\\t')
|
|
236325
236319
|
code = code.replace(/\\\\"/g, '"')
|
|
@@ -236357,43 +236351,22 @@ Write a function called "solve" that: \${problem}\`
|
|
|
236357
236351
|
requiresApi: true,
|
|
236358
236352
|
code: `function generateCode({ task = 'Calculate the factorial of n' }) {
|
|
236359
236353
|
// System prompt with AsyncJS rules and complete example
|
|
236360
|
-
let systemContext =
|
|
236361
|
-
|
|
236362
|
-
RULES:
|
|
236363
|
-
- Types by example: fn(n: 5) means required number param with example value 5
|
|
236364
|
-
- NO: async, await, new, class, this, var, for, generator functions (function*)
|
|
236365
|
-
- Use let for variables, while for loops
|
|
236366
|
-
- Return an object: return { result }
|
|
236367
|
-
|
|
236368
|
-
EXAMPLE - calculating sum of 1 to n:
|
|
236369
|
-
function sumTo(n: 10) {
|
|
236370
|
-
let sum = 0
|
|
236371
|
-
let i = 1
|
|
236372
|
-
while (i <= n) {
|
|
236373
|
-
sum = sum + i
|
|
236374
|
-
i = i + 1
|
|
236375
|
-
}
|
|
236376
|
-
return { result: sum }
|
|
236377
|
-
}\`
|
|
236354
|
+
let systemContext = 'You write AsyncJS code. AsyncJS is a subset of JavaScript.\\n\\nRULES:\\n- Types by example: fn(n: 5) means required number param with example value 5\\n- NO: async, await, new, class, this, var, for, generator functions (function*)\\n- Use let for variables, while for loops\\n- Return an object: return { result }\\n\\nEXAMPLE - calculating sum of 1 to n:\\nfunction sumTo(n: 10) {\\n let sum = 0\\n let i = 1\\n while (i <= n) {\\n sum = sum + i\\n i = i + 1\\n }\\n return { result: sum }\\n}'
|
|
236378
236355
|
|
|
236379
236356
|
let schema = Schema.response('generated_code', {
|
|
236380
236357
|
code: '',
|
|
236381
236358
|
description: ''
|
|
236382
236359
|
})
|
|
236383
236360
|
|
|
236384
|
-
let prompt =
|
|
236385
|
-
|
|
236386
|
-
Write an AsyncJS function for: \${task}
|
|
236387
|
-
|
|
236388
|
-
Return ONLY valid AsyncJS code in the code field. Must start with "function" and use while loops (not for loops).\`
|
|
236361
|
+
let prompt = systemContext + '\\n\\nWrite an AsyncJS function for: ' + task + '\\n\\nReturn ONLY valid AsyncJS code in the code field. Must start with "function" and use while loops (not for loops).'
|
|
236389
236362
|
|
|
236390
236363
|
let response = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
236391
236364
|
let result = JSON.parse(response)
|
|
236392
236365
|
|
|
236393
236366
|
// Clean up any markdown fences and fix escaped newlines
|
|
236394
236367
|
let code = result.code
|
|
236395
|
-
code = code.replace(
|
|
236396
|
-
code = code.replace(/\\n
|
|
236368
|
+
code = code.replace(/\\\`\\\`\\\`(?:javascript|js)?\\n?/g, '')
|
|
236369
|
+
code = code.replace(/\\n?\\\`\\\`\\\`/g, '')
|
|
236397
236370
|
code = code.replace(/\\\\n/g, '\\n')
|
|
236398
236371
|
code = code.replace(/\\\\t/g, '\\t')
|
|
236399
236372
|
code = code.trim()
|
|
@@ -243813,6 +243786,489 @@ async function resolveImports(source) {
|
|
|
243813
243786
|
return { importMap: { imports }, errors, localModules };
|
|
243814
243787
|
}
|
|
243815
243788
|
|
|
243789
|
+
// demo/src/playground-shared.ts
|
|
243790
|
+
var TJS_RUNTIME_STUB = `
|
|
243791
|
+
globalThis.__tjs = {
|
|
243792
|
+
version: '0.0.0',
|
|
243793
|
+
pushStack: () => {},
|
|
243794
|
+
popStack: () => {},
|
|
243795
|
+
getStack: () => [],
|
|
243796
|
+
typeError: (path, expected, value) => {
|
|
243797
|
+
const actual = value === null ? 'null' : typeof value;
|
|
243798
|
+
const err = new Error(\\\`Expected \\\${expected} for '\\\${path}', got \\\${actual}\\\`);
|
|
243799
|
+
err.name = 'MonadicError';
|
|
243800
|
+
err.path = path;
|
|
243801
|
+
err.expected = expected;
|
|
243802
|
+
err.actual = actual;
|
|
243803
|
+
return err;
|
|
243804
|
+
},
|
|
243805
|
+
createRuntime: function() { return this; },
|
|
243806
|
+
Is: (a, b) => {
|
|
243807
|
+
if (a === b) return true;
|
|
243808
|
+
if (a === null || b === null) return a === b;
|
|
243809
|
+
if (typeof a !== typeof b) return false;
|
|
243810
|
+
if (typeof a !== 'object') return false;
|
|
243811
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
243812
|
+
if (a.length !== b.length) return false;
|
|
243813
|
+
return a.every((v, i) => globalThis.__tjs.Is(v, b[i]));
|
|
243814
|
+
}
|
|
243815
|
+
const keysA = Object.keys(a);
|
|
243816
|
+
const keysB = Object.keys(b);
|
|
243817
|
+
if (keysA.length !== keysB.length) return false;
|
|
243818
|
+
return keysA.every(k => globalThis.__tjs.Is(a[k], b[k]));
|
|
243819
|
+
},
|
|
243820
|
+
IsNot: (a, b) => !globalThis.__tjs.Is(a, b),
|
|
243821
|
+
};`;
|
|
243822
|
+
var CONSOLE_CAPTURE_SCRIPT = `
|
|
243823
|
+
const _log = console.log;
|
|
243824
|
+
console.log = (...args) => {
|
|
243825
|
+
_log(...args);
|
|
243826
|
+
parent.postMessage({ type: 'console', message: args.map(a => {
|
|
243827
|
+
if (typeof a !== 'object' || a === null) return String(a);
|
|
243828
|
+
try {
|
|
243829
|
+
return JSON.stringify(a, null, 2);
|
|
243830
|
+
} catch {
|
|
243831
|
+
return String(a);
|
|
243832
|
+
}
|
|
243833
|
+
}).join(' ') }, '*');
|
|
243834
|
+
};`;
|
|
243835
|
+
function buildIframeDoc(options2) {
|
|
243836
|
+
const {
|
|
243837
|
+
cssContent,
|
|
243838
|
+
htmlContent,
|
|
243839
|
+
importMapScript,
|
|
243840
|
+
jsCode,
|
|
243841
|
+
importStatements = [],
|
|
243842
|
+
parentBindings = false,
|
|
243843
|
+
autoCallTjsFunction = false
|
|
243844
|
+
} = options2;
|
|
243845
|
+
const parentBindingsScript = parentBindings ? `
|
|
243846
|
+
if (parent.run) window.run = parent.run.bind(parent);
|
|
243847
|
+
if (parent.runAgent) window.runAgent = parent.runAgent.bind(parent);
|
|
243848
|
+
if (parent.getIdToken) window.getIdToken = parent.getIdToken.bind(parent);` : "";
|
|
243849
|
+
const useSeparateScripts = importStatements.length > 0;
|
|
243850
|
+
const executionCode = autoCallTjsFunction ? `
|
|
243851
|
+
const __execStart = performance.now();
|
|
243852
|
+
${jsCode}
|
|
243853
|
+
|
|
243854
|
+
// Try to call the function if it exists and show result
|
|
243855
|
+
const funcName = Object.keys(window).find(k => {
|
|
243856
|
+
try { return typeof window[k] === 'function' && window[k].__tjs; }
|
|
243857
|
+
catch { return false; }
|
|
243858
|
+
});
|
|
243859
|
+
if (funcName) {
|
|
243860
|
+
const __callStart = performance.now();
|
|
243861
|
+
const result = window[funcName]();
|
|
243862
|
+
const __execTime = performance.now() - __callStart;
|
|
243863
|
+
parent.postMessage({ type: 'timing', execTime: __execTime }, '*');
|
|
243864
|
+
if (result !== undefined) {
|
|
243865
|
+
if (result instanceof Node) {
|
|
243866
|
+
document.body.append(result);
|
|
243867
|
+
parent.postMessage({ type: 'hasPreviewContent' }, '*');
|
|
243868
|
+
} else {
|
|
243869
|
+
console.log('Result:', result);
|
|
243870
|
+
}
|
|
243871
|
+
}
|
|
243872
|
+
} else {
|
|
243873
|
+
const __execTime = performance.now() - __execStart;
|
|
243874
|
+
parent.postMessage({ type: 'timing', execTime: __execTime }, '*');
|
|
243875
|
+
}` : `
|
|
243876
|
+
const __execStart = performance.now();
|
|
243877
|
+
${jsCode}
|
|
243878
|
+
const __execTime = performance.now() - __execStart;
|
|
243879
|
+
parent.postMessage({ type: 'timing', execTime: __execTime }, '*');`;
|
|
243880
|
+
if (useSeparateScripts) {
|
|
243881
|
+
return `<!DOCTYPE html>
|
|
243882
|
+
<html>
|
|
243883
|
+
<head>
|
|
243884
|
+
<style>${cssContent}</style>
|
|
243885
|
+
${importMapScript}
|
|
243886
|
+
</head>
|
|
243887
|
+
<body>
|
|
243888
|
+
${htmlContent}
|
|
243889
|
+
<script>${parentBindingsScript}
|
|
243890
|
+
${TJS_RUNTIME_STUB}
|
|
243891
|
+
</script>
|
|
243892
|
+
<script type="module">
|
|
243893
|
+
${importStatements.join(`
|
|
243894
|
+
`)}
|
|
243895
|
+
${CONSOLE_CAPTURE_SCRIPT}
|
|
243896
|
+
|
|
243897
|
+
const __childrenBefore = document.body.children.length;
|
|
243898
|
+
try {${executionCode}
|
|
243899
|
+
if (document.body.children.length > __childrenBefore) {
|
|
243900
|
+
parent.postMessage({ type: 'hasPreviewContent' }, '*');
|
|
243901
|
+
}
|
|
243902
|
+
} catch (e) {
|
|
243903
|
+
parent.postMessage({ type: 'error', message: e.message }, '*');
|
|
243904
|
+
}
|
|
243905
|
+
</script>
|
|
243906
|
+
</body>
|
|
243907
|
+
</html>`;
|
|
243908
|
+
}
|
|
243909
|
+
return `<!DOCTYPE html>
|
|
243910
|
+
<html>
|
|
243911
|
+
<head>
|
|
243912
|
+
<style>${cssContent}</style>
|
|
243913
|
+
${importMapScript}
|
|
243914
|
+
</head>
|
|
243915
|
+
<body>
|
|
243916
|
+
${htmlContent}
|
|
243917
|
+
<script type="module">${parentBindingsScript}
|
|
243918
|
+
${TJS_RUNTIME_STUB}
|
|
243919
|
+
${CONSOLE_CAPTURE_SCRIPT}
|
|
243920
|
+
|
|
243921
|
+
const __childrenBefore = document.body.children.length;
|
|
243922
|
+
try {${executionCode}
|
|
243923
|
+
if (document.body.children.length > __childrenBefore) {
|
|
243924
|
+
parent.postMessage({ type: 'hasPreviewContent' }, '*');
|
|
243925
|
+
}
|
|
243926
|
+
} catch (e) {
|
|
243927
|
+
parent.postMessage({ type: 'error', message: e.message }, '*');
|
|
243928
|
+
}
|
|
243929
|
+
</script>
|
|
243930
|
+
</body>
|
|
243931
|
+
</html>`;
|
|
243932
|
+
}
|
|
243933
|
+
function createIframeMessageHandler(callbacks) {
|
|
243934
|
+
return (event) => {
|
|
243935
|
+
if (event.data?.type === "console") {
|
|
243936
|
+
callbacks.onConsole(event.data.message);
|
|
243937
|
+
} else if (event.data?.type === "timing") {
|
|
243938
|
+
callbacks.onTiming(event.data.execTime);
|
|
243939
|
+
} else if (event.data?.type === "hasPreviewContent") {
|
|
243940
|
+
callbacks.onPreviewContent();
|
|
243941
|
+
} else if (event.data?.type === "error") {
|
|
243942
|
+
callbacks.onError(event.data.message);
|
|
243943
|
+
}
|
|
243944
|
+
};
|
|
243945
|
+
}
|
|
243946
|
+
function renderConsoleMessages(messages, consoleEl, goToLine) {
|
|
243947
|
+
const linePattern = /(?:at line |line |Line )(\d+)(?:[:,]?\s*(?:column |col )?(\d+))?|:(\d+):(\d+)/g;
|
|
243948
|
+
const html2 = messages.map((msg) => {
|
|
243949
|
+
const escaped = msg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
243950
|
+
return escaped.replace(linePattern, (match, l1, c12, l22, c22) => {
|
|
243951
|
+
const line = l1 || l22;
|
|
243952
|
+
const col = c12 || c22 || "1";
|
|
243953
|
+
return `<span class="clickable-line" data-line="${line}" data-col="${col}">${match}</span>`;
|
|
243954
|
+
});
|
|
243955
|
+
}).join(`
|
|
243956
|
+
`);
|
|
243957
|
+
consoleEl.innerHTML = html2;
|
|
243958
|
+
consoleEl.scrollTop = consoleEl.scrollHeight;
|
|
243959
|
+
consoleEl.querySelectorAll(".clickable-line").forEach((el2) => {
|
|
243960
|
+
el2.addEventListener("click", (e) => {
|
|
243961
|
+
const target = e.currentTarget;
|
|
243962
|
+
const line = parseInt(target.dataset.line || "0", 10);
|
|
243963
|
+
const col = parseInt(target.dataset.col || "1", 10);
|
|
243964
|
+
if (line > 0) {
|
|
243965
|
+
goToLine(line, col);
|
|
243966
|
+
}
|
|
243967
|
+
});
|
|
243968
|
+
});
|
|
243969
|
+
}
|
|
243970
|
+
function renderTestResults(tests, outputEl, editor, goToLine) {
|
|
243971
|
+
if (!tests || tests.length === 0) {
|
|
243972
|
+
outputEl.textContent = "No tests defined";
|
|
243973
|
+
editor.clearMarkers();
|
|
243974
|
+
return { passed: 0, failed: 0 };
|
|
243975
|
+
}
|
|
243976
|
+
const passed = tests.filter((t2) => t2.passed).length;
|
|
243977
|
+
const failed = tests.filter((t2) => !t2.passed).length;
|
|
243978
|
+
const failedTests = tests.filter((t2) => !t2.passed && t2.line);
|
|
243979
|
+
if (failedTests.length > 0) {
|
|
243980
|
+
editor.setMarkers(failedTests.map((t2) => ({
|
|
243981
|
+
line: t2.line,
|
|
243982
|
+
message: t2.error || t2.description,
|
|
243983
|
+
severity: "error"
|
|
243984
|
+
})));
|
|
243985
|
+
} else {
|
|
243986
|
+
editor.clearMarkers();
|
|
243987
|
+
}
|
|
243988
|
+
let html2 = `<div class="test-summary">`;
|
|
243989
|
+
html2 += `<strong>${passed} passed</strong>`;
|
|
243990
|
+
if (failed > 0) {
|
|
243991
|
+
html2 += `, <strong class="test-failed">${failed} failed</strong>`;
|
|
243992
|
+
}
|
|
243993
|
+
html2 += `</div><ul class="test-list">`;
|
|
243994
|
+
for (const test of tests) {
|
|
243995
|
+
const icon = test.passed ? "✓" : "✗";
|
|
243996
|
+
const cls = test.passed ? "test-pass" : "test-fail";
|
|
243997
|
+
const sigBadge = test.isSignatureTest ? ' <span class="sig-badge">signature</span>' : "";
|
|
243998
|
+
const dataLine = test.line ? ` data-line="${test.line}"` : "";
|
|
243999
|
+
html2 += `<li class="${cls}"${dataLine}>${icon} ${test.description}${sigBadge}`;
|
|
244000
|
+
if (!test.passed && test.error) {
|
|
244001
|
+
html2 += `<div class="test-error${test.line ? " clickable-error" : ""}"${dataLine}>${test.error}</div>`;
|
|
244002
|
+
}
|
|
244003
|
+
html2 += `</li>`;
|
|
244004
|
+
}
|
|
244005
|
+
html2 += `</ul>`;
|
|
244006
|
+
outputEl.innerHTML = html2;
|
|
244007
|
+
outputEl.querySelectorAll(".clickable-error").forEach((el2) => {
|
|
244008
|
+
el2.addEventListener("click", (e) => {
|
|
244009
|
+
const line = parseInt(e.currentTarget.dataset.line || "0", 10);
|
|
244010
|
+
if (line > 0) {
|
|
244011
|
+
goToLine(line);
|
|
244012
|
+
}
|
|
244013
|
+
});
|
|
244014
|
+
});
|
|
244015
|
+
return { passed, failed };
|
|
244016
|
+
}
|
|
244017
|
+
function formatExecTime(ms2) {
|
|
244018
|
+
return ms2 < 1 ? `${(ms2 * 1000).toFixed(0)}μs` : `${ms2.toFixed(2)}ms`;
|
|
244019
|
+
}
|
|
244020
|
+
var sharedPlaygroundStyles = {
|
|
244021
|
+
":host": {
|
|
244022
|
+
display: "flex",
|
|
244023
|
+
flexDirection: "column",
|
|
244024
|
+
height: "100%",
|
|
244025
|
+
flex: "1 1 auto",
|
|
244026
|
+
background: "var(--background, #fff)",
|
|
244027
|
+
color: "var(--text-color, #1f2937)",
|
|
244028
|
+
fontFamily: "system-ui, sans-serif"
|
|
244029
|
+
},
|
|
244030
|
+
":host .run-btn": {
|
|
244031
|
+
display: "flex",
|
|
244032
|
+
alignItems: "center",
|
|
244033
|
+
gap: "4px",
|
|
244034
|
+
padding: "6px 12px",
|
|
244035
|
+
background: "var(--brand-color, #3d4a6b)",
|
|
244036
|
+
color: "var(--brand-text-color, white)",
|
|
244037
|
+
border: "none",
|
|
244038
|
+
borderRadius: "6px",
|
|
244039
|
+
cursor: "pointer",
|
|
244040
|
+
fontWeight: "500",
|
|
244041
|
+
fontSize: "14px"
|
|
244042
|
+
},
|
|
244043
|
+
":host .run-btn:hover:not(:disabled)": {
|
|
244044
|
+
filter: "brightness(1.1)"
|
|
244045
|
+
},
|
|
244046
|
+
":host .run-btn:disabled": {
|
|
244047
|
+
opacity: "0.6",
|
|
244048
|
+
cursor: "not-allowed"
|
|
244049
|
+
},
|
|
244050
|
+
":host .toolbar-separator": {
|
|
244051
|
+
width: "1px",
|
|
244052
|
+
height: "20px",
|
|
244053
|
+
background: "var(--code-border, #d1d5db)"
|
|
244054
|
+
},
|
|
244055
|
+
":host .build-flags": {
|
|
244056
|
+
display: "flex",
|
|
244057
|
+
alignItems: "center",
|
|
244058
|
+
gap: "12px"
|
|
244059
|
+
},
|
|
244060
|
+
":host .flag-label": {
|
|
244061
|
+
display: "flex",
|
|
244062
|
+
alignItems: "center",
|
|
244063
|
+
gap: "4px",
|
|
244064
|
+
fontSize: "13px",
|
|
244065
|
+
color: "var(--text-color, #6b7280)",
|
|
244066
|
+
cursor: "pointer",
|
|
244067
|
+
userSelect: "none"
|
|
244068
|
+
},
|
|
244069
|
+
":host .flag-label:hover": {
|
|
244070
|
+
color: "var(--text-color, #374151)"
|
|
244071
|
+
},
|
|
244072
|
+
':host .flag-label input[type="checkbox"]': {
|
|
244073
|
+
margin: "0",
|
|
244074
|
+
cursor: "pointer",
|
|
244075
|
+
accentColor: "var(--brand-color, #3d4a6b)"
|
|
244076
|
+
},
|
|
244077
|
+
":host .revert-btn": {
|
|
244078
|
+
display: "flex",
|
|
244079
|
+
alignItems: "center",
|
|
244080
|
+
gap: "4px",
|
|
244081
|
+
padding: "6px 12px",
|
|
244082
|
+
background: "var(--code-background, #e5e7eb)",
|
|
244083
|
+
color: "var(--text-color, #374151)",
|
|
244084
|
+
border: "1px solid var(--code-border, #d1d5db)",
|
|
244085
|
+
borderRadius: "6px",
|
|
244086
|
+
cursor: "pointer",
|
|
244087
|
+
fontWeight: "500",
|
|
244088
|
+
fontSize: "14px",
|
|
244089
|
+
transition: "opacity 0.2s"
|
|
244090
|
+
},
|
|
244091
|
+
":host .revert-btn:hover:not(:disabled)": {
|
|
244092
|
+
background: "#fef3c7",
|
|
244093
|
+
borderColor: "#f59e0b",
|
|
244094
|
+
color: "#92400e"
|
|
244095
|
+
},
|
|
244096
|
+
":host .revert-btn:disabled": {
|
|
244097
|
+
cursor: "default"
|
|
244098
|
+
},
|
|
244099
|
+
":host .elastic": {
|
|
244100
|
+
flex: "1"
|
|
244101
|
+
},
|
|
244102
|
+
":host .status-bar": {
|
|
244103
|
+
fontSize: "13px",
|
|
244104
|
+
color: "var(--text-color, #6b7280)",
|
|
244105
|
+
opacity: "0.7"
|
|
244106
|
+
},
|
|
244107
|
+
":host .status-bar.error": {
|
|
244108
|
+
color: "#dc2626",
|
|
244109
|
+
opacity: "1"
|
|
244110
|
+
},
|
|
244111
|
+
":host tosi-tabs > [name]": {
|
|
244112
|
+
background: "var(--background, #fff)",
|
|
244113
|
+
color: "var(--text-color, #1f2937)"
|
|
244114
|
+
},
|
|
244115
|
+
":host .editor-wrapper": {
|
|
244116
|
+
flex: "1 1 auto",
|
|
244117
|
+
height: "100%",
|
|
244118
|
+
minHeight: "300px",
|
|
244119
|
+
position: "relative",
|
|
244120
|
+
overflow: "hidden"
|
|
244121
|
+
},
|
|
244122
|
+
":host .editor-wrapper code-mirror": {
|
|
244123
|
+
display: "block",
|
|
244124
|
+
position: "absolute",
|
|
244125
|
+
top: "0",
|
|
244126
|
+
left: "0",
|
|
244127
|
+
right: "0",
|
|
244128
|
+
bottom: "0"
|
|
244129
|
+
},
|
|
244130
|
+
":host .preview-frame": {
|
|
244131
|
+
width: "100%",
|
|
244132
|
+
height: "100%",
|
|
244133
|
+
border: "none",
|
|
244134
|
+
background: "var(--background, #fff)"
|
|
244135
|
+
},
|
|
244136
|
+
":host .docs-output": {
|
|
244137
|
+
display: "block",
|
|
244138
|
+
padding: "12px 16px",
|
|
244139
|
+
fontSize: "14px",
|
|
244140
|
+
fontFamily: "system-ui, sans-serif",
|
|
244141
|
+
color: "var(--text-color, inherit)",
|
|
244142
|
+
background: "var(--background, #fff)",
|
|
244143
|
+
height: "100%",
|
|
244144
|
+
overflow: "auto"
|
|
244145
|
+
},
|
|
244146
|
+
":host .docs-output h2": {
|
|
244147
|
+
fontSize: "1.25em",
|
|
244148
|
+
marginTop: "0",
|
|
244149
|
+
marginBottom: "0.5em",
|
|
244150
|
+
color: "var(--text-color, #1f2937)"
|
|
244151
|
+
},
|
|
244152
|
+
":host .docs-output pre": {
|
|
244153
|
+
background: "var(--code-background, #f3f4f6)",
|
|
244154
|
+
padding: "8px 12px",
|
|
244155
|
+
borderRadius: "6px",
|
|
244156
|
+
overflow: "auto",
|
|
244157
|
+
fontSize: "13px"
|
|
244158
|
+
},
|
|
244159
|
+
":host .docs-output code": {
|
|
244160
|
+
fontFamily: "ui-monospace, monospace",
|
|
244161
|
+
fontSize: "0.9em"
|
|
244162
|
+
},
|
|
244163
|
+
":host .docs-output p": {
|
|
244164
|
+
margin: "0.75em 0",
|
|
244165
|
+
lineHeight: "1.5"
|
|
244166
|
+
},
|
|
244167
|
+
":host .docs-output h3": {
|
|
244168
|
+
fontSize: "1em",
|
|
244169
|
+
marginTop: "1em",
|
|
244170
|
+
marginBottom: "0.5em"
|
|
244171
|
+
},
|
|
244172
|
+
":host .docs-output ul": {
|
|
244173
|
+
paddingLeft: "1.5em",
|
|
244174
|
+
margin: "0.5em 0"
|
|
244175
|
+
},
|
|
244176
|
+
":host .docs-output li": {
|
|
244177
|
+
marginBottom: "0.25em"
|
|
244178
|
+
},
|
|
244179
|
+
":host .docs-output hr": {
|
|
244180
|
+
border: "none",
|
|
244181
|
+
borderTop: "1px solid var(--code-border, #e5e7eb)",
|
|
244182
|
+
margin: "1.5em 0"
|
|
244183
|
+
},
|
|
244184
|
+
":host .tests-output": {
|
|
244185
|
+
padding: "12px",
|
|
244186
|
+
fontSize: "14px",
|
|
244187
|
+
fontFamily: "system-ui, sans-serif",
|
|
244188
|
+
color: "var(--text-color, inherit)",
|
|
244189
|
+
background: "var(--background, #fff)",
|
|
244190
|
+
height: "100%",
|
|
244191
|
+
overflow: "auto"
|
|
244192
|
+
},
|
|
244193
|
+
":host .test-summary": {
|
|
244194
|
+
marginBottom: "12px",
|
|
244195
|
+
paddingBottom: "8px",
|
|
244196
|
+
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
244197
|
+
},
|
|
244198
|
+
":host .test-failed": {
|
|
244199
|
+
color: "#dc2626"
|
|
244200
|
+
},
|
|
244201
|
+
":host .test-list": {
|
|
244202
|
+
listStyle: "none",
|
|
244203
|
+
padding: "0",
|
|
244204
|
+
margin: "0"
|
|
244205
|
+
},
|
|
244206
|
+
":host .test-list li": {
|
|
244207
|
+
padding: "4px 0"
|
|
244208
|
+
},
|
|
244209
|
+
":host .test-pass": {
|
|
244210
|
+
color: "#16a34a"
|
|
244211
|
+
},
|
|
244212
|
+
":host .test-fail": {
|
|
244213
|
+
color: "#dc2626"
|
|
244214
|
+
},
|
|
244215
|
+
":host .test-error": {
|
|
244216
|
+
marginLeft: "20px",
|
|
244217
|
+
marginTop: "4px",
|
|
244218
|
+
padding: "8px",
|
|
244219
|
+
background: "rgba(220, 38, 38, 0.1)",
|
|
244220
|
+
borderRadius: "4px",
|
|
244221
|
+
fontSize: "13px",
|
|
244222
|
+
fontFamily: "var(--font-mono, monospace)"
|
|
244223
|
+
},
|
|
244224
|
+
":host .clickable-error": {
|
|
244225
|
+
cursor: "pointer",
|
|
244226
|
+
textDecoration: "underline",
|
|
244227
|
+
textDecorationStyle: "dotted"
|
|
244228
|
+
},
|
|
244229
|
+
":host .clickable-error:hover": {
|
|
244230
|
+
background: "rgba(220, 38, 38, 0.2)"
|
|
244231
|
+
},
|
|
244232
|
+
":host .sig-badge": {
|
|
244233
|
+
fontSize: "11px",
|
|
244234
|
+
padding: "2px 6px",
|
|
244235
|
+
marginLeft: "8px",
|
|
244236
|
+
background: "rgba(99, 102, 241, 0.1)",
|
|
244237
|
+
color: "#6366f1",
|
|
244238
|
+
borderRadius: "4px"
|
|
244239
|
+
},
|
|
244240
|
+
":host .console-header": {
|
|
244241
|
+
padding: "4px 12px",
|
|
244242
|
+
background: "var(--code-background, #f3f4f6)",
|
|
244243
|
+
fontSize: "12px",
|
|
244244
|
+
fontWeight: "500",
|
|
244245
|
+
color: "var(--text-color, #6b7280)",
|
|
244246
|
+
opacity: "0.7",
|
|
244247
|
+
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
244248
|
+
},
|
|
244249
|
+
":host .console-output": {
|
|
244250
|
+
flex: "1",
|
|
244251
|
+
margin: "0",
|
|
244252
|
+
padding: "8px 12px",
|
|
244253
|
+
background: "var(--code-background, #f3f4f6)",
|
|
244254
|
+
color: "var(--text-color, #1f2937)",
|
|
244255
|
+
fontSize: "12px",
|
|
244256
|
+
fontFamily: "ui-monospace, monospace",
|
|
244257
|
+
overflow: "auto",
|
|
244258
|
+
whiteSpace: "pre-wrap"
|
|
244259
|
+
},
|
|
244260
|
+
":host .clickable-line": {
|
|
244261
|
+
cursor: "pointer",
|
|
244262
|
+
color: "#2563eb",
|
|
244263
|
+
textDecoration: "underline",
|
|
244264
|
+
textDecorationStyle: "dotted"
|
|
244265
|
+
},
|
|
244266
|
+
":host .clickable-line:hover": {
|
|
244267
|
+
color: "#1d4ed8",
|
|
244268
|
+
background: "rgba(37, 99, 235, 0.1)"
|
|
244269
|
+
}
|
|
244270
|
+
};
|
|
244271
|
+
|
|
243816
244272
|
// demo/src/tjs-playground.ts
|
|
243817
244273
|
init_module_store();
|
|
243818
244274
|
|
|
@@ -244088,28 +244544,7 @@ class TJSPlayground extends g {
|
|
|
244088
244544
|
iframe.src = "about:blank";
|
|
244089
244545
|
};
|
|
244090
244546
|
renderConsole() {
|
|
244091
|
-
|
|
244092
|
-
const html2 = this.consoleMessages.map((msg) => {
|
|
244093
|
-
const escaped = msg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
244094
|
-
return escaped.replace(linePattern, (match, l1, c12, l22, c22) => {
|
|
244095
|
-
const line = l1 || l22;
|
|
244096
|
-
const col = c12 || c22 || "1";
|
|
244097
|
-
return `<span class="clickable-line" data-line="${line}" data-col="${col}">${match}</span>`;
|
|
244098
|
-
});
|
|
244099
|
-
}).join(`
|
|
244100
|
-
`);
|
|
244101
|
-
this.parts.console.innerHTML = html2;
|
|
244102
|
-
this.parts.console.scrollTop = this.parts.console.scrollHeight;
|
|
244103
|
-
this.parts.console.querySelectorAll(".clickable-line").forEach((el2) => {
|
|
244104
|
-
el2.addEventListener("click", (e) => {
|
|
244105
|
-
const target = e.currentTarget;
|
|
244106
|
-
const line = parseInt(target.dataset.line || "0", 10);
|
|
244107
|
-
const col = parseInt(target.dataset.col || "1", 10);
|
|
244108
|
-
if (line > 0) {
|
|
244109
|
-
this.goToSourceLine(line, col);
|
|
244110
|
-
}
|
|
244111
|
-
});
|
|
244112
|
-
});
|
|
244547
|
+
renderConsoleMessages(this.consoleMessages, this.parts.console, (line, col) => this.goToSourceLine(line, col));
|
|
244113
244548
|
}
|
|
244114
244549
|
toggleTests = () => {
|
|
244115
244550
|
this.buildFlags.tests = this.parts.testsToggle.checked;
|
|
@@ -244156,7 +244591,7 @@ class TJSPlayground extends g {
|
|
|
244156
244591
|
this.updateDocs(result);
|
|
244157
244592
|
const tests = result.testResults || [];
|
|
244158
244593
|
const failed = tests.filter((t2) => !t2.passed).length;
|
|
244159
|
-
const timeStr =
|
|
244594
|
+
const timeStr = formatExecTime(this.lastTranspileTime);
|
|
244160
244595
|
if (failed > 0) {
|
|
244161
244596
|
this.parts.statusBar.textContent = `Transpiled in ${timeStr} with ${failed} test failure${failed > 1 ? "s" : ""}`;
|
|
244162
244597
|
this.parts.statusBar.classList.add("error");
|
|
@@ -244203,53 +244638,8 @@ class TJSPlayground extends g {
|
|
|
244203
244638
|
};
|
|
244204
244639
|
updateTestResults(result) {
|
|
244205
244640
|
const tests = result.testResults;
|
|
244206
|
-
|
|
244207
|
-
this.parts.testsOutput.textContent = "No tests defined";
|
|
244208
|
-
this.updateTestsTabLabel(0, 0);
|
|
244209
|
-
this.parts.tjsEditor.clearMarkers();
|
|
244210
|
-
return;
|
|
244211
|
-
}
|
|
244212
|
-
const passed = tests.filter((t2) => t2.passed).length;
|
|
244213
|
-
const failed = tests.filter((t2) => !t2.passed).length;
|
|
244641
|
+
const { passed, failed } = renderTestResults(tests, this.parts.testsOutput, this.parts.tjsEditor, (line) => this.goToSourceLine(line));
|
|
244214
244642
|
this.updateTestsTabLabel(passed, failed);
|
|
244215
|
-
const failedTests = tests.filter((t2) => !t2.passed && t2.line);
|
|
244216
|
-
if (failedTests.length > 0) {
|
|
244217
|
-
this.parts.tjsEditor.setMarkers(failedTests.map((t2) => ({
|
|
244218
|
-
line: t2.line,
|
|
244219
|
-
message: t2.error || t2.description,
|
|
244220
|
-
severity: "error"
|
|
244221
|
-
})));
|
|
244222
|
-
} else {
|
|
244223
|
-
this.parts.tjsEditor.clearMarkers();
|
|
244224
|
-
}
|
|
244225
|
-
let html2 = `<div class="test-summary">`;
|
|
244226
|
-
html2 += `<strong>${passed} passed</strong>`;
|
|
244227
|
-
if (failed > 0) {
|
|
244228
|
-
html2 += `, <strong class="test-failed">${failed} failed</strong>`;
|
|
244229
|
-
}
|
|
244230
|
-
html2 += `</div><ul class="test-list">`;
|
|
244231
|
-
for (const test of tests) {
|
|
244232
|
-
const icon = test.passed ? "✓" : "✗";
|
|
244233
|
-
const cls = test.passed ? "test-pass" : "test-fail";
|
|
244234
|
-
const sigBadge = test.isSignatureTest ? ' <span class="sig-badge">signature</span>' : "";
|
|
244235
|
-
const clickable = !test.passed && test.line ? ' class="clickable-error"' : "";
|
|
244236
|
-
const dataLine = test.line ? ` data-line="${test.line}"` : "";
|
|
244237
|
-
html2 += `<li class="${cls}"${dataLine}>${icon} ${test.description}${sigBadge}`;
|
|
244238
|
-
if (!test.passed && test.error) {
|
|
244239
|
-
html2 += `<div${clickable}${dataLine} class="test-error${test.line ? " clickable-error" : ""}">${test.error}</div>`;
|
|
244240
|
-
}
|
|
244241
|
-
html2 += `</li>`;
|
|
244242
|
-
}
|
|
244243
|
-
html2 += `</ul>`;
|
|
244244
|
-
this.parts.testsOutput.innerHTML = html2;
|
|
244245
|
-
this.parts.testsOutput.querySelectorAll(".clickable-error").forEach((el2) => {
|
|
244246
|
-
el2.addEventListener("click", (e) => {
|
|
244247
|
-
const line = parseInt(e.currentTarget.dataset.line || "0", 10);
|
|
244248
|
-
if (line > 0) {
|
|
244249
|
-
this.goToSourceLine(line);
|
|
244250
|
-
}
|
|
244251
|
-
});
|
|
244252
|
-
});
|
|
244253
244643
|
}
|
|
244254
244644
|
updateTestsTabLabel(passed, failed) {
|
|
244255
244645
|
const tabs = this.parts.outputTabs;
|
|
@@ -244498,6 +244888,7 @@ class TJSPlayground extends g {
|
|
|
244498
244888
|
this.parts.runBtn.disabled = false;
|
|
244499
244889
|
return;
|
|
244500
244890
|
}
|
|
244891
|
+
this.parts.outputTabs.value = 0;
|
|
244501
244892
|
this.parts.statusBar.textContent = "Running...";
|
|
244502
244893
|
try {
|
|
244503
244894
|
const wasmCompiled = this.lastTranspileResult.wasmCompiled;
|
|
@@ -244538,131 +244929,29 @@ class TJSPlayground extends g {
|
|
|
244538
244929
|
importStatements.push(match);
|
|
244539
244930
|
return "";
|
|
244540
244931
|
});
|
|
244541
|
-
const iframeDoc =
|
|
244542
|
-
|
|
244543
|
-
|
|
244544
|
-
|
|
244545
|
-
|
|
244546
|
-
|
|
244547
|
-
|
|
244548
|
-
|
|
244549
|
-
<!-- TJS Runtime stub must be set up BEFORE imports execute -->
|
|
244550
|
-
<script>
|
|
244551
|
-
// Expose parent's run/runAgent/getIdToken in iframe for playground convenience
|
|
244552
|
-
if (parent.run) window.run = parent.run.bind(parent);
|
|
244553
|
-
if (parent.runAgent) window.runAgent = parent.runAgent.bind(parent);
|
|
244554
|
-
if (parent.getIdToken) window.getIdToken = parent.getIdToken.bind(parent);
|
|
244555
|
-
|
|
244556
|
-
// TJS runtime stub - must stay in sync with src/lang/runtime.ts
|
|
244557
|
-
// TODO: Eliminate this once transpiler emits self-contained code
|
|
244558
|
-
// See: src/lang/emitters/js.ts for the plan to inline runtime functions
|
|
244559
|
-
globalThis.__tjs = {
|
|
244560
|
-
version: '0.0.0',
|
|
244561
|
-
pushStack: () => {},
|
|
244562
|
-
popStack: () => {},
|
|
244563
|
-
getStack: () => [],
|
|
244564
|
-
typeError: (path, expected, value) => {
|
|
244565
|
-
const actual = value === null ? 'null' : typeof value;
|
|
244566
|
-
const err = new Error(\`Expected \${expected} for '\${path}', got \${actual}\`);
|
|
244567
|
-
err.name = 'MonadicError';
|
|
244568
|
-
err.path = path;
|
|
244569
|
-
err.expected = expected;
|
|
244570
|
-
err.actual = actual;
|
|
244571
|
-
return err;
|
|
244572
|
-
},
|
|
244573
|
-
createRuntime: function() { return this; },
|
|
244574
|
-
Is: (a, b) => {
|
|
244575
|
-
if (a === b) return true;
|
|
244576
|
-
if (a === null || b === null) return a === b;
|
|
244577
|
-
if (typeof a !== typeof b) return false;
|
|
244578
|
-
if (typeof a !== 'object') return false;
|
|
244579
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
244580
|
-
if (a.length !== b.length) return false;
|
|
244581
|
-
return a.every((v, i) => globalThis.__tjs.Is(v, b[i]));
|
|
244582
|
-
}
|
|
244583
|
-
const keysA = Object.keys(a);
|
|
244584
|
-
const keysB = Object.keys(b);
|
|
244585
|
-
if (keysA.length !== keysB.length) return false;
|
|
244586
|
-
return keysA.every(k => globalThis.__tjs.Is(a[k], b[k]));
|
|
244587
|
-
},
|
|
244588
|
-
IsNot: (a, b) => !globalThis.__tjs.Is(a, b),
|
|
244589
|
-
};
|
|
244590
|
-
</script>
|
|
244591
|
-
<script type="module">
|
|
244592
|
-
// Import statements must be at the top of the module
|
|
244593
|
-
${importStatements.join(`
|
|
244594
|
-
`)}
|
|
244595
|
-
|
|
244596
|
-
// Capture console.log
|
|
244597
|
-
const _log = console.log;
|
|
244598
|
-
console.log = (...args) => {
|
|
244599
|
-
_log(...args);
|
|
244600
|
-
parent.postMessage({ type: 'console', message: args.map(a => {
|
|
244601
|
-
if (typeof a !== 'object' || a === null) return String(a);
|
|
244602
|
-
try {
|
|
244603
|
-
return JSON.stringify(a, null, 2);
|
|
244604
|
-
} catch {
|
|
244605
|
-
return String(a);
|
|
244606
|
-
}
|
|
244607
|
-
}).join(' ') }, '*');
|
|
244608
|
-
};
|
|
244609
|
-
|
|
244610
|
-
try {
|
|
244611
|
-
// WASM blocks are pre-compiled and embedded in the transpiled code
|
|
244612
|
-
// They auto-instantiate via the async IIFE at the top of the code
|
|
244613
|
-
|
|
244614
|
-
const __execStart = performance.now();
|
|
244615
|
-
${codeWithoutImports}
|
|
244616
|
-
|
|
244617
|
-
// Try to call the function if it exists and show result
|
|
244618
|
-
const funcName = Object.keys(window).find(k => {
|
|
244619
|
-
try { return typeof window[k] === 'function' && window[k].__tjs; }
|
|
244620
|
-
catch { return false; }
|
|
244932
|
+
const iframeDoc = buildIframeDoc({
|
|
244933
|
+
cssContent,
|
|
244934
|
+
htmlContent,
|
|
244935
|
+
importMapScript,
|
|
244936
|
+
jsCode: codeWithoutImports,
|
|
244937
|
+
importStatements,
|
|
244938
|
+
parentBindings: true,
|
|
244939
|
+
autoCallTjsFunction: true
|
|
244621
244940
|
});
|
|
244622
|
-
|
|
244623
|
-
|
|
244624
|
-
|
|
244625
|
-
|
|
244626
|
-
|
|
244627
|
-
|
|
244628
|
-
// If result is a DOM node, append it; otherwise log it
|
|
244629
|
-
if (result instanceof Node) {
|
|
244630
|
-
document.body.append(result);
|
|
244631
|
-
parent.postMessage({ type: 'hasPreviewContent' }, '*');
|
|
244632
|
-
} else {
|
|
244633
|
-
console.log('Result:', result);
|
|
244634
|
-
}
|
|
244635
|
-
}
|
|
244636
|
-
} else {
|
|
244637
|
-
// No TJS function found, report total parse/exec time
|
|
244638
|
-
const __execTime = performance.now() - __execStart;
|
|
244639
|
-
parent.postMessage({ type: 'timing', execTime: __execTime }, '*');
|
|
244640
|
-
}
|
|
244641
|
-
// Check if body has content after execution
|
|
244642
|
-
if (document.body.children.length > 0) {
|
|
244643
|
-
parent.postMessage({ type: 'hasPreviewContent' }, '*');
|
|
244644
|
-
}
|
|
244645
|
-
} catch (e) {
|
|
244646
|
-
parent.postMessage({ type: 'error', message: e.message }, '*');
|
|
244647
|
-
}
|
|
244648
|
-
</script>
|
|
244649
|
-
</body>
|
|
244650
|
-
</html>`;
|
|
244651
|
-
const messageHandler = (event) => {
|
|
244652
|
-
if (event.data?.type === "console") {
|
|
244653
|
-
this.log(event.data.message);
|
|
244654
|
-
} else if (event.data?.type === "timing") {
|
|
244655
|
-
const execTime = event.data.execTime;
|
|
244656
|
-
const execStr = execTime < 1 ? `${(execTime * 1000).toFixed(0)}μs` : `${execTime.toFixed(2)}ms`;
|
|
244657
|
-
this.parts.consoleHeader.textContent = `Console — executed in ${execStr}`;
|
|
244658
|
-
} else if (event.data?.type === "hasPreviewContent") {
|
|
244941
|
+
const messageHandler = createIframeMessageHandler({
|
|
244942
|
+
onConsole: (message) => this.log(message),
|
|
244943
|
+
onTiming: (execTime) => {
|
|
244944
|
+
this.parts.consoleHeader.textContent = `Console — executed in ${formatExecTime(execTime)}`;
|
|
244945
|
+
},
|
|
244946
|
+
onPreviewContent: () => {
|
|
244659
244947
|
this.parts.outputTabs.value = 1;
|
|
244660
|
-
}
|
|
244661
|
-
|
|
244948
|
+
},
|
|
244949
|
+
onError: (message) => {
|
|
244950
|
+
this.log(`Error: ${message}`);
|
|
244662
244951
|
this.parts.statusBar.textContent = "Runtime error";
|
|
244663
244952
|
this.parts.statusBar.classList.add("error");
|
|
244664
244953
|
}
|
|
244665
|
-
};
|
|
244954
|
+
});
|
|
244666
244955
|
window.addEventListener("message", messageHandler);
|
|
244667
244956
|
const iframe = this.parts.previewFrame;
|
|
244668
244957
|
const blob = new Blob([iframeDoc], { type: "text/html" });
|
|
@@ -244729,15 +245018,7 @@ class TJSPlayground extends g {
|
|
|
244729
245018
|
var tjsPlayground = TJSPlayground.elementCreator({
|
|
244730
245019
|
tag: "tjs-playground",
|
|
244731
245020
|
styleSpec: {
|
|
244732
|
-
|
|
244733
|
-
display: "flex",
|
|
244734
|
-
flexDirection: "column",
|
|
244735
|
-
height: "100%",
|
|
244736
|
-
flex: "1 1 auto",
|
|
244737
|
-
background: "var(--background, #fff)",
|
|
244738
|
-
color: "var(--text-color, #1f2937)",
|
|
244739
|
-
fontFamily: "system-ui, sans-serif"
|
|
244740
|
-
},
|
|
245021
|
+
...sharedPlaygroundStyles,
|
|
244741
245022
|
":host .tjs-toolbar": {
|
|
244742
245023
|
display: "flex",
|
|
244743
245024
|
alignItems: "center",
|
|
@@ -244746,53 +245027,6 @@ var tjsPlayground = TJSPlayground.elementCreator({
|
|
|
244746
245027
|
background: "var(--code-background, #f3f4f6)",
|
|
244747
245028
|
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
244748
245029
|
},
|
|
244749
|
-
":host .run-btn": {
|
|
244750
|
-
display: "flex",
|
|
244751
|
-
alignItems: "center",
|
|
244752
|
-
gap: "4px",
|
|
244753
|
-
padding: "6px 12px",
|
|
244754
|
-
background: "var(--brand-color, #3d4a6b)",
|
|
244755
|
-
color: "var(--brand-text-color, white)",
|
|
244756
|
-
border: "none",
|
|
244757
|
-
borderRadius: "6px",
|
|
244758
|
-
cursor: "pointer",
|
|
244759
|
-
fontWeight: "500",
|
|
244760
|
-
fontSize: "14px"
|
|
244761
|
-
},
|
|
244762
|
-
":host .run-btn:hover:not(:disabled)": {
|
|
244763
|
-
filter: "brightness(1.1)"
|
|
244764
|
-
},
|
|
244765
|
-
":host .run-btn:disabled": {
|
|
244766
|
-
opacity: "0.6",
|
|
244767
|
-
cursor: "not-allowed"
|
|
244768
|
-
},
|
|
244769
|
-
":host .toolbar-separator": {
|
|
244770
|
-
width: "1px",
|
|
244771
|
-
height: "20px",
|
|
244772
|
-
background: "var(--code-border, #d1d5db)"
|
|
244773
|
-
},
|
|
244774
|
-
":host .build-flags": {
|
|
244775
|
-
display: "flex",
|
|
244776
|
-
alignItems: "center",
|
|
244777
|
-
gap: "12px"
|
|
244778
|
-
},
|
|
244779
|
-
":host .flag-label": {
|
|
244780
|
-
display: "flex",
|
|
244781
|
-
alignItems: "center",
|
|
244782
|
-
gap: "4px",
|
|
244783
|
-
fontSize: "13px",
|
|
244784
|
-
color: "var(--text-color, #6b7280)",
|
|
244785
|
-
cursor: "pointer",
|
|
244786
|
-
userSelect: "none"
|
|
244787
|
-
},
|
|
244788
|
-
":host .flag-label:hover": {
|
|
244789
|
-
color: "var(--text-color, #374151)"
|
|
244790
|
-
},
|
|
244791
|
-
':host .flag-label input[type="checkbox"]': {
|
|
244792
|
-
margin: "0",
|
|
244793
|
-
cursor: "pointer",
|
|
244794
|
-
accentColor: "var(--brand-color, #3d4a6b)"
|
|
244795
|
-
},
|
|
244796
245030
|
":host .module-name-input": {
|
|
244797
245031
|
padding: "6px 10px",
|
|
244798
245032
|
border: "1px solid var(--code-border, #d1d5db)",
|
|
@@ -244830,40 +245064,6 @@ var tjsPlayground = TJSPlayground.elementCreator({
|
|
|
244830
245064
|
color: "var(--brand-text-color, white)",
|
|
244831
245065
|
borderColor: "var(--brand-color, #3d4a6b)"
|
|
244832
245066
|
},
|
|
244833
|
-
":host .revert-btn": {
|
|
244834
|
-
display: "flex",
|
|
244835
|
-
alignItems: "center",
|
|
244836
|
-
gap: "4px",
|
|
244837
|
-
padding: "6px 12px",
|
|
244838
|
-
background: "var(--code-background, #e5e7eb)",
|
|
244839
|
-
color: "var(--text-color, #374151)",
|
|
244840
|
-
border: "1px solid var(--code-border, #d1d5db)",
|
|
244841
|
-
borderRadius: "6px",
|
|
244842
|
-
cursor: "pointer",
|
|
244843
|
-
fontWeight: "500",
|
|
244844
|
-
fontSize: "14px",
|
|
244845
|
-
transition: "opacity 0.2s"
|
|
244846
|
-
},
|
|
244847
|
-
":host .revert-btn:hover:not(:disabled)": {
|
|
244848
|
-
background: "#fef3c7",
|
|
244849
|
-
borderColor: "#f59e0b",
|
|
244850
|
-
color: "#92400e"
|
|
244851
|
-
},
|
|
244852
|
-
":host .revert-btn:disabled": {
|
|
244853
|
-
cursor: "default"
|
|
244854
|
-
},
|
|
244855
|
-
":host .elastic": {
|
|
244856
|
-
flex: "1"
|
|
244857
|
-
},
|
|
244858
|
-
":host .status-bar": {
|
|
244859
|
-
fontSize: "13px",
|
|
244860
|
-
color: "var(--text-color, #6b7280)",
|
|
244861
|
-
opacity: "0.7"
|
|
244862
|
-
},
|
|
244863
|
-
":host .status-bar.error": {
|
|
244864
|
-
color: "#dc2626",
|
|
244865
|
-
opacity: "1"
|
|
244866
|
-
},
|
|
244867
245067
|
":host .tjs-main": {
|
|
244868
245068
|
display: "flex",
|
|
244869
245069
|
flex: "1 1 auto",
|
|
@@ -244879,25 +245079,6 @@ var tjsPlayground = TJSPlayground.elementCreator({
|
|
|
244879
245079
|
background: "var(--background, #fff)",
|
|
244880
245080
|
overflow: "hidden"
|
|
244881
245081
|
},
|
|
244882
|
-
":host tosi-tabs > [name]": {
|
|
244883
|
-
background: "var(--background, #fff)",
|
|
244884
|
-
color: "var(--text-color, #1f2937)"
|
|
244885
|
-
},
|
|
244886
|
-
":host .editor-wrapper": {
|
|
244887
|
-
flex: "1 1 auto",
|
|
244888
|
-
height: "100%",
|
|
244889
|
-
minHeight: "300px",
|
|
244890
|
-
position: "relative",
|
|
244891
|
-
overflow: "hidden"
|
|
244892
|
-
},
|
|
244893
|
-
":host .editor-wrapper code-mirror": {
|
|
244894
|
-
display: "block",
|
|
244895
|
-
position: "absolute",
|
|
244896
|
-
top: "0",
|
|
244897
|
-
left: "0",
|
|
244898
|
-
right: "0",
|
|
244899
|
-
bottom: "0"
|
|
244900
|
-
},
|
|
244901
245082
|
":host .js-output": {
|
|
244902
245083
|
margin: "0",
|
|
244903
245084
|
padding: "12px",
|
|
@@ -244909,151 +245090,11 @@ var tjsPlayground = TJSPlayground.elementCreator({
|
|
|
244909
245090
|
height: "100%",
|
|
244910
245091
|
whiteSpace: "pre-wrap"
|
|
244911
245092
|
},
|
|
244912
|
-
":host .preview-frame": {
|
|
244913
|
-
width: "100%",
|
|
244914
|
-
height: "100%",
|
|
244915
|
-
border: "none",
|
|
244916
|
-
background: "var(--background, #fff)"
|
|
244917
|
-
},
|
|
244918
|
-
":host .docs-output": {
|
|
244919
|
-
display: "block",
|
|
244920
|
-
padding: "12px 16px",
|
|
244921
|
-
fontSize: "14px",
|
|
244922
|
-
fontFamily: "system-ui, sans-serif",
|
|
244923
|
-
color: "var(--text-color, inherit)",
|
|
244924
|
-
background: "var(--background, #fff)",
|
|
244925
|
-
height: "100%",
|
|
244926
|
-
overflow: "auto"
|
|
244927
|
-
},
|
|
244928
|
-
":host .docs-output h2": {
|
|
244929
|
-
fontSize: "1.25em",
|
|
244930
|
-
marginTop: "0",
|
|
244931
|
-
marginBottom: "0.5em",
|
|
244932
|
-
color: "var(--text-color, #1f2937)"
|
|
244933
|
-
},
|
|
244934
|
-
":host .docs-output pre": {
|
|
244935
|
-
background: "var(--code-background, #f3f4f6)",
|
|
244936
|
-
padding: "8px 12px",
|
|
244937
|
-
borderRadius: "6px",
|
|
244938
|
-
overflow: "auto",
|
|
244939
|
-
fontSize: "13px"
|
|
244940
|
-
},
|
|
244941
|
-
":host .docs-output code": {
|
|
244942
|
-
fontFamily: "ui-monospace, monospace",
|
|
244943
|
-
fontSize: "0.9em"
|
|
244944
|
-
},
|
|
244945
|
-
":host .docs-output p": {
|
|
244946
|
-
margin: "0.75em 0",
|
|
244947
|
-
lineHeight: "1.5"
|
|
244948
|
-
},
|
|
244949
|
-
":host .docs-output h3": {
|
|
244950
|
-
fontSize: "1em",
|
|
244951
|
-
marginTop: "1em",
|
|
244952
|
-
marginBottom: "0.5em"
|
|
244953
|
-
},
|
|
244954
|
-
":host .docs-output ul": {
|
|
244955
|
-
paddingLeft: "1.5em",
|
|
244956
|
-
margin: "0.5em 0"
|
|
244957
|
-
},
|
|
244958
|
-
":host .docs-output li": {
|
|
244959
|
-
marginBottom: "0.25em"
|
|
244960
|
-
},
|
|
244961
|
-
":host .docs-output hr": {
|
|
244962
|
-
border: "none",
|
|
244963
|
-
borderTop: "1px solid var(--code-border, #e5e7eb)",
|
|
244964
|
-
margin: "1.5em 0"
|
|
244965
|
-
},
|
|
244966
|
-
":host .tests-output": {
|
|
244967
|
-
padding: "12px",
|
|
244968
|
-
fontSize: "14px",
|
|
244969
|
-
fontFamily: "system-ui, sans-serif",
|
|
244970
|
-
color: "var(--text-color, inherit)",
|
|
244971
|
-
background: "var(--background, #fff)",
|
|
244972
|
-
height: "100%",
|
|
244973
|
-
overflow: "auto"
|
|
244974
|
-
},
|
|
244975
|
-
":host .test-summary": {
|
|
244976
|
-
marginBottom: "12px",
|
|
244977
|
-
paddingBottom: "8px",
|
|
244978
|
-
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
244979
|
-
},
|
|
244980
|
-
":host .test-failed": {
|
|
244981
|
-
color: "#dc2626"
|
|
244982
|
-
},
|
|
244983
|
-
":host .test-list": {
|
|
244984
|
-
listStyle: "none",
|
|
244985
|
-
padding: 0,
|
|
244986
|
-
margin: 0
|
|
244987
|
-
},
|
|
244988
|
-
":host .test-list li": {
|
|
244989
|
-
padding: "4px 0"
|
|
244990
|
-
},
|
|
244991
|
-
":host .test-pass": {
|
|
244992
|
-
color: "#16a34a"
|
|
244993
|
-
},
|
|
244994
|
-
":host .test-fail": {
|
|
244995
|
-
color: "#dc2626"
|
|
244996
|
-
},
|
|
244997
|
-
":host .test-error": {
|
|
244998
|
-
marginLeft: "20px",
|
|
244999
|
-
marginTop: "4px",
|
|
245000
|
-
padding: "8px",
|
|
245001
|
-
background: "rgba(220, 38, 38, 0.1)",
|
|
245002
|
-
borderRadius: "4px",
|
|
245003
|
-
fontSize: "13px",
|
|
245004
|
-
fontFamily: "var(--font-mono, monospace)"
|
|
245005
|
-
},
|
|
245006
|
-
":host .clickable-error": {
|
|
245007
|
-
cursor: "pointer",
|
|
245008
|
-
textDecoration: "underline",
|
|
245009
|
-
textDecorationStyle: "dotted"
|
|
245010
|
-
},
|
|
245011
|
-
":host .clickable-error:hover": {
|
|
245012
|
-
background: "rgba(220, 38, 38, 0.2)"
|
|
245013
|
-
},
|
|
245014
|
-
":host .sig-badge": {
|
|
245015
|
-
fontSize: "11px",
|
|
245016
|
-
padding: "2px 6px",
|
|
245017
|
-
marginLeft: "8px",
|
|
245018
|
-
background: "rgba(99, 102, 241, 0.1)",
|
|
245019
|
-
color: "#6366f1",
|
|
245020
|
-
borderRadius: "4px"
|
|
245021
|
-
},
|
|
245022
245093
|
":host .tjs-console": {
|
|
245023
245094
|
height: "120px",
|
|
245024
245095
|
borderTop: "1px solid var(--code-border, #e5e7eb)",
|
|
245025
245096
|
display: "flex",
|
|
245026
245097
|
flexDirection: "column"
|
|
245027
|
-
},
|
|
245028
|
-
":host .console-header": {
|
|
245029
|
-
padding: "4px 12px",
|
|
245030
|
-
background: "var(--code-background, #f3f4f6)",
|
|
245031
|
-
fontSize: "12px",
|
|
245032
|
-
fontWeight: "500",
|
|
245033
|
-
color: "var(--text-color, #6b7280)",
|
|
245034
|
-
opacity: "0.7",
|
|
245035
|
-
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
245036
|
-
},
|
|
245037
|
-
":host .console-output": {
|
|
245038
|
-
flex: "1",
|
|
245039
|
-
margin: "0",
|
|
245040
|
-
padding: "8px 12px",
|
|
245041
|
-
background: "var(--code-background, #f3f4f6)",
|
|
245042
|
-
color: "var(--text-color, #1f2937)",
|
|
245043
|
-
fontSize: "12px",
|
|
245044
|
-
fontFamily: "ui-monospace, monospace",
|
|
245045
|
-
overflow: "auto",
|
|
245046
|
-
whiteSpace: "pre-wrap"
|
|
245047
|
-
},
|
|
245048
|
-
":host .clickable-line": {
|
|
245049
|
-
cursor: "pointer",
|
|
245050
|
-
color: "#2563eb",
|
|
245051
|
-
textDecoration: "underline",
|
|
245052
|
-
textDecorationStyle: "dotted"
|
|
245053
|
-
},
|
|
245054
|
-
":host .clickable-line:hover": {
|
|
245055
|
-
color: "#1d4ed8",
|
|
245056
|
-
background: "rgba(37, 99, 235, 0.1)"
|
|
245057
245098
|
}
|
|
245058
245099
|
}
|
|
245059
245100
|
});
|
|
@@ -245174,28 +245215,7 @@ class TSPlayground extends g {
|
|
|
245174
245215
|
this.parts.consoleHeader.textContent = "Console";
|
|
245175
245216
|
};
|
|
245176
245217
|
renderConsole() {
|
|
245177
|
-
|
|
245178
|
-
const html2 = this.consoleMessages.map((msg) => {
|
|
245179
|
-
const escaped = msg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
245180
|
-
return escaped.replace(linePattern, (match, l1, c12, l22, c22) => {
|
|
245181
|
-
const line = l1 || l22;
|
|
245182
|
-
const col = c12 || c22 || "1";
|
|
245183
|
-
return `<span class="clickable-line" data-line="${line}" data-col="${col}">${match}</span>`;
|
|
245184
|
-
});
|
|
245185
|
-
}).join(`
|
|
245186
|
-
`);
|
|
245187
|
-
this.parts.console.innerHTML = html2;
|
|
245188
|
-
this.parts.console.scrollTop = this.parts.console.scrollHeight;
|
|
245189
|
-
this.parts.console.querySelectorAll(".clickable-line").forEach((el2) => {
|
|
245190
|
-
el2.addEventListener("click", (e) => {
|
|
245191
|
-
const target = e.currentTarget;
|
|
245192
|
-
const line = parseInt(target.dataset.line || "0", 10);
|
|
245193
|
-
const col = parseInt(target.dataset.col || "1", 10);
|
|
245194
|
-
if (line > 0) {
|
|
245195
|
-
this.goToSourceLine(line, col);
|
|
245196
|
-
}
|
|
245197
|
-
});
|
|
245198
|
-
});
|
|
245218
|
+
renderConsoleMessages(this.consoleMessages, this.parts.console, (line, col) => this.goToSourceLine(line, col));
|
|
245199
245219
|
}
|
|
245200
245220
|
goToSourceLine(line, column = 1) {
|
|
245201
245221
|
this.parts.inputTabs.value = 0;
|
|
@@ -245251,8 +245271,7 @@ class TSPlayground extends g {
|
|
|
245251
245271
|
this.parts.jsOutput.textContent = jsResult.code;
|
|
245252
245272
|
this.updateTestResults(jsResult.testResults || []);
|
|
245253
245273
|
this.updateDocs(jsResult);
|
|
245254
|
-
|
|
245255
|
-
this.parts.statusBar.textContent = `TS→TJS ${formatTime2(this.lastTsToTjsTime)} + TJS→JS ${formatTime2(this.lastTjsToJsTime)} = ${formatTime2(this.lastTranspileTime)}`;
|
|
245274
|
+
this.parts.statusBar.textContent = `TS→TJS ${formatExecTime(this.lastTsToTjsTime)} + TJS→JS ${formatExecTime(this.lastTjsToJsTime)} = ${formatExecTime(this.lastTranspileTime)}`;
|
|
245256
245275
|
this.parts.statusBar.classList.remove("error");
|
|
245257
245276
|
} catch (jsError) {
|
|
245258
245277
|
this.parts.jsOutput.textContent = `// TJS -> JS Error:
|
|
@@ -245291,50 +245310,7 @@ class TSPlayground extends g {
|
|
|
245291
245310
|
`);
|
|
245292
245311
|
}
|
|
245293
245312
|
updateTestResults(tests) {
|
|
245294
|
-
|
|
245295
|
-
this.parts.testsOutput.textContent = "No tests defined";
|
|
245296
|
-
this.parts.tsEditor.clearMarkers();
|
|
245297
|
-
return;
|
|
245298
|
-
}
|
|
245299
|
-
const passed = tests.filter((t2) => t2.passed).length;
|
|
245300
|
-
const failed = tests.filter((t2) => !t2.passed).length;
|
|
245301
|
-
const failedTests = tests.filter((t2) => !t2.passed && t2.line);
|
|
245302
|
-
if (failedTests.length > 0) {
|
|
245303
|
-
this.parts.tsEditor.setMarkers(failedTests.map((t2) => ({
|
|
245304
|
-
line: t2.line,
|
|
245305
|
-
message: t2.error || t2.description,
|
|
245306
|
-
severity: "error"
|
|
245307
|
-
})));
|
|
245308
|
-
} else {
|
|
245309
|
-
this.parts.tsEditor.clearMarkers();
|
|
245310
|
-
}
|
|
245311
|
-
let html2 = `<div class="test-summary">`;
|
|
245312
|
-
html2 += `<strong>${passed} passed</strong>`;
|
|
245313
|
-
if (failed > 0) {
|
|
245314
|
-
html2 += `, <strong class="test-failed">${failed} failed</strong>`;
|
|
245315
|
-
}
|
|
245316
|
-
html2 += `</div><ul class="test-list">`;
|
|
245317
|
-
for (const test of tests) {
|
|
245318
|
-
const icon = test.passed ? "✓" : "✗";
|
|
245319
|
-
const cls = test.passed ? "test-pass" : "test-fail";
|
|
245320
|
-
const sigBadge = test.isSignatureTest ? ' <span class="sig-badge">signature</span>' : "";
|
|
245321
|
-
const dataLine = test.line ? ` data-line="${test.line}"` : "";
|
|
245322
|
-
html2 += `<li class="${cls}"${dataLine}>${icon} ${test.description}${sigBadge}`;
|
|
245323
|
-
if (!test.passed && test.error) {
|
|
245324
|
-
html2 += `<div class="test-error${test.line ? " clickable-error" : ""}"${dataLine}>${test.error}</div>`;
|
|
245325
|
-
}
|
|
245326
|
-
html2 += `</li>`;
|
|
245327
|
-
}
|
|
245328
|
-
html2 += `</ul>`;
|
|
245329
|
-
this.parts.testsOutput.innerHTML = html2;
|
|
245330
|
-
this.parts.testsOutput.querySelectorAll(".clickable-error").forEach((el2) => {
|
|
245331
|
-
el2.addEventListener("click", (e) => {
|
|
245332
|
-
const line = parseInt(e.currentTarget.dataset.line || "0", 10);
|
|
245333
|
-
if (line > 0) {
|
|
245334
|
-
this.goToSourceLine(line);
|
|
245335
|
-
}
|
|
245336
|
-
});
|
|
245337
|
-
});
|
|
245313
|
+
renderTestResults(tests, this.parts.testsOutput, this.parts.tsEditor, (line) => this.goToSourceLine(line));
|
|
245338
245314
|
}
|
|
245339
245315
|
updateDocs(result) {
|
|
245340
245316
|
const source = this.parts.tsEditor.value;
|
|
@@ -245363,6 +245339,7 @@ class TSPlayground extends g {
|
|
|
245363
245339
|
this.log("Cannot run - transpilation failed");
|
|
245364
245340
|
return;
|
|
245365
245341
|
}
|
|
245342
|
+
this.parts.outputTabs.value = 1;
|
|
245366
245343
|
this.parts.statusBar.textContent = "Running...";
|
|
245367
245344
|
try {
|
|
245368
245345
|
const htmlContent = this.parts.htmlEditor.value;
|
|
@@ -245382,81 +245359,26 @@ class TSPlayground extends g {
|
|
|
245382
245359
|
importMapScript = `<script type="importmap">${JSON.stringify(importMap)}</script>`;
|
|
245383
245360
|
}
|
|
245384
245361
|
}
|
|
245385
|
-
const iframeDoc =
|
|
245386
|
-
|
|
245387
|
-
|
|
245388
|
-
|
|
245389
|
-
|
|
245390
|
-
|
|
245391
|
-
|
|
245392
|
-
|
|
245393
|
-
|
|
245394
|
-
|
|
245395
|
-
|
|
245396
|
-
|
|
245397
|
-
|
|
245398
|
-
|
|
245399
|
-
|
|
245400
|
-
|
|
245401
|
-
const actual = value === null ? 'null' : typeof value;
|
|
245402
|
-
const err = new Error(\`Expected \${expected} for '\${path}', got \${actual}\`);
|
|
245403
|
-
err.name = 'MonadicError';
|
|
245404
|
-
err.path = path;
|
|
245405
|
-
err.expected = expected;
|
|
245406
|
-
err.actual = actual;
|
|
245407
|
-
return err;
|
|
245408
|
-
},
|
|
245409
|
-
createRuntime: function() { return this; },
|
|
245410
|
-
Is: (a, b) => {
|
|
245411
|
-
if (a === b) return true;
|
|
245412
|
-
if (a === null || b === null) return a === b;
|
|
245413
|
-
if (typeof a !== typeof b) return false;
|
|
245414
|
-
if (typeof a !== 'object') return false;
|
|
245415
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
245416
|
-
if (a.length !== b.length) return false;
|
|
245417
|
-
return a.every((v, i) => globalThis.__tjs.Is(v, b[i]));
|
|
245418
|
-
}
|
|
245419
|
-
const keysA = Object.keys(a);
|
|
245420
|
-
const keysB = Object.keys(b);
|
|
245421
|
-
if (keysA.length !== keysB.length) return false;
|
|
245422
|
-
return keysA.every(k => globalThis.__tjs.Is(a[k], b[k]));
|
|
245423
|
-
},
|
|
245424
|
-
IsNot: (a, b) => !globalThis.__tjs.Is(a, b),
|
|
245425
|
-
};
|
|
245426
|
-
|
|
245427
|
-
// Capture console.log
|
|
245428
|
-
const _log = console.log;
|
|
245429
|
-
console.log = (...args) => {
|
|
245430
|
-
_log(...args);
|
|
245431
|
-
parent.postMessage({ type: 'console', message: args.map(a =>
|
|
245432
|
-
typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a)
|
|
245433
|
-
).join(' ') }, '*');
|
|
245434
|
-
};
|
|
245435
|
-
|
|
245436
|
-
try {
|
|
245437
|
-
const __execStart = performance.now();
|
|
245438
|
-
${jsCode}
|
|
245439
|
-
const __execTime = performance.now() - __execStart;
|
|
245440
|
-
parent.postMessage({ type: 'timing', execTime: __execTime }, '*');
|
|
245441
|
-
} catch (e) {
|
|
245442
|
-
parent.postMessage({ type: 'error', message: e.message }, '*');
|
|
245443
|
-
}
|
|
245444
|
-
</script>
|
|
245445
|
-
</body>
|
|
245446
|
-
</html>`;
|
|
245447
|
-
const messageHandler = (event) => {
|
|
245448
|
-
if (event.data?.type === "console") {
|
|
245449
|
-
this.log(event.data.message);
|
|
245450
|
-
} else if (event.data?.type === "timing") {
|
|
245451
|
-
const execTime = event.data.execTime;
|
|
245452
|
-
const execStr = execTime < 1 ? `${(execTime * 1000).toFixed(0)}μs` : `${execTime.toFixed(2)}ms`;
|
|
245453
|
-
this.parts.consoleHeader.textContent = `Console — executed in ${execStr}`;
|
|
245454
|
-
} else if (event.data?.type === "error") {
|
|
245455
|
-
this.log(`Error: ${event.data.message}`);
|
|
245362
|
+
const iframeDoc = buildIframeDoc({
|
|
245363
|
+
cssContent,
|
|
245364
|
+
htmlContent,
|
|
245365
|
+
importMapScript,
|
|
245366
|
+
jsCode
|
|
245367
|
+
});
|
|
245368
|
+
const messageHandler = createIframeMessageHandler({
|
|
245369
|
+
onConsole: (message) => this.log(message),
|
|
245370
|
+
onTiming: (execTime) => {
|
|
245371
|
+
this.parts.consoleHeader.textContent = `Console — executed in ${formatExecTime(execTime)}`;
|
|
245372
|
+
},
|
|
245373
|
+
onPreviewContent: () => {
|
|
245374
|
+
this.parts.outputTabs.value = 2;
|
|
245375
|
+
},
|
|
245376
|
+
onError: (message) => {
|
|
245377
|
+
this.log(`Error: ${message}`);
|
|
245456
245378
|
this.parts.statusBar.textContent = "Runtime error";
|
|
245457
245379
|
this.parts.statusBar.classList.add("error");
|
|
245458
245380
|
}
|
|
245459
|
-
};
|
|
245381
|
+
});
|
|
245460
245382
|
window.addEventListener("message", messageHandler);
|
|
245461
245383
|
this.parts.previewFrame.srcdoc = iframeDoc;
|
|
245462
245384
|
setTimeout(() => {
|
|
@@ -245497,15 +245419,7 @@ class TSPlayground extends g {
|
|
|
245497
245419
|
var tsPlayground = TSPlayground.elementCreator({
|
|
245498
245420
|
tag: "ts-playground",
|
|
245499
245421
|
styleSpec: {
|
|
245500
|
-
|
|
245501
|
-
display: "flex",
|
|
245502
|
-
flexDirection: "column",
|
|
245503
|
-
height: "100%",
|
|
245504
|
-
flex: "1 1 auto",
|
|
245505
|
-
background: "var(--background, #fff)",
|
|
245506
|
-
color: "var(--text-color, #1f2937)",
|
|
245507
|
-
fontFamily: "system-ui, sans-serif"
|
|
245508
|
-
},
|
|
245422
|
+
...sharedPlaygroundStyles,
|
|
245509
245423
|
":host .ts-toolbar": {
|
|
245510
245424
|
display: "flex",
|
|
245511
245425
|
alignItems: "center",
|
|
@@ -245514,83 +245428,11 @@ var tsPlayground = TSPlayground.elementCreator({
|
|
|
245514
245428
|
background: "var(--code-background, #f3f4f6)",
|
|
245515
245429
|
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
245516
245430
|
},
|
|
245517
|
-
":host .run-btn": {
|
|
245518
|
-
display: "flex",
|
|
245519
|
-
alignItems: "center",
|
|
245520
|
-
gap: "4px",
|
|
245521
|
-
padding: "6px 12px",
|
|
245522
|
-
background: "var(--brand-color, #3178c6)",
|
|
245523
|
-
color: "var(--brand-text-color, white)",
|
|
245524
|
-
border: "none",
|
|
245525
|
-
borderRadius: "6px",
|
|
245526
|
-
cursor: "pointer",
|
|
245527
|
-
fontWeight: "500",
|
|
245528
|
-
fontSize: "14px"
|
|
245529
|
-
},
|
|
245530
|
-
":host .run-btn:hover": {
|
|
245531
|
-
filter: "brightness(1.1)"
|
|
245532
|
-
},
|
|
245533
|
-
":host .toolbar-separator": {
|
|
245534
|
-
width: "1px",
|
|
245535
|
-
height: "20px",
|
|
245536
|
-
background: "var(--code-border, #d1d5db)"
|
|
245537
|
-
},
|
|
245538
|
-
":host .build-flags": {
|
|
245539
|
-
display: "flex",
|
|
245540
|
-
alignItems: "center",
|
|
245541
|
-
gap: "12px"
|
|
245542
|
-
},
|
|
245543
|
-
":host .flag-label": {
|
|
245544
|
-
display: "flex",
|
|
245545
|
-
alignItems: "center",
|
|
245546
|
-
gap: "4px",
|
|
245547
|
-
fontSize: "13px",
|
|
245548
|
-
color: "var(--text-color, #6b7280)",
|
|
245549
|
-
cursor: "pointer",
|
|
245550
|
-
userSelect: "none"
|
|
245551
|
-
},
|
|
245552
|
-
":host .flag-label:hover": {
|
|
245553
|
-
color: "var(--text-color, #374151)"
|
|
245554
|
-
},
|
|
245555
245431
|
':host .flag-label input[type="checkbox"]': {
|
|
245556
245432
|
margin: "0",
|
|
245557
245433
|
cursor: "pointer",
|
|
245558
245434
|
accentColor: "var(--brand-color, #3178c6)"
|
|
245559
245435
|
},
|
|
245560
|
-
":host .revert-btn": {
|
|
245561
|
-
display: "flex",
|
|
245562
|
-
alignItems: "center",
|
|
245563
|
-
gap: "4px",
|
|
245564
|
-
padding: "6px 12px",
|
|
245565
|
-
background: "var(--code-background, #e5e7eb)",
|
|
245566
|
-
color: "var(--text-color, #374151)",
|
|
245567
|
-
border: "1px solid var(--code-border, #d1d5db)",
|
|
245568
|
-
borderRadius: "6px",
|
|
245569
|
-
cursor: "pointer",
|
|
245570
|
-
fontWeight: "500",
|
|
245571
|
-
fontSize: "14px",
|
|
245572
|
-
transition: "opacity 0.2s"
|
|
245573
|
-
},
|
|
245574
|
-
":host .revert-btn:hover:not(:disabled)": {
|
|
245575
|
-
background: "#fef3c7",
|
|
245576
|
-
borderColor: "#f59e0b",
|
|
245577
|
-
color: "#92400e"
|
|
245578
|
-
},
|
|
245579
|
-
":host .revert-btn:disabled": {
|
|
245580
|
-
cursor: "default"
|
|
245581
|
-
},
|
|
245582
|
-
":host .elastic": {
|
|
245583
|
-
flex: "1"
|
|
245584
|
-
},
|
|
245585
|
-
":host .status-bar": {
|
|
245586
|
-
fontSize: "13px",
|
|
245587
|
-
color: "var(--text-color, #6b7280)",
|
|
245588
|
-
opacity: "0.7"
|
|
245589
|
-
},
|
|
245590
|
-
":host .status-bar.error": {
|
|
245591
|
-
color: "#dc2626",
|
|
245592
|
-
opacity: "1"
|
|
245593
|
-
},
|
|
245594
245436
|
":host .ts-main": {
|
|
245595
245437
|
display: "flex",
|
|
245596
245438
|
flex: "1 1 auto",
|
|
@@ -245613,25 +245455,6 @@ var tsPlayground = TSPlayground.elementCreator({
|
|
|
245613
245455
|
minHeight: "0",
|
|
245614
245456
|
height: "100%"
|
|
245615
245457
|
},
|
|
245616
|
-
":host tosi-tabs > [name]": {
|
|
245617
|
-
background: "var(--background, #fff)",
|
|
245618
|
-
color: "var(--text-color, #1f2937)"
|
|
245619
|
-
},
|
|
245620
|
-
":host .editor-wrapper": {
|
|
245621
|
-
flex: "1 1 auto",
|
|
245622
|
-
height: "100%",
|
|
245623
|
-
minHeight: "300px",
|
|
245624
|
-
position: "relative",
|
|
245625
|
-
overflow: "hidden"
|
|
245626
|
-
},
|
|
245627
|
-
":host .editor-wrapper code-mirror": {
|
|
245628
|
-
display: "block",
|
|
245629
|
-
position: "absolute",
|
|
245630
|
-
top: "0",
|
|
245631
|
-
left: "0",
|
|
245632
|
-
right: "0",
|
|
245633
|
-
bottom: "0"
|
|
245634
|
-
},
|
|
245635
245458
|
":host .output-toolbar": {
|
|
245636
245459
|
display: "flex",
|
|
245637
245460
|
gap: "8px",
|
|
@@ -245669,112 +245492,11 @@ var tsPlayground = TSPlayground.elementCreator({
|
|
|
245669
245492
|
height: "100%",
|
|
245670
245493
|
background: "var(--background, #fff)"
|
|
245671
245494
|
},
|
|
245672
|
-
":host .preview-frame": {
|
|
245673
|
-
width: "100%",
|
|
245674
|
-
height: "100%",
|
|
245675
|
-
border: "none"
|
|
245676
|
-
},
|
|
245677
|
-
":host .docs-output": {
|
|
245678
|
-
display: "block",
|
|
245679
|
-
padding: "12px 16px",
|
|
245680
|
-
fontSize: "14px",
|
|
245681
|
-
fontFamily: "system-ui, sans-serif",
|
|
245682
|
-
color: "var(--text-color, inherit)",
|
|
245683
|
-
background: "var(--background, #fff)",
|
|
245684
|
-
height: "100%",
|
|
245685
|
-
overflow: "auto"
|
|
245686
|
-
},
|
|
245687
|
-
":host .tests-output": {
|
|
245688
|
-
padding: "12px",
|
|
245689
|
-
fontSize: "14px",
|
|
245690
|
-
fontFamily: "system-ui, sans-serif",
|
|
245691
|
-
color: "var(--text-color, inherit)",
|
|
245692
|
-
background: "var(--background, #fff)",
|
|
245693
|
-
height: "100%",
|
|
245694
|
-
overflow: "auto"
|
|
245695
|
-
},
|
|
245696
|
-
":host .test-summary": {
|
|
245697
|
-
marginBottom: "12px",
|
|
245698
|
-
paddingBottom: "8px",
|
|
245699
|
-
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
245700
|
-
},
|
|
245701
|
-
":host .test-failed": {
|
|
245702
|
-
color: "#dc2626"
|
|
245703
|
-
},
|
|
245704
|
-
":host .test-list": {
|
|
245705
|
-
listStyle: "none",
|
|
245706
|
-
padding: 0,
|
|
245707
|
-
margin: 0
|
|
245708
|
-
},
|
|
245709
|
-
":host .test-list li": {
|
|
245710
|
-
padding: "4px 0"
|
|
245711
|
-
},
|
|
245712
|
-
":host .test-pass": {
|
|
245713
|
-
color: "#16a34a"
|
|
245714
|
-
},
|
|
245715
|
-
":host .test-fail": {
|
|
245716
|
-
color: "#dc2626"
|
|
245717
|
-
},
|
|
245718
|
-
":host .test-error": {
|
|
245719
|
-
marginLeft: "20px",
|
|
245720
|
-
marginTop: "4px",
|
|
245721
|
-
padding: "8px",
|
|
245722
|
-
background: "rgba(220, 38, 38, 0.1)",
|
|
245723
|
-
borderRadius: "4px",
|
|
245724
|
-
fontSize: "13px",
|
|
245725
|
-
fontFamily: "var(--font-mono, monospace)"
|
|
245726
|
-
},
|
|
245727
|
-
":host .clickable-error": {
|
|
245728
|
-
cursor: "pointer",
|
|
245729
|
-
textDecoration: "underline",
|
|
245730
|
-
textDecorationStyle: "dotted"
|
|
245731
|
-
},
|
|
245732
|
-
":host .clickable-error:hover": {
|
|
245733
|
-
background: "rgba(220, 38, 38, 0.2)"
|
|
245734
|
-
},
|
|
245735
|
-
":host .sig-badge": {
|
|
245736
|
-
fontSize: "11px",
|
|
245737
|
-
padding: "2px 6px",
|
|
245738
|
-
marginLeft: "8px",
|
|
245739
|
-
background: "rgba(99, 102, 241, 0.1)",
|
|
245740
|
-
color: "#6366f1",
|
|
245741
|
-
borderRadius: "4px"
|
|
245742
|
-
},
|
|
245743
245495
|
":host .ts-console": {
|
|
245744
245496
|
height: "120px",
|
|
245745
245497
|
borderTop: "1px solid var(--code-border, #e5e7eb)",
|
|
245746
245498
|
display: "flex",
|
|
245747
245499
|
flexDirection: "column"
|
|
245748
|
-
},
|
|
245749
|
-
":host .console-header": {
|
|
245750
|
-
padding: "4px 12px",
|
|
245751
|
-
background: "var(--code-background, #f3f4f6)",
|
|
245752
|
-
fontSize: "12px",
|
|
245753
|
-
fontWeight: "500",
|
|
245754
|
-
color: "var(--text-color, #6b7280)",
|
|
245755
|
-
opacity: "0.7",
|
|
245756
|
-
borderBottom: "1px solid var(--code-border, #e5e7eb)"
|
|
245757
|
-
},
|
|
245758
|
-
":host .console-output": {
|
|
245759
|
-
flex: "1",
|
|
245760
|
-
margin: "0",
|
|
245761
|
-
padding: "8px 12px",
|
|
245762
|
-
background: "var(--code-background, #f3f4f6)",
|
|
245763
|
-
color: "var(--text-color, #1f2937)",
|
|
245764
|
-
fontSize: "12px",
|
|
245765
|
-
fontFamily: "ui-monospace, monospace",
|
|
245766
|
-
overflow: "auto",
|
|
245767
|
-
whiteSpace: "pre-wrap"
|
|
245768
|
-
},
|
|
245769
|
-
":host .clickable-line": {
|
|
245770
|
-
cursor: "pointer",
|
|
245771
|
-
color: "#2563eb",
|
|
245772
|
-
textDecoration: "underline",
|
|
245773
|
-
textDecorationStyle: "dotted"
|
|
245774
|
-
},
|
|
245775
|
-
":host .clickable-line:hover": {
|
|
245776
|
-
color: "#1d4ed8",
|
|
245777
|
-
background: "rgba(37, 99, 235, 0.1)"
|
|
245778
245500
|
}
|
|
245779
245501
|
}
|
|
245780
245502
|
});
|
|
@@ -246135,25 +245857,26 @@ main()
|
|
|
246135
245857
|
description: "Classes are supported with metadata",
|
|
246136
245858
|
group: "advanced",
|
|
246137
245859
|
code: `// Classes with typed methods
|
|
245860
|
+
// Note: return types omitted on methods — TJS infers them
|
|
246138
245861
|
|
|
246139
245862
|
class Calculator {
|
|
246140
245863
|
private value: number = 0
|
|
246141
245864
|
|
|
246142
|
-
add(n: number)
|
|
245865
|
+
add(n: number) {
|
|
246143
245866
|
this.value += n
|
|
246144
245867
|
return this
|
|
246145
245868
|
}
|
|
246146
245869
|
|
|
246147
|
-
multiply(n: number)
|
|
245870
|
+
multiply(n: number) {
|
|
246148
245871
|
this.value *= n
|
|
246149
245872
|
return this
|
|
246150
245873
|
}
|
|
246151
245874
|
|
|
246152
|
-
getResult()
|
|
245875
|
+
getResult() {
|
|
246153
245876
|
return this.value
|
|
246154
245877
|
}
|
|
246155
245878
|
|
|
246156
|
-
reset()
|
|
245879
|
+
reset() {
|
|
246157
245880
|
this.value = 0
|
|
246158
245881
|
}
|
|
246159
245882
|
}
|
|
@@ -266724,11 +266447,10 @@ main()`,
|
|
|
266724
266447
|
const todos = new Map()
|
|
266725
266448
|
let nextId = 1
|
|
266726
266449
|
|
|
266727
|
-
// Types
|
|
266728
|
-
|
|
266729
|
-
|
|
266730
|
-
|
|
266731
|
-
type FilterInput = { completed: true } | { completed: false } | {}
|
|
266450
|
+
// Types are inferred from function signatures below
|
|
266451
|
+
// Todo: { id: 0, title: '', completed: false, createdAt: '' }
|
|
266452
|
+
// CreateInput: { title: 'Buy milk' }
|
|
266453
|
+
// UpdateInput: { id: 1, title: 'Buy milk', completed: false }
|
|
266732
266454
|
|
|
266733
266455
|
// POST /todos - Create
|
|
266734
266456
|
export function createTodo(input: { title: 'New todo' })
|
|
@@ -267059,7 +266781,9 @@ function createEvent(input: {
|
|
|
267059
266781
|
title: input.title,
|
|
267060
266782
|
start: format(start, 'yyyy-MM-dd'),
|
|
267061
266783
|
end: format(end, 'yyyy-MM-dd'),
|
|
267062
|
-
formatted:
|
|
266784
|
+
formatted: \`\${input.title}: \${format(start, 'MMM d')} - \${format(end, 'MMM d, yyyy')}\`
|
|
266785
|
+
}
|
|
266786
|
+
}`,
|
|
267063
266787
|
language: "tjs",
|
|
267064
266788
|
description: "Uses date-fns for date formatting via ESM import"
|
|
267065
266789
|
},
|
|
@@ -267081,7 +266805,34 @@ You can import from modules saved in the playground!
|
|
|
267081
266805
|
2. Import it by name from another file
|
|
267082
266806
|
|
|
267083
266807
|
## Try it:
|
|
267084
|
-
1. First, create and save a module named "mymath"
|
|
266808
|
+
1. First, create and save a module named "mymath":
|
|
266809
|
+
|
|
266810
|
+
export function add(a: 0, b: 0) -> 0 {
|
|
266811
|
+
return a + b
|
|
266812
|
+
}
|
|
266813
|
+
|
|
266814
|
+
export function multiply(a: 0, b: 0) -> 0 {
|
|
266815
|
+
return a * b
|
|
266816
|
+
}
|
|
266817
|
+
|
|
266818
|
+
2. Then run this code (it imports from your saved module)
|
|
266819
|
+
*/
|
|
266820
|
+
|
|
266821
|
+
// This imports from a module you saved in the playground
|
|
266822
|
+
// Change 'mymath' to match whatever name you used when saving
|
|
266823
|
+
import { add, multiply } from 'mymath'
|
|
266824
|
+
|
|
266825
|
+
function calculate(x: 0, y: 0) -> 0 {
|
|
266826
|
+
// (x + y) * 2
|
|
266827
|
+
return multiply(add(x, y), 2)
|
|
266828
|
+
}
|
|
266829
|
+
|
|
266830
|
+
test 'calculate combines add and multiply' {
|
|
266831
|
+
expect(calculate(3, 4)).toBe(14) // (3 + 4) * 2 = 14
|
|
266832
|
+
}
|
|
266833
|
+
|
|
266834
|
+
console.log('calculate(3, 4) =', calculate(3, 4))
|
|
266835
|
+
console.log('calculate(10, 5) =', calculate(10, 5))`,
|
|
267085
266836
|
language: "tjs",
|
|
267086
266837
|
description: "Import from modules you save in the playground"
|
|
267087
266838
|
},
|
|
@@ -267313,22 +267064,31 @@ document.body.append(
|
|
|
267313
267064
|
requiresApi: true,
|
|
267314
267065
|
code: `function mathAssistant({ question = 'What is 23 * 47 + 156?' }) {
|
|
267315
267066
|
// First, ask LLM to extract the calculation
|
|
267316
|
-
let extractPrompt =
|
|
267317
|
-
|
|
267067
|
+
let extractPrompt =
|
|
267068
|
+
'Extract the math expression from this question. Return ONLY the expression, nothing else.\\nQuestion: ' +
|
|
267069
|
+
question
|
|
267318
267070
|
let expression = llmPredict({ prompt: extractPrompt })
|
|
267319
267071
|
|
|
267320
267072
|
// Evaluate the expression (simple eval simulation)
|
|
267321
|
-
let calcPrompt =
|
|
267322
|
-
|
|
267073
|
+
let calcPrompt =
|
|
267074
|
+
'Calculate: ' + expression + '\\nReturn ONLY the numeric result.'
|
|
267323
267075
|
let calcResult = llmPredict({ prompt: calcPrompt })
|
|
267324
267076
|
|
|
267325
267077
|
// Format the answer
|
|
267326
|
-
let answerPrompt =
|
|
267327
|
-
The
|
|
267328
|
-
|
|
267078
|
+
let answerPrompt =
|
|
267079
|
+
'The user asked: "' +
|
|
267080
|
+
question +
|
|
267081
|
+
'"\\nThe calculated result is: ' +
|
|
267082
|
+
calcResult +
|
|
267083
|
+
'\\nWrite a brief, friendly response with the answer.'
|
|
267329
267084
|
let answer = llmPredict({ prompt: answerPrompt })
|
|
267330
267085
|
|
|
267331
|
-
return {
|
|
267086
|
+
return {
|
|
267087
|
+
question,
|
|
267088
|
+
expression: expression.trim(),
|
|
267089
|
+
result: calcResult.trim(),
|
|
267090
|
+
answer,
|
|
267091
|
+
}
|
|
267332
267092
|
}`,
|
|
267333
267093
|
language: "javascript",
|
|
267334
267094
|
description: "LLM uses a calculator tool (requires llm capability)"
|
|
@@ -267344,33 +267104,33 @@ Write a brief, friendly response with the answer.\\\`
|
|
|
267344
267104
|
requiresApi: true,
|
|
267345
267105
|
code: `function collaborativeWriting({ topic = 'the future of renewable energy' }) {
|
|
267346
267106
|
// Agent 1: Research Agent - generates key points
|
|
267347
|
-
let researchPrompt =
|
|
267348
|
-
|
|
267107
|
+
let researchPrompt =
|
|
267108
|
+
'You are a research agent. Generate 3 key facts or points about: ' +
|
|
267109
|
+
topic +
|
|
267110
|
+
'\\nFormat as a numbered list. Be concise.'
|
|
267349
267111
|
let research = llmPredict({ prompt: researchPrompt })
|
|
267350
267112
|
|
|
267351
267113
|
// Agent 2: Writer Agent - creates content from research
|
|
267352
|
-
let writerPrompt =
|
|
267353
|
-
|
|
267354
|
-
|
|
267355
|
-
|
|
267356
|
-
|
|
267357
|
-
|
|
267114
|
+
let writerPrompt =
|
|
267115
|
+
'You are a writer agent. Using these research points:\\n\\n' +
|
|
267116
|
+
research +
|
|
267117
|
+
'\\n\\nWrite a short, engaging paragraph (2-3 sentences) about ' +
|
|
267118
|
+
topic +
|
|
267119
|
+
'.\\nMake it informative and accessible.'
|
|
267358
267120
|
let article = llmPredict({ prompt: writerPrompt })
|
|
267359
267121
|
|
|
267360
267122
|
// Agent 3: Editor Agent - reviews and improves
|
|
267361
|
-
let editorPrompt =
|
|
267362
|
-
|
|
267363
|
-
|
|
267364
|
-
|
|
267365
|
-
Suggest one specific improvement. Then provide the improved version.
|
|
267366
|
-
Format: "Suggestion: [your suggestion]\\\\n\\\\nImproved: [improved text]"\\\`
|
|
267123
|
+
let editorPrompt =
|
|
267124
|
+
'You are an editor agent. Review this draft:\\n\\n"' +
|
|
267125
|
+
article +
|
|
267126
|
+
'"\\n\\nSuggest one specific improvement. Then provide the improved version.\\nFormat: "Suggestion: [your suggestion]\\n\\nImproved: [improved text]"'
|
|
267367
267127
|
let edited = llmPredict({ prompt: editorPrompt })
|
|
267368
267128
|
|
|
267369
267129
|
return {
|
|
267370
267130
|
topic,
|
|
267371
267131
|
researchPoints: research,
|
|
267372
267132
|
firstDraft: article,
|
|
267373
|
-
editedVersion: edited
|
|
267133
|
+
editedVersion: edited,
|
|
267374
267134
|
}
|
|
267375
267135
|
}`,
|
|
267376
267136
|
language: "javascript",
|
|
@@ -267454,65 +267214,17 @@ Format: "Suggestion: [your suggestion]\\\\n\\\\nImproved: [improved text]"\\\`
|
|
|
267454
267214
|
requiresApi: true,
|
|
267455
267215
|
code: `function solveWithCode({ problem = 'Calculate the 10th Fibonacci number' }) {
|
|
267456
267216
|
// System prompt with AsyncJS rules and example
|
|
267457
|
-
let systemContext =
|
|
267217
|
+
let systemContext =
|
|
267218
|
+
'You write AsyncJS code. AsyncJS is a JavaScript subset.\\n\\nRULES:\\n- NO: async, await, new, class, this, var, for loops\\n- Use let for variables, while for loops\\n- Return an object: return { result }\\n\\nEXAMPLE (factorial):\\nfunction solve() {\\n let result = 1\\n let i = 5\\n while (i > 1) {\\n result = result * i\\n i = i - 1\\n }\\n return { result }\\n}\\n\\nReturn ONLY the function code, nothing else.'
|
|
267458
267219
|
|
|
267459
|
-
|
|
267460
|
-
|
|
267461
|
-
- Use let for variables, while for loops
|
|
267462
|
-
- Return an object: return { result }
|
|
267463
|
-
|
|
267464
|
-
EXAMPLE (factorial):
|
|
267465
|
-
function solve() {
|
|
267466
|
-
let result = 1
|
|
267467
|
-
let i = 5
|
|
267468
|
-
while (i > 1) {
|
|
267469
|
-
result = result * i
|
|
267470
|
-
i = i - 1
|
|
267471
|
-
}
|
|
267472
|
-
return { result }
|
|
267473
|
-
}
|
|
267474
|
-
|
|
267475
|
-
Return ONLY the function code, nothing else.\\\`
|
|
267476
|
-
|
|
267477
|
-
let prompt = \\\`\\\${systemContext}
|
|
267478
|
-
|
|
267479
|
-
Write a function called "solve" that: \\\${problem}\\\`
|
|
267220
|
+
let prompt =
|
|
267221
|
+
systemContext + '\\n\\nWrite a function called "solve" that: ' + problem
|
|
267480
267222
|
|
|
267481
267223
|
let response = llmPredict({ prompt })
|
|
267482
267224
|
|
|
267483
267225
|
// Clean up code - remove markdown fences, fix escapes, extract function
|
|
267484
267226
|
let code = response
|
|
267485
|
-
code = code.replace(
|
|
267486
|
-
code = code.replace(/\\\\n?\\\`\\\`\\\`/g, '')
|
|
267487
|
-
code = code.replace(/\\\\\\\\n/g, '\\\\n')
|
|
267488
|
-
code = code.replace(/\\\\\\\\t/g, '\\\\t')
|
|
267489
|
-
code = code.replace(/\\\\\\\\"/g, '"')
|
|
267490
|
-
code = code.trim()
|
|
267491
|
-
|
|
267492
|
-
// Try to extract just the function if there's extra text
|
|
267493
|
-
let funcMatch = code.match(/function\\\\s+solve\\\\s*\\\\([^)]*\\\\)\\\\s*\\\\{[\\\\s\\\\S]*\\\\}/)
|
|
267494
|
-
if (funcMatch) {
|
|
267495
|
-
code = funcMatch[0]
|
|
267496
|
-
}
|
|
267497
|
-
|
|
267498
|
-
// Validate it looks like a function before running
|
|
267499
|
-
if (!code.startsWith('function')) {
|
|
267500
|
-
return {
|
|
267501
|
-
problem,
|
|
267502
|
-
error: 'LLM did not generate valid code',
|
|
267503
|
-
rawResponse: response
|
|
267504
|
-
}
|
|
267505
|
-
}
|
|
267506
|
-
|
|
267507
|
-
// Execute the generated code
|
|
267508
|
-
let output = runCode({ code, args: {} })
|
|
267509
|
-
|
|
267510
|
-
return {
|
|
267511
|
-
problem,
|
|
267512
|
-
generatedCode: code,
|
|
267513
|
-
result: output.result
|
|
267514
|
-
}
|
|
267515
|
-
}`,
|
|
267227
|
+
code = code.replace(/`,
|
|
267516
267228
|
language: "javascript",
|
|
267517
267229
|
description: "LLM writes and runs code to solve a problem (requires llm capability)"
|
|
267518
267230
|
},
|
|
@@ -267527,53 +267239,26 @@ Write a function called "solve" that: \\\${problem}\\\`
|
|
|
267527
267239
|
requiresApi: true,
|
|
267528
267240
|
code: `function generateCode({ task = 'Calculate the factorial of n' }) {
|
|
267529
267241
|
// System prompt with AsyncJS rules and complete example
|
|
267530
|
-
let systemContext =
|
|
267531
|
-
|
|
267532
|
-
RULES:
|
|
267533
|
-
- Types by example: fn(n: 5) means required number param with example value 5
|
|
267534
|
-
- NO: async, await, new, class, this, var, for, generator functions (function*)
|
|
267535
|
-
- Use let for variables, while for loops
|
|
267536
|
-
- Return an object: return { result }
|
|
267537
|
-
|
|
267538
|
-
EXAMPLE - calculating sum of 1 to n:
|
|
267539
|
-
function sumTo(n: 10) {
|
|
267540
|
-
let sum = 0
|
|
267541
|
-
let i = 1
|
|
267542
|
-
while (i <= n) {
|
|
267543
|
-
sum = sum + i
|
|
267544
|
-
i = i + 1
|
|
267545
|
-
}
|
|
267546
|
-
return { result: sum }
|
|
267547
|
-
}\\\`
|
|
267242
|
+
let systemContext =
|
|
267243
|
+
'You write AsyncJS code. AsyncJS is a subset of JavaScript.\\n\\nRULES:\\n- Types by example: fn(n: 5) means required number param with example value 5\\n- NO: async, await, new, class, this, var, for, generator functions (function*)\\n- Use let for variables, while for loops\\n- Return an object: return { result }\\n\\nEXAMPLE - calculating sum of 1 to n:\\nfunction sumTo(n: 10) {\\n let sum = 0\\n let i = 1\\n while (i <= n) {\\n sum = sum + i\\n i = i + 1\\n }\\n return { result: sum }\\n}'
|
|
267548
267244
|
|
|
267549
267245
|
let schema = Schema.response('generated_code', {
|
|
267550
267246
|
code: '',
|
|
267551
|
-
description: ''
|
|
267247
|
+
description: '',
|
|
267552
267248
|
})
|
|
267553
267249
|
|
|
267554
|
-
let prompt =
|
|
267555
|
-
|
|
267556
|
-
|
|
267557
|
-
|
|
267558
|
-
|
|
267250
|
+
let prompt =
|
|
267251
|
+
systemContext +
|
|
267252
|
+
'\\n\\nWrite an AsyncJS function for: ' +
|
|
267253
|
+
task +
|
|
267254
|
+
'\\n\\nReturn ONLY valid AsyncJS code in the code field. Must start with "function" and use while loops (not for loops).'
|
|
267559
267255
|
|
|
267560
267256
|
let response = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
267561
267257
|
let result = JSON.parse(response)
|
|
267562
267258
|
|
|
267563
267259
|
// Clean up any markdown fences and fix escaped newlines
|
|
267564
267260
|
let code = result.code
|
|
267565
|
-
code = code.replace(
|
|
267566
|
-
code = code.replace(/\\\\n?\\\`\\\`\\\`/g, '')
|
|
267567
|
-
code = code.replace(/\\\\\\\\n/g, '\\\\n')
|
|
267568
|
-
code = code.replace(/\\\\\\\\t/g, '\\\\t')
|
|
267569
|
-
code = code.trim()
|
|
267570
|
-
|
|
267571
|
-
return {
|
|
267572
|
-
task,
|
|
267573
|
-
code,
|
|
267574
|
-
description: result.description
|
|
267575
|
-
}
|
|
267576
|
-
}`,
|
|
267261
|
+
code = code.replace(/`,
|
|
267577
267262
|
language: "javascript",
|
|
267578
267263
|
description: "LLM writes AsyncJS code from a description (requires llm capability)"
|
|
267579
267264
|
},
|
|
@@ -267586,7 +267271,12 @@ Return ONLY valid AsyncJS code in the code field. Must start with "function" and
|
|
|
267586
267271
|
group: "api",
|
|
267587
267272
|
order: 7,
|
|
267588
267273
|
code: `function getWeather({ lat = 37.7749, lon = -122.4194 }) {
|
|
267589
|
-
let url =
|
|
267274
|
+
let url =
|
|
267275
|
+
'https://api.open-meteo.com/v1/forecast?latitude=' +
|
|
267276
|
+
lat +
|
|
267277
|
+
'&longitude=' +
|
|
267278
|
+
lon +
|
|
267279
|
+
'¤t_weather=true'
|
|
267590
267280
|
let response = httpFetch({ url, cache: 1800 })
|
|
267591
267281
|
let weather = response.current_weather
|
|
267592
267282
|
return { weather }
|
|
@@ -267603,12 +267293,17 @@ Return ONLY valid AsyncJS code in the code field. Must start with "function" and
|
|
|
267603
267293
|
group: "api",
|
|
267604
267294
|
order: 8,
|
|
267605
267295
|
code: `function searchMusic({ query = 'Beatles', limit = 5 }) {
|
|
267606
|
-
let url =
|
|
267296
|
+
let url =
|
|
267297
|
+
'https://itunes.apple.com/search?term=' +
|
|
267298
|
+
query +
|
|
267299
|
+
'&limit=' +
|
|
267300
|
+
limit +
|
|
267301
|
+
'&media=music'
|
|
267607
267302
|
let response = httpFetch({ url, cache: 3600 })
|
|
267608
|
-
let tracks = response.results.map(x => ({
|
|
267303
|
+
let tracks = response.results.map((x) => ({
|
|
267609
267304
|
artist: x.artistName,
|
|
267610
267305
|
track: x.trackName,
|
|
267611
|
-
album: x.collectionName
|
|
267306
|
+
album: x.collectionName,
|
|
267612
267307
|
}))
|
|
267613
267308
|
return { tracks }
|
|
267614
267309
|
}`,
|
|
@@ -267624,12 +267319,17 @@ Return ONLY valid AsyncJS code in the code field. Must start with "function" and
|
|
|
267624
267319
|
group: "api",
|
|
267625
267320
|
order: 9,
|
|
267626
267321
|
code: `function searchRepos({ query = 'tosijs', perPage = 5 }) {
|
|
267627
|
-
let url =
|
|
267322
|
+
let url =
|
|
267323
|
+
'https://api.github.com/search/repositories?q=' +
|
|
267324
|
+
query +
|
|
267325
|
+
'&per_page=' +
|
|
267326
|
+
perPage +
|
|
267327
|
+
'&sort=stars'
|
|
267628
267328
|
let response = httpFetch({ url, cache: 300 })
|
|
267629
|
-
let repos = response.items.map(x => ({
|
|
267329
|
+
let repos = response.items.map((x) => ({
|
|
267630
267330
|
name: x.full_name,
|
|
267631
267331
|
stars: x.stargazers_count,
|
|
267632
|
-
description: x.description
|
|
267332
|
+
description: x.description,
|
|
267633
267333
|
}))
|
|
267634
267334
|
return { repos }
|
|
267635
267335
|
}`,
|
|
@@ -269033,24 +268733,33 @@ This minimal dependency approach reduces supply chain risk and bundle size.
|
|
|
269033
268733
|
code: `function findCovers({ song = 'Yesterday', artist = 'Beatles' }) {
|
|
269034
268734
|
// Search iTunes for the song
|
|
269035
268735
|
let query = song + ' ' + artist
|
|
269036
|
-
let url =
|
|
268736
|
+
let url =
|
|
268737
|
+
'https://itunes.apple.com/search?term=' + query + '&limit=25&media=music'
|
|
269037
268738
|
let response = httpFetch({ url, cache: 3600 })
|
|
269038
268739
|
|
|
269039
268740
|
// Format results for LLM analysis
|
|
269040
268741
|
let results = response.results || []
|
|
269041
|
-
let tracks = results.map(
|
|
269042
|
-
|
|
268742
|
+
let tracks = results.map(
|
|
268743
|
+
(x) =>
|
|
268744
|
+
'"' + x.trackName + '" by ' + x.artistName + ' (' + x.collectionName + ')'
|
|
268745
|
+
)
|
|
268746
|
+
let trackList = tracks.join('\\n')
|
|
269043
268747
|
|
|
269044
268748
|
// Schema.response from example - much cleaner!
|
|
269045
268749
|
let schema = Schema.response('cover_versions', {
|
|
269046
|
-
covers: [{ track: '', artist: '', album: '' }]
|
|
268750
|
+
covers: [{ track: '', artist: '', album: '' }],
|
|
269047
268751
|
})
|
|
269048
268752
|
|
|
269049
|
-
let prompt =
|
|
269050
|
-
|
|
269051
|
-
|
|
269052
|
-
|
|
269053
|
-
|
|
268753
|
+
let prompt =
|
|
268754
|
+
'Search results for "' +
|
|
268755
|
+
song +
|
|
268756
|
+
'" by ' +
|
|
268757
|
+
artist +
|
|
268758
|
+
':\\n\\n' +
|
|
268759
|
+
trackList +
|
|
268760
|
+
'\\n\\nList cover versions (tracks NOT by ' +
|
|
268761
|
+
artist +
|
|
268762
|
+
').'
|
|
269054
268763
|
|
|
269055
268764
|
let llmResponse = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
269056
268765
|
let parsed = JSON.parse(llmResponse)
|
|
@@ -269109,10 +268818,10 @@ List cover versions (tracks NOT by \\\${artist}).\\\`
|
|
|
269109
268818
|
code: `function summarize({ source = 'coffee-origins' }) {
|
|
269110
268819
|
// Fetch text from our sample documents
|
|
269111
268820
|
// Options: 'coffee-origins', 'ai-history', 'renewable-energy'
|
|
269112
|
-
let url =
|
|
268821
|
+
let url = '/texts/' + source + '.txt'
|
|
269113
268822
|
let text = httpFetch({ url })
|
|
269114
268823
|
|
|
269115
|
-
let prompt =
|
|
268824
|
+
let prompt = 'Summarize the following text in 2-3 sentences:\\n\\n' + text
|
|
269116
268825
|
let summary = llmPredict({ prompt })
|
|
269117
268826
|
return { source, summary }
|
|
269118
268827
|
}`,
|
|
@@ -269128,17 +268837,19 @@ List cover versions (tracks NOT by \\\${artist}).\\\`
|
|
|
269128
268837
|
group: "llm",
|
|
269129
268838
|
order: 12,
|
|
269130
268839
|
requiresApi: true,
|
|
269131
|
-
code: `function extractInfo({
|
|
268840
|
+
code: `function extractInfo({
|
|
268841
|
+
text = 'John Smith is a 35-year-old software engineer from San Francisco who loves hiking and photography.',
|
|
268842
|
+
}) {
|
|
269132
268843
|
// Schema.response builds responseFormat from an example
|
|
269133
268844
|
let schema = Schema.response('person_info', {
|
|
269134
268845
|
name: '',
|
|
269135
268846
|
age: 0,
|
|
269136
268847
|
occupation: '',
|
|
269137
268848
|
location: '',
|
|
269138
|
-
hobbies: ['']
|
|
268849
|
+
hobbies: [''],
|
|
269139
268850
|
})
|
|
269140
268851
|
|
|
269141
|
-
let prompt =
|
|
268852
|
+
let prompt = 'Extract person info from this text: ' + text
|
|
269142
268853
|
let response = llmPredict({ prompt, options: { responseFormat: schema } })
|
|
269143
268854
|
let person = JSON.parse(response)
|
|
269144
268855
|
return { person }
|
|
@@ -271270,7 +270981,7 @@ The transpiler generates code like:
|
|
|
271270
270981
|
* )
|
|
271271
270982
|
*/
|
|
271272
270983
|
const add = await (async () => {
|
|
271273
|
-
const bytes = Uint8Array.from(atob('AGFzbQEAAAA...'), c => c.charCodeAt(0))
|
|
270984
|
+
const bytes = Uint8Array.from(atob('AGFzbQEAAAA...'), (c) => c.charCodeAt(0))
|
|
271274
270985
|
const { instance } = await WebAssembly.instantiate(bytes)
|
|
271275
270986
|
return instance.exports.fn
|
|
271276
270987
|
})()
|
|
@@ -271510,6 +271221,25 @@ Comment inside function`,
|
|
|
271510
271221
|
filename: "from-ts.test.ts",
|
|
271511
271222
|
path: "src/lang/from-ts.test.ts"
|
|
271512
271223
|
},
|
|
271224
|
+
{
|
|
271225
|
+
title: "icebox",
|
|
271226
|
+
filename: "tasks-f6d70f.md",
|
|
271227
|
+
path: ".haltija/tasks-f6d70f.md",
|
|
271228
|
+
text: `# icebox
|
|
271229
|
+
|
|
271230
|
+
# queued
|
|
271231
|
+
|
|
271232
|
+
# in_progress
|
|
271233
|
+
|
|
271234
|
+
# blocked
|
|
271235
|
+
|
|
271236
|
+
# review
|
|
271237
|
+
|
|
271238
|
+
# done
|
|
271239
|
+
|
|
271240
|
+
# trash
|
|
271241
|
+
`
|
|
271242
|
+
},
|
|
271513
271243
|
{
|
|
271514
271244
|
text: `# TJS Platform Cloud Functions
|
|
271515
271245
|
|
|
@@ -275179,4 +274909,4 @@ if (main) {
|
|
|
275179
274909
|
}
|
|
275180
274910
|
console.log(`%c tjs-lang %c v${VERSION} `, "background: #6366f1; color: white; padding: 2px 6px; border-radius: 3px 0 0 3px;", "background: #374151; color: white; padding: 2px 6px; border-radius: 0 3px 3px 0;");
|
|
275181
274911
|
|
|
275182
|
-
//# debugId=
|
|
274912
|
+
//# debugId=9B23A9B33C90485E64756E2164756E21
|