apprun 3.38.0 → 6.0.0-rc.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/CHANGELOG.md +12 -1
- package/README.md +18 -10
- package/apprun.d.ts +67 -23
- package/dist/apprun-code.js +1 -1
- package/dist/apprun-code.js.map +1 -1
- package/dist/apprun-dev-tools.js +1 -1
- package/dist/apprun-dev-tools.js.map +1 -1
- package/dist/apprun-html.esm.js +7 -7
- package/dist/apprun-html.esm.js.map +1 -1
- package/dist/apprun-html.js +1 -1
- package/dist/apprun-html.js.map +1 -1
- package/dist/apprun-play.js +1 -1
- package/dist/apprun-play.js.map +1 -1
- package/dist/apprun.esm.js +1 -1
- package/dist/apprun.esm.js.map +1 -1
- package/dist/apprun.js +1 -1
- package/dist/apprun.js.map +1 -1
- package/esm/add-components.js +7 -7
- package/esm/add-components.js.map +1 -1
- package/esm/app.js +81 -32
- package/esm/app.js.map +1 -1
- package/esm/apprun-code.js +8 -2
- package/esm/apprun-code.js.map +1 -1
- package/esm/apprun-html.js +14 -9
- package/esm/apprun-html.js.map +1 -1
- package/esm/apprun-play.js +7 -1
- package/esm/apprun-play.js.map +1 -1
- package/esm/apprun.js +38 -19
- package/esm/apprun.js.map +1 -1
- package/esm/component.js +90 -37
- package/esm/component.js.map +1 -1
- package/esm/directive.js +1 -1
- package/esm/directive.js.map +1 -1
- package/esm/router.js +73 -19
- package/esm/router.js.map +1 -1
- package/esm/types.js +2 -1
- package/esm/types.js.map +1 -1
- package/esm/vdom-my.js +52 -52
- package/esm/vdom-my.js.map +1 -1
- package/esm/vdom-to-html.js +8 -1
- package/esm/vdom-to-html.js.map +1 -1
- package/esm/vdom.js +3 -3
- package/esm/vdom.js.map +1 -1
- package/esm/version.js +1 -1
- package/esm/version.js.map +1 -1
- package/esm/web-component.js +23 -6
- package/esm/web-component.js.map +1 -1
- package/jsx-runtime.js +1 -1
- package/jsx-runtime.js.map +1 -1
- package/package.json +62 -2
- package/.clinerules +0 -1
- package/.travis.yml +0 -10
- package/BACKERS.md +0 -8
- package/CNAME +0 -1
- package/WHATSNEW.md +0 -367
- package/ai/apprun-html.prompt.md +0 -290
- package/ai/apprun.prompt.md +0 -602
- package/apprun-book.jpg +0 -0
- package/dist/apprun-dev-tools-tests.js +0 -1
- package/dist/apprun-dev-tools.js.LICENSE.txt +0 -1
- package/dist/apprun-play-html.esm.js +0 -34
- package/dist/apprun-play-html.esm.js.map +0 -1
- package/error.log +0 -0
- package/esm/apprun-play-html.js +0 -210
- package/esm/apprun-play-html.js.map +0 -1
- package/esm/shadow.js +0 -8
- package/esm/shadow.js.map +0 -1
- package/esm/vdom-html.js +0 -22
- package/esm/vdom-html.js.map +0 -1
- package/esm/vdom-my-new.js +0 -327
- package/esm/vdom-my-new.js.map +0 -1
- package/esm/vdom-patch.js +0 -103
- package/esm/vdom-patch.js.map +0 -1
- package/index.html +0 -87
- package/jest.config.js +0 -57
- package/jest.setup.js +0 -73
- package/logo.png +0 -0
- package/react.js +0 -13
- package/rollup.config.js +0 -62
- package/src/add-components.ts +0 -103
- package/src/app.ts +0 -173
- package/src/apprun-code.tsx +0 -177
- package/src/apprun-dev-tools-tests.tsx +0 -101
- package/src/apprun-dev-tools.tsx +0 -307
- package/src/apprun-html.ts +0 -25
- package/src/apprun-play.tsx +0 -249
- package/src/apprun.ts +0 -238
- package/src/component.ts +0 -388
- package/src/createState.ts +0 -11
- package/src/decorator.ts +0 -98
- package/src/directive.ts +0 -303
- package/src/global.d.ts +0 -22
- package/src/router.ts +0 -311
- package/src/shadow.tsx +0 -8
- package/src/tsconfig.json +0 -16
- package/src/type-utils.ts +0 -130
- package/src/types.ts +0 -151
- package/src/vdom-html.ts_ +0 -20
- package/src/vdom-lit-html.ts +0 -67
- package/src/vdom-my-new.ts +0 -311
- package/src/vdom-my-prop-attr.ts +0 -241
- package/src/vdom-my.ts +0 -286
- package/src/vdom-patch.ts +0 -108
- package/src/vdom-to-html.tsx +0 -49
- package/src/vdom.ts +0 -28
- package/src/version.ts +0 -16
- package/src/web-component.ts +0 -154
- package/tsconfig.jest.json +0 -49
- package/tsconfig.json +0 -16
- package/tslint.json +0 -114
- package/typescriptreact.json +0 -87
- package/viewEngine.js +0 -54
- package/webpack.config.cjs +0 -41
package/src/apprun-dev-tools.tsx
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import app from './app';
|
|
2
|
-
import toHTML from './vdom-to-html';
|
|
3
|
-
import { _createEventTests, _createStateTests } from './apprun-dev-tools-tests';
|
|
4
|
-
|
|
5
|
-
function createProxy(obj) {
|
|
6
|
-
const handler = {
|
|
7
|
-
get(target, property, receiver) {
|
|
8
|
-
|
|
9
|
-
// Get the property value
|
|
10
|
-
const value = Reflect.get(target, property, receiver);
|
|
11
|
-
|
|
12
|
-
// If the value is an object (including arrays), proxy it
|
|
13
|
-
if (typeof value === 'object' && value !== null) {
|
|
14
|
-
if (Array.isArray(value)) {
|
|
15
|
-
// Proxy each element of the array if it's an object
|
|
16
|
-
return value.map(item => createProxy(item));
|
|
17
|
-
} else {
|
|
18
|
-
// Recursively proxy the object
|
|
19
|
-
return createProxy(value);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return `{${property}}`
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return Array.isArray(obj) ?
|
|
29
|
-
obj.map(item => createProxy(item)) : new Proxy(obj, handler);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function htmlEncode(input) {
|
|
33
|
-
return !input ? input : input.toString()
|
|
34
|
-
.replace(/&/g, '&')
|
|
35
|
-
.replace(/</g, '<')
|
|
36
|
-
.replace(/>/g, '>');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getVDOM(component) {
|
|
40
|
-
let view;
|
|
41
|
-
if (typeof component.state === 'object') {
|
|
42
|
-
const proxy = createProxy(component.state);
|
|
43
|
-
view = component.view(proxy);
|
|
44
|
-
} else {
|
|
45
|
-
view = component.view(component.state);
|
|
46
|
-
}
|
|
47
|
-
return view;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const componentCache = new Map();
|
|
51
|
-
app['debug'] = true;
|
|
52
|
-
app.on('debug-create-component', component => {
|
|
53
|
-
const element = component.element;
|
|
54
|
-
if (!element) {
|
|
55
|
-
console.warn('Component created without an element:', component);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (componentCache.get(element)) { componentCache.get(element).push(component) }
|
|
59
|
-
else { componentCache.set(element, [component]) }
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
window['_apprun-help'] = ['', () => {
|
|
63
|
-
Object.keys(window).forEach(cmd => {
|
|
64
|
-
if (cmd.startsWith('_apprun-')) {
|
|
65
|
-
cmd === '_apprun-help' ?
|
|
66
|
-
console.log('AppRun Commands:') :
|
|
67
|
-
console.log(`* ${cmd.substring(8)}: ${window[cmd][0]}`);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}];
|
|
71
|
-
|
|
72
|
-
function newWin(html) {
|
|
73
|
-
const win = window.open('', '_apprun_debug', 'toolbar=0');
|
|
74
|
-
win.document.write(`<html>
|
|
75
|
-
<title>AppRun Analyzer | ${document.location.href}</title>
|
|
76
|
-
<style>
|
|
77
|
-
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI" }
|
|
78
|
-
li { margin-left: 80px; }
|
|
79
|
-
</style>
|
|
80
|
-
<body>
|
|
81
|
-
<div id="main">${html}</div>
|
|
82
|
-
</script>
|
|
83
|
-
</body>
|
|
84
|
-
</html>`);
|
|
85
|
-
win.document.close();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const viewElement = element => <div>
|
|
89
|
-
{element.tagName.toLowerCase()}{element.id ? '#' + element.id : ''}
|
|
90
|
-
{' '}
|
|
91
|
-
{element.className && element.className.split(' ').map(c => '.' + c).join()}
|
|
92
|
-
</div>;
|
|
93
|
-
|
|
94
|
-
const viewComponents = state => {
|
|
95
|
-
const Components = ({ components }) => <ul>
|
|
96
|
-
{components.map(component => {
|
|
97
|
-
|
|
98
|
-
const vdom = getVDOM(component);
|
|
99
|
-
const events = component['_actions'].map(a => a.name);
|
|
100
|
-
|
|
101
|
-
const component_def = {
|
|
102
|
-
state: component.state,
|
|
103
|
-
view: vdom,
|
|
104
|
-
actions: events,
|
|
105
|
-
update: component.update
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
return <li>
|
|
109
|
-
<div>{component.constructor.name}</div>
|
|
110
|
-
<div><pre>{htmlEncode(JSON.stringify(component_def, null, 2))}</pre></div>
|
|
111
|
-
<br />
|
|
112
|
-
</li>;
|
|
113
|
-
|
|
114
|
-
})}
|
|
115
|
-
</ul>;
|
|
116
|
-
|
|
117
|
-
return <ul>
|
|
118
|
-
{state.map(({ element, comps }) => <li>
|
|
119
|
-
<div>{viewElement(element)}</div>
|
|
120
|
-
<Components components={comps} />
|
|
121
|
-
</li>)}
|
|
122
|
-
</ul>
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const viewEvents = state => {
|
|
126
|
-
const Components = ({ components }) => <ul>
|
|
127
|
-
{components.map(component => <li>
|
|
128
|
-
<div>{component.constructor.name}</div>
|
|
129
|
-
</li>)}
|
|
130
|
-
</ul>;
|
|
131
|
-
|
|
132
|
-
const Events = ({ events, global }) => <ul>
|
|
133
|
-
{events && events
|
|
134
|
-
.filter(event =>
|
|
135
|
-
event.global === global && event.event !== '.')
|
|
136
|
-
.map(({ event, components }) => <li>
|
|
137
|
-
<div>{event}</div>
|
|
138
|
-
<Components components={components} />
|
|
139
|
-
</li>)}
|
|
140
|
-
</ul>;
|
|
141
|
-
|
|
142
|
-
return <div>
|
|
143
|
-
<div>GLOBAL EVENTS</div>
|
|
144
|
-
<Events events={state} global={true} />
|
|
145
|
-
<div>LOCAL EVENTS</div>
|
|
146
|
-
<Events events={state} global={false} />
|
|
147
|
-
</div>
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const _events = (print?) => {
|
|
151
|
-
const global_events = app['_events']
|
|
152
|
-
const events = {};
|
|
153
|
-
const cache = componentCache;
|
|
154
|
-
|
|
155
|
-
const add_component = component => component['_actions'].forEach(event => {
|
|
156
|
-
events[event.name] = events[event.name] || [];
|
|
157
|
-
events[event.name].push(component);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
if (cache instanceof Map) {
|
|
161
|
-
for (let [key, comps] of cache) {
|
|
162
|
-
comps.forEach(add_component);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const data = [];
|
|
166
|
-
Object.keys(events).forEach(event => {
|
|
167
|
-
data.push({ event, components: events[event], global: global_events[event] ? true : false });
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
data.sort(((a, b) => a.event > b.event ? 1 : -1)).map(e => e.event);
|
|
171
|
-
|
|
172
|
-
if (print) {
|
|
173
|
-
const vdom = viewEvents(data);
|
|
174
|
-
newWin(toHTML(vdom));
|
|
175
|
-
} else {
|
|
176
|
-
console.log('=== GLOBAL EVENTS ===')
|
|
177
|
-
data.filter(event => event.global && event.event !== '.')
|
|
178
|
-
.forEach(({ event, components }) => console.log({ event }, components));
|
|
179
|
-
console.log('=== LOCAL EVENTS ===')
|
|
180
|
-
data.filter(event => !event.global && event.event !== '.')
|
|
181
|
-
.forEach(({ event, components }) => console.log({ event }, components));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const _components = (print?) => {
|
|
186
|
-
const components = componentCache;
|
|
187
|
-
const data = [];
|
|
188
|
-
|
|
189
|
-
if (components instanceof Map) {
|
|
190
|
-
for (let [key, comps] of components) {
|
|
191
|
-
const element = typeof key === 'string' ? document.getElementById(key) || document.querySelector(key) : key;
|
|
192
|
-
data.push({ element, comps });
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (print) {
|
|
196
|
-
const vdom = viewComponents(data);
|
|
197
|
-
newWin(toHTML(vdom));
|
|
198
|
-
} else {
|
|
199
|
-
data.forEach(({ element, comps }) => console.log(element, comps));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
let debugging = Number(window?.localStorage?.getItem('__apprun_debugging__')) || 0;
|
|
204
|
-
app.on('debug', p => {
|
|
205
|
-
if (debugging & 1 && p.event) console.log(p);
|
|
206
|
-
if (debugging & 2 && p.vdom) console.log(p);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
window['_apprun-components'] = ['components [print|clear]', (p) => {
|
|
210
|
-
if (p === 'print') {
|
|
211
|
-
_components(true);
|
|
212
|
-
} else if (p === 'clear') {
|
|
213
|
-
componentCache.clear();
|
|
214
|
-
console.log('Component cache cleared');
|
|
215
|
-
} else {
|
|
216
|
-
_components(false);
|
|
217
|
-
}
|
|
218
|
-
}]
|
|
219
|
-
|
|
220
|
-
window['_apprun-events'] = ['events [print]', (p) => {
|
|
221
|
-
_events(p === 'print');
|
|
222
|
-
}]
|
|
223
|
-
|
|
224
|
-
window['_apprun-log'] = ['log [event|view] on|off', (a1?, a2?) => {
|
|
225
|
-
if (a1 === 'on') {
|
|
226
|
-
debugging = 3;
|
|
227
|
-
} else if (a1 === 'off') {
|
|
228
|
-
debugging = 0;
|
|
229
|
-
} else if (a1 === 'event') {
|
|
230
|
-
if (a2 === 'on') {
|
|
231
|
-
debugging |= 1;
|
|
232
|
-
} else if (a2 === 'off') {
|
|
233
|
-
debugging &= ~1;
|
|
234
|
-
}
|
|
235
|
-
} else if (a1 === 'view') {
|
|
236
|
-
if (a2 === 'on') {
|
|
237
|
-
debugging |= 2;
|
|
238
|
-
} else if (a2 === 'off') {
|
|
239
|
-
debugging &= ~2;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
console.log(`* log ${a1} ${a2 || ''}`);
|
|
243
|
-
window?.localStorage?.setItem('__apprun_debugging__', `${debugging}`)
|
|
244
|
-
}];
|
|
245
|
-
|
|
246
|
-
window['_apprun-create-event-tests'] = ['create-event-tests',
|
|
247
|
-
() => _createEventTests()
|
|
248
|
-
]
|
|
249
|
-
|
|
250
|
-
window['_apprun-create-state-tests'] = ['create-state-tests <start|stop>',
|
|
251
|
-
(p?) => _createStateTests(p)
|
|
252
|
-
]
|
|
253
|
-
|
|
254
|
-
window['_apprun'] = (strings) => {
|
|
255
|
-
const [cmd, ...p] = strings[0].split(' ').filter(c => !!c);
|
|
256
|
-
const command = window[`_apprun-${cmd}`];
|
|
257
|
-
if (command) command[1](...p);
|
|
258
|
-
else window['_apprun-help'][1]();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
console.info('AppRun DevTools 3.36: type "_apprun `help`" to list all available commands.');
|
|
262
|
-
|
|
263
|
-
const reduxExt = window['__REDUX_DEVTOOLS_EXTENSION__'];
|
|
264
|
-
if (reduxExt) {
|
|
265
|
-
let devTools_running = false;
|
|
266
|
-
const devTools = window['__REDUX_DEVTOOLS_EXTENSION__'].connect();
|
|
267
|
-
if (devTools) {
|
|
268
|
-
const hash = location.hash || '#';
|
|
269
|
-
devTools.send(hash, '');
|
|
270
|
-
const buf = [{ component: null, state: '' }];
|
|
271
|
-
console.info('Connected to the Redux DevTools');
|
|
272
|
-
devTools.subscribe((message) => {
|
|
273
|
-
if (message.type === 'START') devTools_running = true;
|
|
274
|
-
else if (message.type === 'STOP') devTools_running = false;
|
|
275
|
-
else if (message.type === 'DISPATCH') {
|
|
276
|
-
// console.log('From Redux DevTools: ', message);
|
|
277
|
-
const idx = message.payload.index;
|
|
278
|
-
if (idx === 0) { app.run(hash) }
|
|
279
|
-
else {
|
|
280
|
-
const { component, state } = buf[idx];
|
|
281
|
-
component?.setState(state);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
const send = (component, action, state) => {
|
|
287
|
-
if (state == null) return;
|
|
288
|
-
buf.push({ component, state });
|
|
289
|
-
devTools.send(action, state);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
app.on('debug', p => {
|
|
293
|
-
if (devTools_running && p.event) {
|
|
294
|
-
const state = p.newState;
|
|
295
|
-
const type = p.event;
|
|
296
|
-
const payload = p.p;
|
|
297
|
-
const action = { type, payload };
|
|
298
|
-
const component = p.component;
|
|
299
|
-
if (state instanceof Promise) {
|
|
300
|
-
state.then(s => send(component, action, s));
|
|
301
|
-
} else {
|
|
302
|
-
send(component, action, state);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}
|
package/src/apprun-html.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import app from './apprun'
|
|
2
|
-
import { safeGlobalAssign, SafeGlobalContext } from './type-utils';
|
|
3
|
-
export {
|
|
4
|
-
app, Component, View, Action, Update, on, update, event, EventOptions,
|
|
5
|
-
customElement, CustomElementOptions,
|
|
6
|
-
ROUTER_404_EVENT, ROUTER_EVENT, safeHTML
|
|
7
|
-
} from './apprun'
|
|
8
|
-
import { createElement, render, Fragment, html, svg, run } from './vdom-lit-html';
|
|
9
|
-
export { html, svg, render, run }
|
|
10
|
-
|
|
11
|
-
app.createElement = createElement;
|
|
12
|
-
app.render = render;
|
|
13
|
-
app.Fragment = Fragment;
|
|
14
|
-
|
|
15
|
-
export default app;
|
|
16
|
-
|
|
17
|
-
if (typeof window === 'object') {
|
|
18
|
-
const globalWindow = window as SafeGlobalContext;
|
|
19
|
-
safeGlobalAssign(globalWindow, {
|
|
20
|
-
'React': globalWindow['_React'] || app,
|
|
21
|
-
'html': html,
|
|
22
|
-
'svg': svg,
|
|
23
|
-
'run': run
|
|
24
|
-
});
|
|
25
|
-
}
|
package/src/apprun-play.tsx
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { app, Component } from './apprun';
|
|
2
|
-
|
|
3
|
-
const popup_div = `<div id="play-popup" class="overlay">
|
|
4
|
-
<style id="apprun-play-style">
|
|
5
|
-
.apprun-play .col {
|
|
6
|
-
height: 100%;
|
|
7
|
-
flex: 1;
|
|
8
|
-
}
|
|
9
|
-
.apprun-preview {
|
|
10
|
-
width: 100%
|
|
11
|
-
}
|
|
12
|
-
.apprun-play .editor, .apprun-play .preview {
|
|
13
|
-
display: inline-block;
|
|
14
|
-
width: calc(100% - 20px);
|
|
15
|
-
height: calc(100% - 10px);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
a.button {
|
|
19
|
-
font-size: .8em;
|
|
20
|
-
padding: 10px;
|
|
21
|
-
cursor: pointer;
|
|
22
|
-
color: var(--md-primary-bg-color);
|
|
23
|
-
background: var(--md-primary-fg-color)
|
|
24
|
-
}
|
|
25
|
-
a.button:hover {
|
|
26
|
-
color: var(--md-primary-fg-color);
|
|
27
|
-
background: var(--md-primary-bg-color)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.overlay {
|
|
31
|
-
position: fixed;
|
|
32
|
-
top: 0;
|
|
33
|
-
bottom: 0;
|
|
34
|
-
left: 0;
|
|
35
|
-
right: 0;
|
|
36
|
-
background: rgba(0, 0, 0, 0.7);
|
|
37
|
-
visibility: hidden;
|
|
38
|
-
opacity: 0;
|
|
39
|
-
z-index: 999;
|
|
40
|
-
}
|
|
41
|
-
.overlay.show {
|
|
42
|
-
visibility: visible;
|
|
43
|
-
opacity: 1;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.popup {
|
|
47
|
-
margin: 80px auto;
|
|
48
|
-
padding: 20px;
|
|
49
|
-
background: #fff;
|
|
50
|
-
border-radius: 3px;
|
|
51
|
-
position: relative;
|
|
52
|
-
width: 90%;
|
|
53
|
-
height: calc(100% - 150px);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.popup .close {
|
|
57
|
-
position: absolute;
|
|
58
|
-
top: 10px;
|
|
59
|
-
right: 20px;
|
|
60
|
-
font-size: 20px;
|
|
61
|
-
font-weight: bold;
|
|
62
|
-
text-decoration: none;
|
|
63
|
-
color: #333;
|
|
64
|
-
}
|
|
65
|
-
.popup .close:hover {
|
|
66
|
-
color: #06D85F;
|
|
67
|
-
}
|
|
68
|
-
.popup .content {
|
|
69
|
-
height: 100%;
|
|
70
|
-
overflow: hidden;
|
|
71
|
-
display: flex;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.cm-s-default {
|
|
75
|
-
height: 100%;
|
|
76
|
-
font-size: small;
|
|
77
|
-
line-height: 1.5em;
|
|
78
|
-
z-index: 0;
|
|
79
|
-
}
|
|
80
|
-
</style>
|
|
81
|
-
|
|
82
|
-
<div class="popup apprun-play">
|
|
83
|
-
<a class="close" href="javascript:app.run('@close-popup')">×</a>
|
|
84
|
-
<div class="content">
|
|
85
|
-
<div class="col">
|
|
86
|
-
<textarea class="editor"></textarea>
|
|
87
|
-
</div>
|
|
88
|
-
<div class="col">
|
|
89
|
-
<iframe class="preview"/>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
</div>`;
|
|
94
|
-
|
|
95
|
-
const encodeHTML = code => {
|
|
96
|
-
return code.replace(/&/g, '&')
|
|
97
|
-
.replace(/</g, '<')
|
|
98
|
-
.replace(/>/g, '>')
|
|
99
|
-
.replace(/"/g, '"')
|
|
100
|
-
.replace(/'/g, ''');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const code_html = code => `<!DOCTYPE html>
|
|
104
|
-
<html lang="en">
|
|
105
|
-
<head>
|
|
106
|
-
<meta charset="UTF-8">
|
|
107
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
108
|
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
109
|
-
<title>AppRun Playground</title>
|
|
110
|
-
<style>
|
|
111
|
-
body {
|
|
112
|
-
font-family: "Benton Sans", "Helvetica Neue", helvetica, arial, sans-serif;
|
|
113
|
-
margin: 2em;
|
|
114
|
-
}
|
|
115
|
-
</style>
|
|
116
|
-
<script src="https://cdn.jsdelivr.net/npm/typescript@latest"></script>
|
|
117
|
-
<script src="https://unpkg.com/apprun/dist/apprun-html.js"></script>
|
|
118
|
-
</head>
|
|
119
|
-
<body>
|
|
120
|
-
<pre id="code" style="display:none">${encodeHTML(code)}</pre>
|
|
121
|
-
<script type="module">
|
|
122
|
-
const code = document.getElementById('code').innerText;
|
|
123
|
-
const compiled = ts.transpileModule(code, {
|
|
124
|
-
compilerOptions: {
|
|
125
|
-
"jsx": "react",
|
|
126
|
-
"jsxFactory": "app.h",
|
|
127
|
-
"jsxFragmentFactory": "app.Fragment",
|
|
128
|
-
"target": "es2020",
|
|
129
|
-
"module": "esnext",
|
|
130
|
-
},
|
|
131
|
-
reportDiagnostics: true,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
if (compiled.diagnostics && compiled.diagnostics.length) {
|
|
135
|
-
const pre = document.createElement('pre');
|
|
136
|
-
pre.style = 'font-size: 10px;';
|
|
137
|
-
pre.innerText = compiled.diagnostics.map(d => {
|
|
138
|
-
const start = d.start;
|
|
139
|
-
const end = d.start + d.length;
|
|
140
|
-
const line = code.substring(0, end).split('\\n').length;
|
|
141
|
-
const column = code.substring(0, end).split('\\n').pop().length;
|
|
142
|
-
return \`Line: \${line}, Column: \${column}, \${d.messageText}\`;
|
|
143
|
-
}).join('\\n');
|
|
144
|
-
document.body.appendChild(pre);
|
|
145
|
-
} else {
|
|
146
|
-
window.onerror = function () {
|
|
147
|
-
const pre = document.createElement('pre');
|
|
148
|
-
pre.style = 'font-size: 10px;';
|
|
149
|
-
pre.innerText = compiled.outputText;;
|
|
150
|
-
document.body.appendChild(pre);
|
|
151
|
-
};
|
|
152
|
-
const script = document.createElement('script');
|
|
153
|
-
script.type = 'module';
|
|
154
|
-
script.text = compiled.outputText;
|
|
155
|
-
document.body.appendChild(script);
|
|
156
|
-
}
|
|
157
|
-
</script>
|
|
158
|
-
</body>
|
|
159
|
-
</html>`;
|
|
160
|
-
|
|
161
|
-
declare var CodeMirror;
|
|
162
|
-
|
|
163
|
-
const setup_editor = (textarea, iframe, code, hide_src) => {
|
|
164
|
-
|
|
165
|
-
if (!iframe || !code) return;
|
|
166
|
-
|
|
167
|
-
const run_code = code => {
|
|
168
|
-
const iframe_clone = iframe.cloneNode();
|
|
169
|
-
iframe.parentNode?.replaceChild(iframe_clone, iframe);
|
|
170
|
-
iframe = iframe_clone;
|
|
171
|
-
const doc = iframe.contentWindow?.document;
|
|
172
|
-
if (!doc) return;
|
|
173
|
-
doc.open();
|
|
174
|
-
if (code.indexOf('<html') >= 0)
|
|
175
|
-
doc.write(code);
|
|
176
|
-
else
|
|
177
|
-
doc.write(code_html(code));
|
|
178
|
-
doc.close();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
run_code(code);
|
|
182
|
-
|
|
183
|
-
if (hide_src || !textarea || textarea.nodeName !== 'TEXTAREA') return;
|
|
184
|
-
if (typeof CodeMirror === 'undefined') {
|
|
185
|
-
textarea.onkeyup = () => run_code(textarea.value);
|
|
186
|
-
} else {
|
|
187
|
-
if (!textarea.editor) {
|
|
188
|
-
textarea.editor = CodeMirror.fromTextArea(textarea, {
|
|
189
|
-
lineNumbers: true,
|
|
190
|
-
mode: 'jsx'
|
|
191
|
-
});
|
|
192
|
-
textarea.editor.on('change', (cm) => run_code(cm.getValue()));
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
class Play extends Component<any> {
|
|
198
|
-
view = (state) => {
|
|
199
|
-
const code_id = state['code-element-id'];
|
|
200
|
-
const element = this.element;
|
|
201
|
-
let code_area, code;
|
|
202
|
-
if (code_id) {
|
|
203
|
-
code_area = document.getElementById(code_id);
|
|
204
|
-
} else {
|
|
205
|
-
code_area = element.previousElementSibling ||
|
|
206
|
-
element.parentElement.previousElementSibling;
|
|
207
|
-
}
|
|
208
|
-
code = code_area?.innerText // from div-code
|
|
209
|
-
|| code_area?.value // from textarea
|
|
210
|
-
|| state['code']; // from code attr
|
|
211
|
-
|
|
212
|
-
this.state.code_area = code_area;
|
|
213
|
-
this.state.code = code;
|
|
214
|
-
|
|
215
|
-
return code ? <>
|
|
216
|
-
<div class="toolbox">
|
|
217
|
-
{!state.hide_button && <a class="button" $onclick="show-popup">Try the Code</a>}
|
|
218
|
-
</div></>
|
|
219
|
-
: <div>AppRun Play cannot find code to run, please set code-element-id or code.</div>
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
rendered = ({ style, hide_src, code_area, code }) => {
|
|
223
|
-
if (!code) return;
|
|
224
|
-
if (!document.getElementById('play-popup')) {
|
|
225
|
-
document.body.insertAdjacentHTML('beforeend', popup_div);
|
|
226
|
-
const textarea = document.querySelector(".apprun-play .editor") as any;
|
|
227
|
-
const iframe = document.querySelector('.apprun-play .preview');
|
|
228
|
-
textarea.value = code;
|
|
229
|
-
setup_editor(textarea, iframe, code, false);
|
|
230
|
-
}
|
|
231
|
-
const iframe = document.createElement('iframe');
|
|
232
|
-
iframe.classList.add('apprun-preview');
|
|
233
|
-
iframe.style.cssText = style;
|
|
234
|
-
this.element.before(iframe);
|
|
235
|
-
if (hide_src) code_area.style.display = 'none';
|
|
236
|
-
setup_editor(code_area, iframe, code, hide_src);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
update = {
|
|
240
|
-
'show-popup': ({ code }) => {
|
|
241
|
-
const textarea = document.querySelector(".apprun-play .editor") as any;
|
|
242
|
-
textarea.editor?.setValue(code);
|
|
243
|
-
document.getElementById('play-popup').classList.add('show');
|
|
244
|
-
},
|
|
245
|
-
'@close-popup': () => { document.getElementById('play-popup').classList.remove('show') },
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
app.webComponent('apprun-play', Play);
|