repl-sdk 0.0.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/tar-worker-kdkltuRC.js +598 -0
- package/dist/assets/tar-worker-kdkltuRC.js.map +1 -0
- package/dist/codemirror-D4aIVflZ.js +110 -0
- package/dist/codemirror-D4aIVflZ.js.map +1 -0
- package/dist/gjs-CzFzkEFv.js +173 -0
- package/dist/gjs-CzFzkEFv.js.map +1 -0
- package/dist/gmd-D9OXs2v3.js +166 -0
- package/dist/gmd-D9OXs2v3.js.map +1 -0
- package/dist/hbs-CuhWjffM.js +62 -0
- package/dist/hbs-CuhWjffM.js.map +1 -0
- package/dist/index-CUWCqMoD.js +2133 -0
- package/dist/index-CUWCqMoD.js.map +1 -0
- package/dist/index.js +4 -104
- package/dist/index.js.map +1 -1
- package/dist/parse-aBKk9rfS.js +328 -0
- package/dist/parse-aBKk9rfS.js.map +1 -0
- package/dist/render-app-island-B-i8rvGi.js +61 -0
- package/dist/render-app-island-B-i8rvGi.js.map +1 -0
- package/package.json +82 -9
- package/src/cache.js +138 -0
- package/src/cdn.js +93 -0
- package/src/codemirror.js +161 -0
- package/src/compilers/ember/gjs.js +212 -0
- package/src/compilers/ember/gmd.js +190 -0
- package/src/compilers/ember/hbs.js +98 -0
- package/src/compilers/ember/render-app-island.js +83 -0
- package/src/compilers/ember.js +166 -0
- package/src/compilers/js.js +32 -0
- package/src/compilers/markdown/build-compiler.js +151 -0
- package/src/compilers/markdown/const.js +2 -0
- package/src/compilers/markdown/heading-id.js +75 -0
- package/src/compilers/markdown/live-code-extraction.js +198 -0
- package/src/compilers/markdown/parse.js +22 -0
- package/src/compilers/markdown/parse.test.ts +363 -0
- package/src/compilers/markdown/sanitize-for-glimmer.js +26 -0
- package/src/compilers/markdown/types.ts +21 -0
- package/src/compilers/markdown/utils.js +78 -0
- package/src/compilers/markdown.js +125 -0
- package/src/compilers/mermaid.js +35 -0
- package/src/compilers/react.js +47 -0
- package/src/compilers/svelte.js +116 -0
- package/src/compilers/vue.js +58 -0
- package/src/compilers.js +108 -0
- package/src/es-module-shim.js +53 -0
- package/src/index.d.ts +53 -4
- package/src/index.js +744 -89
- package/src/npm.js +58 -0
- package/src/request.Request.test.ts +59 -0
- package/src/request.js +140 -0
- package/src/resolve.fromImports.test.ts +35 -0
- package/src/resolve.fromInternalImport.test.ts +69 -0
- package/src/resolve.js +352 -0
- package/src/resolve.resolvePath.test.ts +24 -0
- package/src/resolve.test.ts +23 -0
- package/src/specifier.js +71 -0
- package/src/specifier.test.ts +90 -0
- package/src/tar-worker.js +61 -0
- package/src/tar.js +76 -0
- package/src/types.ts +335 -58
- package/src/utils.js +28 -1
- package/declarations/index.d.ts +0 -73
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('unified').Plugin} Plugin
|
|
3
|
+
*/
|
|
4
|
+
import { assert, isRecord } from '../../utils.js';
|
|
5
|
+
import { buildCodeFenceMetaUtils } from '../markdown/utils.js';
|
|
6
|
+
import { renderApp } from './render-app-island.js';
|
|
7
|
+
|
|
8
|
+
let elementId = 0;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {unknown} [ options ]
|
|
12
|
+
* @returns {{
|
|
13
|
+
* scope: Record<string, unknown>,
|
|
14
|
+
* remarkPlugins: Plugin[],
|
|
15
|
+
* rehypePlugins: Plugin[],
|
|
16
|
+
* ShadowComponent: string | undefined,
|
|
17
|
+
* CopyComponent: string | undefined
|
|
18
|
+
* }}
|
|
19
|
+
*/
|
|
20
|
+
export function filterOptions(options) {
|
|
21
|
+
if (!isRecord(options)) {
|
|
22
|
+
return {
|
|
23
|
+
scope: {},
|
|
24
|
+
remarkPlugins: [],
|
|
25
|
+
rehypePlugins: [],
|
|
26
|
+
ShadowComponent: undefined,
|
|
27
|
+
CopyComponent: undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
scope: /** @type {Record<string, unknown>}*/ (options?.scope || {}),
|
|
33
|
+
remarkPlugins: /** @type {Plugin[]}*/ (options?.remarkPlugins || []),
|
|
34
|
+
rehypePlugins: /** @type {Plugin[]}*/ (options?.rehypePlugins || []),
|
|
35
|
+
ShadowComponent: /** @type {string}*/ (options?.ShadowComponent),
|
|
36
|
+
CopyComponent: /** @type {string}*/ (options?.CopyComponent),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @type {import('../../types.ts').CompilerConfig['compiler']}
|
|
42
|
+
*/
|
|
43
|
+
export async function compiler(config, api) {
|
|
44
|
+
const userOptions = filterOptions(
|
|
45
|
+
/** @type {Record<string, unknown>} */ (config.userOptions)?.gmd || config
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const { isLive, isPreview, needsLive, allowedFormats, getFlavorFromMeta, isBelow } =
|
|
49
|
+
buildCodeFenceMetaUtils(api);
|
|
50
|
+
|
|
51
|
+
const { parseMarkdown } = await import(/* @vite-ignore */ '../markdown/parse.js');
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @type {import('../../types.ts').Compiler}
|
|
55
|
+
*/
|
|
56
|
+
const gmdCompiler = {
|
|
57
|
+
compile: async (text, options) => {
|
|
58
|
+
const compileOptions = filterOptions(options);
|
|
59
|
+
const result = await parseMarkdown(text, {
|
|
60
|
+
remarkPlugins: [...userOptions.remarkPlugins, ...compileOptions.remarkPlugins],
|
|
61
|
+
rehypePlugins: [...userOptions.rehypePlugins, ...compileOptions.rehypePlugins],
|
|
62
|
+
isLive,
|
|
63
|
+
isPreview,
|
|
64
|
+
isBelow,
|
|
65
|
+
needsLive,
|
|
66
|
+
ALLOWED_FORMATS: allowedFormats,
|
|
67
|
+
getFlavorFromMeta,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const { template } = await api.tryResolve('@ember/template-compiler/runtime');
|
|
71
|
+
|
|
72
|
+
const scope = {
|
|
73
|
+
...filterOptions(userOptions).scope,
|
|
74
|
+
...filterOptions(options).scope,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const component = template(result.text, {
|
|
78
|
+
scope: () => ({
|
|
79
|
+
...scope,
|
|
80
|
+
// TODO: compile all the components from "result" and add them to scope here
|
|
81
|
+
// would this be better than the markdown style multiple islands
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return { compiled: component, ...result, scope };
|
|
86
|
+
},
|
|
87
|
+
render: async (element, compiled, extra, compiler) => {
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* TODO: These will make things easier:
|
|
91
|
+
* https://github.com/emberjs/rfcs/pull/1099
|
|
92
|
+
* https://github.com/ember-cli/ember-addon-blueprint/blob/main/files/tests/test-helper.js
|
|
93
|
+
*/
|
|
94
|
+
const attribute = `data-repl-sdk-ember-gmd-${elementId++}`;
|
|
95
|
+
|
|
96
|
+
element.setAttribute(attribute, '');
|
|
97
|
+
|
|
98
|
+
const [application, destroyable, resolver, router, route, testWaiters, runloop] =
|
|
99
|
+
await compiler.tryResolveAll([
|
|
100
|
+
'@ember/application',
|
|
101
|
+
'@ember/destroyable',
|
|
102
|
+
'ember-resolver',
|
|
103
|
+
'@ember/routing/router',
|
|
104
|
+
'@ember/routing/route',
|
|
105
|
+
'@ember/test-waiters',
|
|
106
|
+
'@ember/runloop',
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
// We don't want to await here, because we need to early
|
|
110
|
+
// return the element so that the app can render in to it.
|
|
111
|
+
// (Ember will only render in to an element if it's present in the DOM)
|
|
112
|
+
const destroy = await renderApp({
|
|
113
|
+
element,
|
|
114
|
+
selector: `[${attribute}]`,
|
|
115
|
+
component: compiled,
|
|
116
|
+
log: compiler.announce,
|
|
117
|
+
modules: {
|
|
118
|
+
application,
|
|
119
|
+
destroyable,
|
|
120
|
+
resolver,
|
|
121
|
+
router,
|
|
122
|
+
route,
|
|
123
|
+
testWaiters,
|
|
124
|
+
runloop,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @type {(() => void)[]}
|
|
130
|
+
*/
|
|
131
|
+
const destroyables = [];
|
|
132
|
+
|
|
133
|
+
await Promise.all(
|
|
134
|
+
/** @type {unknown[]} */ (extra.codeBlocks).map(async (/** @type {unknown} */ info) => {
|
|
135
|
+
/** @type {Record<string, unknown>} */
|
|
136
|
+
const infoObj = /** @type {Record<string, unknown>} */ (info);
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
!api.canCompile(
|
|
140
|
+
/** @type {string} */ (infoObj.format),
|
|
141
|
+
/** @type {string} */ (infoObj.flavor)
|
|
142
|
+
)
|
|
143
|
+
) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const flavor = /** @type {string} */ (infoObj.flavor);
|
|
148
|
+
const hasScope =
|
|
149
|
+
flavor === 'ember' || infoObj.format === 'gjs' || infoObj.format === 'hbs';
|
|
150
|
+
const subRender = await compiler.compile(
|
|
151
|
+
/** @type {string} */ (infoObj.format),
|
|
152
|
+
/** @type {string} */ (infoObj.code),
|
|
153
|
+
{
|
|
154
|
+
...compiler.optionsFor(/** @type {string} */ (infoObj.format), flavor),
|
|
155
|
+
flavor: flavor,
|
|
156
|
+
// @ts-ignore
|
|
157
|
+
...(hasScope
|
|
158
|
+
? {
|
|
159
|
+
scope: extra.scope,
|
|
160
|
+
}
|
|
161
|
+
: {}),
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const selector = `#${/** @type {string} */ (infoObj.placeholderId)}`;
|
|
166
|
+
const target = element.querySelector(selector);
|
|
167
|
+
|
|
168
|
+
assert(
|
|
169
|
+
`Could not find placeholder / target element (using selector: \`${selector}\`). ` +
|
|
170
|
+
`Could not render ${/** @type {string} */ (infoObj.format)} block.`,
|
|
171
|
+
target
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
destroyables.push(subRender.destroy);
|
|
175
|
+
target.appendChild(subRender.element);
|
|
176
|
+
})
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
return () => {
|
|
180
|
+
for (const subDestroy of destroyables) {
|
|
181
|
+
subDestroy();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
destroy();
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
return gmdCompiler;
|
|
190
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { isRecord } from '../../utils.js';
|
|
2
|
+
import { renderApp } from './render-app-island.js';
|
|
3
|
+
|
|
4
|
+
let elementId = 0;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {unknown} [ options ]
|
|
8
|
+
* @returns {{ scope: Record<string, unknown> }}
|
|
9
|
+
*/
|
|
10
|
+
function filterOptions(options) {
|
|
11
|
+
if (!isRecord(options)) {
|
|
12
|
+
return { scope: {} };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
scope: /** @type {Record<string, unknown>}*/ (options?.scope || {}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {import('../../types.ts').CompilerConfig['compiler']}
|
|
22
|
+
*/
|
|
23
|
+
export async function compiler(config, api) {
|
|
24
|
+
/**
|
|
25
|
+
* @type {import('../../types.ts').Compiler}
|
|
26
|
+
*/
|
|
27
|
+
const hbsCompiler = {
|
|
28
|
+
compile: async (text, options) => {
|
|
29
|
+
const { template } = await api.tryResolve('@ember/template-compiler/runtime');
|
|
30
|
+
|
|
31
|
+
const component = template(text, {
|
|
32
|
+
scope: () => ({
|
|
33
|
+
...filterOptions(config).scope,
|
|
34
|
+
...filterOptions(options).scope,
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Some versions of ember implement the runtime template compiler incorrectly (albeit, correct enough for the constraints at the time).
|
|
40
|
+
* So we need to wait longer than a microtask queue request could take.
|
|
41
|
+
*
|
|
42
|
+
* To make sure that the template is compiled, and "component"
|
|
43
|
+
* has a value.
|
|
44
|
+
*
|
|
45
|
+
* See:
|
|
46
|
+
* - https://github.com/emberjs/ember.js/issues/20913
|
|
47
|
+
* - https://github.com/emberjs/ember.js/issues/20914
|
|
48
|
+
*/
|
|
49
|
+
await new Promise(requestAnimationFrame);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Is this allowed here? or do I just return text,
|
|
53
|
+
* and do the above in 'render'
|
|
54
|
+
*/
|
|
55
|
+
return component;
|
|
56
|
+
},
|
|
57
|
+
render: async (element, compiled, extra, compiler) => {
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* TODO: These will make things easier:
|
|
61
|
+
* https://github.com/emberjs/rfcs/pull/1099
|
|
62
|
+
* https://github.com/ember-cli/ember-addon-blueprint/blob/main/files/tests/test-helper.js
|
|
63
|
+
*/
|
|
64
|
+
const attribute = `data-repl-sdk-ember-hbs-${elementId++}`;
|
|
65
|
+
|
|
66
|
+
element.setAttribute(attribute, '');
|
|
67
|
+
|
|
68
|
+
const [application, destroyable, resolver, router, route, testWaiters, runloop] =
|
|
69
|
+
await compiler.tryResolveAll([
|
|
70
|
+
'@ember/application',
|
|
71
|
+
'@ember/destroyable',
|
|
72
|
+
'ember-resolver',
|
|
73
|
+
'@ember/routing/router',
|
|
74
|
+
'@ember/routing/route',
|
|
75
|
+
'@ember/test-waiters',
|
|
76
|
+
'@ember/runloop',
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
return renderApp({
|
|
80
|
+
element,
|
|
81
|
+
selector: `[${attribute}]`,
|
|
82
|
+
component: compiled,
|
|
83
|
+
log: compiler.announce,
|
|
84
|
+
modules: {
|
|
85
|
+
application,
|
|
86
|
+
destroyable,
|
|
87
|
+
resolver,
|
|
88
|
+
router,
|
|
89
|
+
route,
|
|
90
|
+
testWaiters,
|
|
91
|
+
runloop,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return hbsCompiler;
|
|
98
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** @type {any} */
|
|
2
|
+
let bootWaiter;
|
|
3
|
+
/** @type {any} */
|
|
4
|
+
let createWaiter;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Wait to boot the app until the Element is in the DOM.
|
|
8
|
+
* because This old way of making a whole app requires that the element
|
|
9
|
+
* be present in the app.
|
|
10
|
+
*
|
|
11
|
+
* We really need renderComponent(...)
|
|
12
|
+
* https://github.com/emberjs/ember.js/pull/20781
|
|
13
|
+
*
|
|
14
|
+
* @param {{
|
|
15
|
+
* element: Element,
|
|
16
|
+
* modules: { [name: string]: any},
|
|
17
|
+
* selector: string,
|
|
18
|
+
* log: (type: 'error' | 'info', message: string) => void;
|
|
19
|
+
* component: unknown
|
|
20
|
+
* }} options
|
|
21
|
+
*/
|
|
22
|
+
export async function renderApp({ element, modules, selector, component, log }) {
|
|
23
|
+
const App = modules.application.default;
|
|
24
|
+
const registerDestructor = modules.destroyable.registerDestructor;
|
|
25
|
+
const destroy = modules.destroyable.destroy;
|
|
26
|
+
const Resolver = modules.resolver.default;
|
|
27
|
+
const Router = modules.router.default;
|
|
28
|
+
const Route = modules.route.default;
|
|
29
|
+
const schedule = modules.runloop.schedule;
|
|
30
|
+
|
|
31
|
+
bootWaiter ||= modules.testWaiters.buildWaiter('repl-output:waiting-for-boot');
|
|
32
|
+
createWaiter ||= modules.testWaiters.buildWaiter('repl-output:waiting-for-creation');
|
|
33
|
+
|
|
34
|
+
const bootToken = bootWaiter.beginAsync();
|
|
35
|
+
const createToken = createWaiter.beginAsync();
|
|
36
|
+
|
|
37
|
+
class EphemeralApp extends App {
|
|
38
|
+
modulePrefix = 'ephemeral-render-output';
|
|
39
|
+
rootElement = element;
|
|
40
|
+
Resolver = Resolver.withModules({
|
|
41
|
+
'ephemeral-render-output/templates/application': { default: component },
|
|
42
|
+
'ephemeral-render-output/routes/application': {
|
|
43
|
+
default: class Application extends Route {
|
|
44
|
+
/**
|
|
45
|
+
* @param {unknown[]} args
|
|
46
|
+
*/
|
|
47
|
+
constructor(...args) {
|
|
48
|
+
super(...args);
|
|
49
|
+
|
|
50
|
+
registerDestructor(() => {
|
|
51
|
+
bootWaiter.endAsync(bootToken);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
afterModel() {
|
|
55
|
+
schedule('afterRender', () => {
|
|
56
|
+
requestAnimationFrame(() => {
|
|
57
|
+
log('info', 'Ember Island Rendered');
|
|
58
|
+
bootWaiter.endAsync(bootToken);
|
|
59
|
+
createWaiter.endAsync(createToken);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
'ephemeral-render-output/router': {
|
|
66
|
+
default: class BoilerplateRouter extends Router {
|
|
67
|
+
location = 'none';
|
|
68
|
+
rootURL = '/';
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
log('info', 'Booting Ember Island');
|
|
75
|
+
|
|
76
|
+
const app = EphemeralApp.create({
|
|
77
|
+
rootElement: element,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return () => {
|
|
81
|
+
destroy(app);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('../types.ts').CompilerConfig} CompilerConfig
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Other `@ember` (and `@glimmer`) packages are bundled in ember-source,
|
|
7
|
+
* and typecilaly use a build plugin to resolve from `@ember/*` imports.
|
|
8
|
+
*/
|
|
9
|
+
const externalPackages = [
|
|
10
|
+
'@ember/test-helpers',
|
|
11
|
+
'@ember/string',
|
|
12
|
+
'@ember/test-waiters',
|
|
13
|
+
'@ember/render-modifiers',
|
|
14
|
+
'@glimmer/component',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} id
|
|
19
|
+
* @returns {string | undefined | (() => Record<string, unknown>)}
|
|
20
|
+
*/
|
|
21
|
+
function resolve(id) {
|
|
22
|
+
if (id === '@ember/template-compiler/runtime') {
|
|
23
|
+
return `https://esm.sh/*ember-source/dist/packages/@ember/template-compiler/runtime.js`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isExternalEmber = externalPackages.some((name) => id.startsWith(name));
|
|
27
|
+
|
|
28
|
+
if (isExternalEmber) {
|
|
29
|
+
return `https://esm.sh/*${id}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (id.startsWith('@ember')) {
|
|
33
|
+
return `https://esm.sh/*ember-source/dist/packages/${id}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (id.startsWith('@glimmer')) {
|
|
37
|
+
return `https://esm.sh/*ember-source/dist/dependencies/${id}.js`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (id.startsWith('@embroider/macros')) {
|
|
41
|
+
return () => ({
|
|
42
|
+
// passthrough, we are not doing dead-code-elimination
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {unknown} x
|
|
46
|
+
*/
|
|
47
|
+
macroCondition: (x) => Boolean(x),
|
|
48
|
+
// I *could* actually implement this
|
|
49
|
+
dependencySatisfies: () => true,
|
|
50
|
+
isDevelopingApp: () => true,
|
|
51
|
+
getGlobalConfig: () => ({
|
|
52
|
+
WarpDrive: {
|
|
53
|
+
debug: false,
|
|
54
|
+
env: {
|
|
55
|
+
DEBUG: false,
|
|
56
|
+
TESTING: false,
|
|
57
|
+
PRODUCTION: true,
|
|
58
|
+
},
|
|
59
|
+
activeLogging: false,
|
|
60
|
+
compatWith: '99.0',
|
|
61
|
+
features: {},
|
|
62
|
+
deprecations: {},
|
|
63
|
+
polyfillUUID: false,
|
|
64
|
+
includeDataAdapter: false,
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
Example:
|
|
73
|
+
|
|
74
|
+
Uncaught (in promise) Error: Assertion Failed: You attempted to update `count` on `Demo`, but it had already been used previously in the same computation. Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.
|
|
75
|
+
|
|
76
|
+
`count` was first used:
|
|
77
|
+
|
|
78
|
+
- While rendering:
|
|
79
|
+
{{outlet}} for -top-level
|
|
80
|
+
-top-level
|
|
81
|
+
{{outlet}} for application
|
|
82
|
+
Demo
|
|
83
|
+
this.foos.value
|
|
84
|
+
this.foos
|
|
85
|
+
|
|
86
|
+
Stack trace for the update:
|
|
87
|
+
*
|
|
88
|
+
* @param {PromiseRejectionEvent} e
|
|
89
|
+
* @param {(message: string) => void} handle
|
|
90
|
+
*/
|
|
91
|
+
function onUnhandled(e, handle) {
|
|
92
|
+
if (!e.reason?.message) return;
|
|
93
|
+
|
|
94
|
+
let reason = e.reason.message;
|
|
95
|
+
|
|
96
|
+
if (reason.includes('Stack trace for the update:')) {
|
|
97
|
+
reason += ' (see console)';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
handle(reason);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @type {CompilerConfig}
|
|
105
|
+
*/
|
|
106
|
+
export const gjs = {
|
|
107
|
+
resolve,
|
|
108
|
+
onUnhandled,
|
|
109
|
+
codemirror: {
|
|
110
|
+
lang: async () => {
|
|
111
|
+
const { gjs } = await import('codemirror-lang-glimmer-js');
|
|
112
|
+
|
|
113
|
+
return gjs();
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
compiler: async (...args) => {
|
|
117
|
+
const gjs = await import('./ember/gjs.js');
|
|
118
|
+
|
|
119
|
+
return gjs.compiler(...args);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @type {CompilerConfig}
|
|
125
|
+
*/
|
|
126
|
+
export const hbs = {
|
|
127
|
+
resolve,
|
|
128
|
+
onUnhandled,
|
|
129
|
+
codemirror: {
|
|
130
|
+
lang: async () => {
|
|
131
|
+
const { glimmer } = await import('codemirror-lang-glimmer');
|
|
132
|
+
|
|
133
|
+
return glimmer();
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
compiler: async (...args) => {
|
|
137
|
+
const hbs = await import('./ember/hbs.js');
|
|
138
|
+
|
|
139
|
+
return hbs.compiler(...args);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @type {CompilerConfig}
|
|
145
|
+
*/
|
|
146
|
+
export const gmd = {
|
|
147
|
+
resolve,
|
|
148
|
+
onUnhandled,
|
|
149
|
+
codemirror: {
|
|
150
|
+
lang: async () => {
|
|
151
|
+
const { glimdown } = await import('codemirror-lang-glimdown');
|
|
152
|
+
|
|
153
|
+
return glimdown();
|
|
154
|
+
},
|
|
155
|
+
support: async () => {
|
|
156
|
+
const { gjs } = await import('codemirror-lang-glimmer-js');
|
|
157
|
+
|
|
158
|
+
return [gjs().support];
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
compiler: async (...args) => {
|
|
162
|
+
const hbs = await import('./ember/gmd.js');
|
|
163
|
+
|
|
164
|
+
return hbs.compiler(...args);
|
|
165
|
+
},
|
|
166
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { assert } from '../utils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {import('../types.ts').CompilerConfig}
|
|
5
|
+
*/
|
|
6
|
+
export const js = {
|
|
7
|
+
codemirror: {
|
|
8
|
+
lang: async () => {
|
|
9
|
+
const { javascript } = await import('@codemirror/lang-javascript');
|
|
10
|
+
|
|
11
|
+
return javascript();
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
compiler: async (config, api) => {
|
|
15
|
+
return {
|
|
16
|
+
compile: async (text, options) => {
|
|
17
|
+
// No compiling needed. Just JS
|
|
18
|
+
return text;
|
|
19
|
+
},
|
|
20
|
+
render: async (element, fun, extra, compiler) => {
|
|
21
|
+
assert(
|
|
22
|
+
`js document must have a function for a default export. Instead received: ${typeof fun}`,
|
|
23
|
+
typeof fun === 'function'
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
await fun(element);
|
|
27
|
+
|
|
28
|
+
compiler.announce('info', 'Done');
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|