repl-sdk 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -2
- package/src/compilers/ember/gjs.js +8 -40
- package/src/compilers/ember/gmd.js +7 -41
- package/src/compilers/ember/hbs.js +5 -36
- package/src/compilers/markdown/build-compiler.js +4 -4
- package/src/compilers/markdown/parse.test.ts +27 -0
- package/src/compilers/ember/render-app-island.js +0 -83
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repl-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"default": "./src/compilers/markdown/parse.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "https",
|
|
17
|
+
"url": "https://github.com/NullVoxPopuli/limber.git",
|
|
18
|
+
"directory": "packages/repl-sdk"
|
|
19
|
+
},
|
|
15
20
|
"ember-addon": {
|
|
16
21
|
"version": 2,
|
|
17
22
|
"type": "addon"
|
|
@@ -90,8 +95,8 @@
|
|
|
90
95
|
"unified": "^11.0.5",
|
|
91
96
|
"unist-util-visit": "^5.0.0",
|
|
92
97
|
"vfile": "^6.0.3",
|
|
93
|
-
"codemirror-lang-glimmer": "^2.0.3",
|
|
94
98
|
"codemirror-lang-glimdown": "^2.0.3",
|
|
99
|
+
"codemirror-lang-glimmer": "^2.0.3",
|
|
95
100
|
"codemirror-lang-glimmer-js": "^2.0.3"
|
|
96
101
|
},
|
|
97
102
|
"volta": {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { renderApp } from './render-app-island.js';
|
|
1
|
+
import { makeOwner } from './owner.js';
|
|
3
2
|
|
|
4
3
|
let elementId = 0;
|
|
5
4
|
|
|
@@ -27,7 +26,7 @@ const buildDependencies = [
|
|
|
27
26
|
* because the underlying format / bytecodes / etc is private,
|
|
28
27
|
* and can change between versions of ember-source.
|
|
29
28
|
*/
|
|
30
|
-
'ember-source/
|
|
29
|
+
'ember-source/ember-template-compiler/index.js',
|
|
31
30
|
/**
|
|
32
31
|
* Converts gjs/gts to standard js/ts
|
|
33
32
|
*/
|
|
@@ -168,43 +167,12 @@ export async function compiler(config, api) {
|
|
|
168
167
|
|
|
169
168
|
element.setAttribute(attribute, '');
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// const owner = makeOwner(config.owner);
|
|
178
|
-
// const result = renderComponent(compiled, { into: element, owner });
|
|
179
|
-
//
|
|
180
|
-
// return () => result.destroy();
|
|
181
|
-
|
|
182
|
-
const [application, destroyable, resolver, router, route, testWaiters, runloop] =
|
|
183
|
-
await compiler.tryResolveAll([
|
|
184
|
-
'@ember/application',
|
|
185
|
-
'@ember/destroyable',
|
|
186
|
-
'ember-resolver',
|
|
187
|
-
'@ember/routing/router',
|
|
188
|
-
'@ember/routing/route',
|
|
189
|
-
'@ember/test-waiters',
|
|
190
|
-
'@ember/runloop',
|
|
191
|
-
]);
|
|
192
|
-
|
|
193
|
-
return renderApp({
|
|
194
|
-
element,
|
|
195
|
-
selector: `[${attribute}]`,
|
|
196
|
-
component: compiled,
|
|
197
|
-
log: compiler.announce,
|
|
198
|
-
modules: {
|
|
199
|
-
application,
|
|
200
|
-
destroyable,
|
|
201
|
-
resolver,
|
|
202
|
-
router,
|
|
203
|
-
route,
|
|
204
|
-
testWaiters,
|
|
205
|
-
runloop,
|
|
206
|
-
},
|
|
207
|
-
});
|
|
170
|
+
const { renderComponent } = await compiler.tryResolve('@ember/renderer');
|
|
171
|
+
|
|
172
|
+
const owner = makeOwner(config.owner);
|
|
173
|
+
const result = renderComponent(compiled, { into: element, owner });
|
|
174
|
+
|
|
175
|
+
return () => result.destroy();
|
|
208
176
|
},
|
|
209
177
|
handlers: {
|
|
210
178
|
js: async (text) => {
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { assert, isRecord } from '../../utils.js';
|
|
5
5
|
import { buildCodeFenceMetaUtils } from '../markdown/utils.js';
|
|
6
|
-
import { renderApp } from './render-app-island.js';
|
|
7
6
|
|
|
8
7
|
let elementId = 0;
|
|
9
8
|
|
|
@@ -97,48 +96,15 @@ export async function compiler(config, api) {
|
|
|
97
96
|
|
|
98
97
|
element.setAttribute(attribute, '');
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
// const result = renderComponent(compiled, {
|
|
107
|
-
// into: element,
|
|
108
|
-
// owner: userOptions.owner,
|
|
109
|
-
// });
|
|
110
|
-
//
|
|
111
|
-
// const destroy = () => result.destroy();
|
|
112
|
-
const [application, destroyable, resolver, router, route, testWaiters, runloop] =
|
|
113
|
-
await compiler.tryResolveAll([
|
|
114
|
-
'@ember/application',
|
|
115
|
-
'@ember/destroyable',
|
|
116
|
-
'ember-resolver',
|
|
117
|
-
'@ember/routing/router',
|
|
118
|
-
'@ember/routing/route',
|
|
119
|
-
'@ember/test-waiters',
|
|
120
|
-
'@ember/runloop',
|
|
121
|
-
]);
|
|
122
|
-
|
|
123
|
-
// We don't want to await here, because we need to early
|
|
124
|
-
// return the element so that the app can render in to it.
|
|
125
|
-
// (Ember will only render in to an element if it's present in the DOM)
|
|
126
|
-
const destroy = await renderApp({
|
|
127
|
-
element,
|
|
128
|
-
selector: `[${attribute}]`,
|
|
129
|
-
component: compiled,
|
|
130
|
-
log: compiler.announce,
|
|
131
|
-
modules: {
|
|
132
|
-
application,
|
|
133
|
-
destroyable,
|
|
134
|
-
resolver,
|
|
135
|
-
router,
|
|
136
|
-
route,
|
|
137
|
-
testWaiters,
|
|
138
|
-
runloop,
|
|
139
|
-
},
|
|
99
|
+
const { renderComponent } = await compiler.tryResolve('@ember/renderer');
|
|
100
|
+
|
|
101
|
+
const result = renderComponent(compiled, {
|
|
102
|
+
into: element,
|
|
103
|
+
owner: userOptions.owner,
|
|
140
104
|
});
|
|
141
105
|
|
|
106
|
+
const destroy = () => result.destroy();
|
|
107
|
+
|
|
142
108
|
/**
|
|
143
109
|
* @type {(() => void)[]}
|
|
144
110
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isRecord } from '../../utils.js';
|
|
2
|
-
|
|
3
|
-
import { renderApp } from './render-app-island.js';
|
|
2
|
+
import { makeOwner } from './owner.js';
|
|
4
3
|
|
|
5
4
|
let elementId = 0;
|
|
6
5
|
|
|
@@ -66,41 +65,11 @@ export async function compiler(config, api) {
|
|
|
66
65
|
|
|
67
66
|
element.setAttribute(attribute, '');
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
// const { renderComponent } = await compiler.tryResolve('@ember/renderer');
|
|
74
|
-
// const owner = makeOwner(config.owner);
|
|
75
|
-
// const result = renderComponent(compiled, { into: element, owner });
|
|
76
|
-
//
|
|
77
|
-
// return () => result.destroy();
|
|
78
|
-
const [application, destroyable, resolver, router, route, testWaiters, runloop] =
|
|
79
|
-
await compiler.tryResolveAll([
|
|
80
|
-
'@ember/application',
|
|
81
|
-
'@ember/destroyable',
|
|
82
|
-
'ember-resolver',
|
|
83
|
-
'@ember/routing/router',
|
|
84
|
-
'@ember/routing/route',
|
|
85
|
-
'@ember/test-waiters',
|
|
86
|
-
'@ember/runloop',
|
|
87
|
-
]);
|
|
68
|
+
const { renderComponent } = await compiler.tryResolve('@ember/renderer');
|
|
69
|
+
const owner = makeOwner(config.owner);
|
|
70
|
+
const result = renderComponent(compiled, { into: element, owner });
|
|
88
71
|
|
|
89
|
-
return
|
|
90
|
-
element,
|
|
91
|
-
selector: `[${attribute}]`,
|
|
92
|
-
component: compiled,
|
|
93
|
-
log: compiler.announce,
|
|
94
|
-
modules: {
|
|
95
|
-
application,
|
|
96
|
-
destroyable,
|
|
97
|
-
resolver,
|
|
98
|
-
router,
|
|
99
|
-
route,
|
|
100
|
-
testWaiters,
|
|
101
|
-
runloop,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
72
|
+
return () => result.destroy();
|
|
104
73
|
},
|
|
105
74
|
};
|
|
106
75
|
|
|
@@ -44,8 +44,8 @@ export function buildCompiler(options) {
|
|
|
44
44
|
// @ts-ignore - unified processor types are complex and change as plugins are added
|
|
45
45
|
compiler = compiler.use(() => (tree) => {
|
|
46
46
|
visit(tree, 'html', function (node) {
|
|
47
|
-
// Check if this html node is a PascalCase component
|
|
48
|
-
if (typeof node.value === 'string' && node.value.match(
|
|
47
|
+
// Check if this html node is a PascalCase component (opening or closing tag)
|
|
48
|
+
if (typeof node.value === 'string' && node.value.match(/^<\/?[A-Z][a-zA-Z0-9]/)) {
|
|
49
49
|
// Add a marker to the node's data that remarkRehype will preserve
|
|
50
50
|
// remark-rehype with allowDangerousHtml will turn this into a text node,
|
|
51
51
|
// and the data should be preserved
|
|
@@ -63,7 +63,7 @@ export function buildCompiler(options) {
|
|
|
63
63
|
if (
|
|
64
64
|
child.type === 'html' &&
|
|
65
65
|
typeof child.value === 'string' &&
|
|
66
|
-
child.value.match(
|
|
66
|
+
child.value.match(/^<\/?[A-Z][a-zA-Z0-9]/)
|
|
67
67
|
) {
|
|
68
68
|
if (!child.data) child.data = {};
|
|
69
69
|
child.data.isPascalCaseComponent = true;
|
|
@@ -154,7 +154,7 @@ export function buildCompiler(options) {
|
|
|
154
154
|
// Pattern: <PascalCaseName followed by whitespace, > or @
|
|
155
155
|
if (
|
|
156
156
|
(nodeObj.type === 'text' || nodeObj.type === 'raw' || nodeObj.type === 'html') &&
|
|
157
|
-
nodeObj.value.match(
|
|
157
|
+
nodeObj.value.match(/<\/?[A-Z][a-zA-Z0-9]*(\s|>|@)/)
|
|
158
158
|
) {
|
|
159
159
|
nodeObj.type = 'glimmer_raw';
|
|
160
160
|
|
|
@@ -104,6 +104,33 @@ describe('default features', () => {
|
|
|
104
104
|
`);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
it('allows components to wrap markdown content', async () => {
|
|
108
|
+
const result = await parseMarkdown(
|
|
109
|
+
[
|
|
110
|
+
`# Title`,
|
|
111
|
+
'',
|
|
112
|
+
'Text',
|
|
113
|
+
'',
|
|
114
|
+
'<Callout>',
|
|
115
|
+
'',
|
|
116
|
+
'Info [text](https://url.url)',
|
|
117
|
+
'',
|
|
118
|
+
'</Callout>',
|
|
119
|
+
'',
|
|
120
|
+
].join('\n'),
|
|
121
|
+
{ ...defaults }
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(result.codeBlocks).toMatchInlineSnapshot(`[]`);
|
|
125
|
+
expect(result.text).toMatchInlineSnapshot(`
|
|
126
|
+
"<h1 id="title">Title</h1>
|
|
127
|
+
<p>Text</p>
|
|
128
|
+
<Callout>
|
|
129
|
+
<p>Info <a href="https://url.url">text</a></p>
|
|
130
|
+
</Callout>"
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
|
|
107
134
|
describe('does not', () => {
|
|
108
135
|
it(`mistakenly transform text in codefences (previewed text is transformed though)`, async () => {
|
|
109
136
|
const result = await parseMarkdown(
|
|
@@ -1,83 +0,0 @@
|
|
|
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
|
-
}
|