apprun 4.0.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +235 -12
  2. package/LICENSE +1 -1
  3. package/README.md +225 -110
  4. package/apprun.d.ts +240 -34
  5. package/cli/app.js +29 -0
  6. package/cli/colors.js +69 -0
  7. package/cli/index.html +13 -0
  8. package/cli/index.js +96 -0
  9. package/dist/apprun-code.js +2 -0
  10. package/dist/apprun-code.js.map +1 -0
  11. package/dist/apprun-dev-tools.js +1 -1
  12. package/dist/apprun-dev-tools.js.map +1 -1
  13. package/dist/apprun-html.esm.js +34 -0
  14. package/dist/apprun-html.esm.js.map +1 -0
  15. package/dist/apprun-html.js +2 -1
  16. package/dist/apprun-html.js.LICENSE.txt +11 -0
  17. package/dist/apprun-html.js.map +1 -1
  18. package/dist/apprun-play.js +2 -0
  19. package/dist/apprun-play.js.map +1 -0
  20. package/dist/apprun.esm.js +2 -0
  21. package/dist/apprun.esm.js.map +1 -0
  22. package/dist/apprun.js +1 -1
  23. package/dist/apprun.js.map +1 -1
  24. package/dist/createState.js +2 -0
  25. package/dist/createState.js.map +1 -0
  26. package/esm/add-components.js +90 -0
  27. package/esm/add-components.js.map +1 -0
  28. package/esm/app.js +209 -0
  29. package/esm/app.js.map +1 -0
  30. package/esm/apprun-code.js +170 -0
  31. package/esm/apprun-code.js.map +1 -0
  32. package/esm/apprun-dev-tools-tests.js +95 -0
  33. package/esm/apprun-dev-tools-tests.js.map +1 -0
  34. package/esm/apprun-dev-tools.js +281 -0
  35. package/esm/apprun-dev-tools.js.map +1 -0
  36. package/esm/apprun-html.js +24 -0
  37. package/esm/apprun-html.js.map +1 -0
  38. package/esm/apprun-play.js +248 -0
  39. package/esm/apprun-play.js.map +1 -0
  40. package/esm/apprun.js +220 -0
  41. package/esm/apprun.js.map +1 -0
  42. package/esm/component.js +413 -0
  43. package/esm/component.js.map +1 -0
  44. package/esm/createState.js +9 -0
  45. package/esm/createState.js.map +1 -0
  46. package/esm/decorator.js +88 -0
  47. package/esm/decorator.js.map +1 -0
  48. package/esm/directive.js +306 -0
  49. package/esm/directive.js.map +1 -0
  50. package/esm/router.js +345 -0
  51. package/esm/router.js.map +1 -0
  52. package/esm/type-utils.js +90 -0
  53. package/esm/type-utils.js.map +1 -0
  54. package/esm/types.js +58 -0
  55. package/esm/types.js.map +1 -0
  56. package/esm/vdom-lit-html.js +65 -0
  57. package/esm/vdom-lit-html.js.map +1 -0
  58. package/esm/vdom-my-prop-attr.js +227 -0
  59. package/esm/vdom-my-prop-attr.js.map +1 -0
  60. package/esm/vdom-my.js +293 -0
  61. package/esm/vdom-my.js.map +1 -0
  62. package/esm/vdom-to-html.js +54 -0
  63. package/esm/vdom-to-html.js.map +1 -0
  64. package/esm/vdom.js +28 -0
  65. package/esm/vdom.js.map +1 -0
  66. package/esm/version.js +15 -0
  67. package/esm/version.js.map +1 -0
  68. package/esm/web-component.js +155 -0
  69. package/esm/web-component.js.map +1 -0
  70. package/jsx-runtime.js +2 -0
  71. package/jsx-runtime.js.map +1 -0
  72. package/package.json +90 -41
  73. package/.travis.yml +0 -10
  74. package/.vscode/launch.json +0 -19
  75. package/BACKERS.md +0 -3
  76. package/apprun-cli.js +0 -177
  77. package/cli-templates/_gitignore +0 -6
  78. package/cli-templates/component.ts_ +0 -16
  79. package/cli-templates/index.html +0 -11
  80. package/cli-templates/karma.conf.js +0 -24
  81. package/cli-templates/main.ts_ +0 -13
  82. package/cli-templates/readme.md +0 -7
  83. package/cli-templates/spa_index.html +0 -14
  84. package/cli-templates/spa_main.ts_ +0 -47
  85. package/cli-templates/spec.ts_ +0 -11
  86. package/cli-templates/tsconfig.json +0 -12
  87. package/cli-templates/webpack.config.js +0 -23
  88. package/demo-html/app.js +0 -2
  89. package/demo-html/app.js.map +0 -1
  90. package/demo-html/counter-c.html +0 -29
  91. package/demo-html/counter-wc-event.html +0 -29
  92. package/demo-html/counter-wc.html +0 -29
  93. package/demo-html/counter.html +0 -26
  94. package/demo-html/index.html +0 -14
  95. package/demo-html/main.tsx +0 -31
  96. package/docs/README.md +0 -326
  97. package/docs/index.html +0 -23
  98. package/index.html +0 -85
  99. package/logo.png +0 -0
  100. package/src/app.ts +0 -69
  101. package/src/apprun-dev-tools.tsx +0 -67
  102. package/src/apprun-html.ts +0 -13
  103. package/src/apprun.ts +0 -53
  104. package/src/component.ts +0 -189
  105. package/src/createComponent.tsx +0 -38
  106. package/src/decorator.ts +0 -36
  107. package/src/router.ts +0 -19
  108. package/src/types.ts +0 -9
  109. package/src/vdom-html.ts +0 -17
  110. package/src/vdom-my.ts +0 -191
  111. package/src/vdom-to-html.tsx +0 -45
  112. package/src/vdom.ts +0 -7
  113. package/src/web-component.ts +0 -29
  114. package/tests/app-rx.spec_ +0 -41
  115. package/tests/app.spec.ts +0 -122
  116. package/tests/application.spec.tsx +0 -23
  117. package/tests/component.spec.tsx +0 -296
  118. package/tests/custom-element.spec.tsx +0 -19
  119. package/tests/data-attr.spec.tsx +0 -42
  120. package/tests/decorator.spec.tsx +0 -104
  121. package/tests/fragment.spec.tsx +0 -79
  122. package/tests/hyperscript.spec.ts +0 -43
  123. package/tests/node-test.js +0 -7
  124. package/tests/router.spec.ts +0 -69
  125. package/tests/stateful-component.spec.tsx +0 -248
  126. package/tests/typed.spec.tsx +0 -63
  127. package/tests/vdom-html.spec.ts +0 -35
  128. package/tests/vdom-jsx.spec.tsx +0 -131
  129. package/tests/vdom-my.spec.tsx +0 -195
  130. package/tests/view-engine.spec.js +0 -59
  131. package/tsconfig.json +0 -11
  132. package/tslint.json +0 -124
  133. package/typescriptreact.json +0 -87
  134. package/viewEngine.js +0 -54
  135. package/webpack.config.js +0 -30
package/src/component.ts DELETED
@@ -1,189 +0,0 @@
1
-
2
- import app, { App } from './app';
3
- import { Reflect } from './decorator'
4
- import { VNode, View, Update } from './types';
5
-
6
- const componentCache = {};
7
- app.on('get-components', o => o.components = componentCache);
8
-
9
- export class Component<T=any> {
10
- static __isAppRunComponent = true;
11
- private _app = new App();
12
- private _actions = [];
13
- element;
14
- private _history = [];
15
- private _history_idx = -1;
16
- private enable_history;
17
- private global_event;
18
- public rendered;
19
- public mounted;
20
-
21
- private renderState(state: T) {
22
- if (!this.view) return;
23
- const html = this.view(state);
24
-
25
- app.run('debug', {
26
- component: this,
27
- state,
28
- vdom: html || '[vdom is null - no render]',
29
- });
30
-
31
- if (typeof document !== 'object') return;
32
-
33
- const el = (typeof this.element === 'string') ?
34
- document.getElementById(this.element) : this.element;
35
- if (el) el['_component'] = this;
36
- app.render(el, html, this);
37
- if (this.rendered) (this.rendered(this.state));
38
- }
39
-
40
- public setState(state: T, options: { render: boolean, history: boolean, callback?}
41
- = { render: true, history: false}) {
42
- if (state instanceof Promise) {
43
- // Promise will not be saved or rendered
44
- // state will be saved and rendered when promise is resolved
45
- state.then(s => {
46
- this.setState(s, options)
47
- }).catch(err => {
48
- console.error(err);
49
- throw err;
50
- });
51
- this.state = state;
52
- } else {
53
- if (state == null) return;
54
- this.state = state;
55
- if (options.render !== false) this.renderState(state);
56
- if (options.history !== false && this.enable_history) {
57
- this._history = [...this._history, state];
58
- this._history_idx = this._history.length - 1;
59
- }
60
- if (typeof options.callback === 'function') options.callback(this.state);
61
- }
62
- }
63
-
64
- constructor(
65
- protected state?: T,
66
- protected view?: View<T>,
67
- protected update?: Update<T>,
68
- protected options?) {
69
- }
70
-
71
- start = (element = null,
72
- options: { render?: boolean, history?, global_event?: boolean } = { render: true }): Component<T> => {
73
- return this.mount(element, { ...options, render: true });
74
- }
75
-
76
- public mount(element = null, options?: { render?: boolean, history?, global_event?: boolean}) {
77
-
78
- console.assert(!this.element, 'Component already mounted.')
79
- this.options = options = Object.assign(this.options || {}, options);
80
- this.element = element;
81
- this.global_event = options.global_event;
82
- this.enable_history = !!options.history;
83
-
84
- if (this.enable_history) {
85
- const prev = () => {
86
- this._history_idx --;
87
- if (this._history_idx >=0) {
88
- this.setState(this._history[this._history_idx], { render: true, history: false });
89
- }
90
- else {
91
- this._history_idx = 0;
92
- }
93
- };
94
-
95
- const next = () => {
96
- this._history_idx ++;
97
- if (this._history_idx < this._history.length) {
98
- this.setState(this._history[this._history_idx], { render: true, history: false });
99
- }
100
- else {
101
- this._history_idx = this._history.length - 1;
102
- }
103
- };
104
- this.on(options.history.prev || 'history-prev', prev)
105
- this.on(options.history.next || 'history-next', next)
106
- }
107
- this.add_actions();
108
- if (this.state === undefined) this.state = this['model'] || {};
109
- if (options.render) {
110
- this.setState(this.state, { render: true, history: true });
111
- } else {
112
- this.setState(this.state, { render: false, history: true });
113
- }
114
-
115
- componentCache[element] = componentCache[element] || [];
116
- componentCache[element].push(this);
117
- return this;
118
- }
119
-
120
- is_global_event(name: string): boolean {
121
- return name && (name.startsWith('#') || name.startsWith('/'));
122
- }
123
-
124
- add_action(name: string, action, options: any = {}) {
125
- if (!action || typeof action !== 'function') return;
126
- this.on(name, (...p) => {
127
- const newState = action(this.state, ...p);
128
-
129
- app.run('debug', {
130
- component: this,
131
- 'event': name,
132
- e: p,
133
- state: this.state,
134
- newState,
135
- options
136
- })
137
-
138
- this.setState(newState, options)
139
- }, options);
140
- }
141
-
142
- add_actions() {
143
- const actions = this.update || {};
144
- Reflect.getMetadataKeys(this).forEach(key => {
145
- if (key.startsWith('apprun-update:')) {
146
- const meta = Reflect.getMetadata(key, this)
147
- actions[meta.name] = [this[meta.key].bind(this), meta.options];
148
- }
149
- })
150
- const all = {};
151
- Object.keys(actions).forEach(name => {
152
- const action = actions[name];
153
- if (typeof action === 'function' || Array.isArray(action)) {
154
- name.split(',').forEach(n => all[n.trim()] = action)
155
- }
156
- })
157
-
158
- Object.keys(all).forEach(name => {
159
- const action = all[name];
160
- if (typeof action === 'function') {
161
- this.add_action(name, action);
162
- } else if (Array.isArray(action)) {
163
- this.add_action(name, action[0], action[1]);
164
- }
165
- });
166
- }
167
-
168
- public run(name: string, ...args) {
169
- return this.global_event || this.is_global_event(name) ?
170
- app.run(name, ...args) :
171
- this._app.run(name, ...args);
172
- }
173
-
174
- public on(name: string, fn: (...args) => void, options?: any) {
175
- this._actions.push({ name, fn });
176
- return this.global_event || this.is_global_event(name) ?
177
- app.on(name, fn, options) :
178
- this._app.on(name, fn, options);
179
- }
180
-
181
- public unmount() {
182
- this._actions.forEach(action => {
183
- const { name, fn } = action;
184
- this.global_event || this.is_global_event(name) ?
185
- app.off(name, fn) :
186
- this._app.off(name, fn);
187
- });
188
- }
189
- }
@@ -1,38 +0,0 @@
1
- import app from './app';
2
-
3
- function render(node, parent, idx) {
4
- const { tag, props, children } = node;
5
-
6
- let id = props && props['id'];
7
- let key = `_${tag.name}_${idx}`
8
- if (!id) {
9
- id = `_${tag.name}_${idx}`;
10
- } else {
11
- key = `_${tag.name}_${id}`;
12
- }
13
-
14
- if (!parent.__componentCache) parent.__componentCache = {};
15
- let component = parent.__componentCache[key];
16
- if (!component) {
17
- component = parent.__componentCache[key] = new tag({ ...props, children }).mount(id);
18
- }
19
- component.mounted && component.mounted(props, children);
20
- const state = component.state;
21
- let vdom = '';
22
- if (!(state instanceof Promise) && component.view) {
23
- vdom = component.view(state);
24
- component.rendered && component.rendered(state);
25
- }
26
- return <div id={id}>{vdom}</div>;
27
- }
28
-
29
- function createComponent(node, parent, idx = 0) {
30
- if (typeof node === 'string') return node;
31
- if (Array.isArray(node)) return node.map(child => createComponent(child, parent, idx++));
32
- let vdom = node;
33
- if (node && node.tag && Object.getPrototypeOf(node.tag).__isAppRunComponent) vdom = render(node, parent, idx++);
34
- if (vdom && vdom.children) vdom.children = vdom.children.map(child => createComponent(child, parent, idx++));
35
- return vdom;
36
- }
37
-
38
- export default createComponent;
package/src/decorator.ts DELETED
@@ -1,36 +0,0 @@
1
- export const Reflect = {
2
-
3
- meta: new WeakMap(),
4
-
5
- defineMetadata(metadataKey, metadataValue, target) {
6
- if (!this.meta.has(target)) this.meta.set(target, {});
7
- this.meta.get(target)[metadataKey] = metadataValue;
8
- },
9
-
10
- getMetadataKeys(target) {
11
- target = Object.getPrototypeOf(target);
12
- return this.meta.get(target) ? Object.keys(this.meta.get(target)) : [];
13
- },
14
-
15
- getMetadata(metadataKey, target) {
16
- target = Object.getPrototypeOf(target);
17
- return this.meta.get(target) ? this.meta.get(target)[metadataKey] : null;
18
- }
19
- }
20
-
21
- export function update(name?: string, options: any = {}) {
22
- return (target: any, key: string, descriptor: any) => {
23
- name = name || key;
24
- Reflect.defineMetadata(`apprun-update:${name}`,
25
- { name, key, options }, target);
26
- return descriptor;
27
- }
28
- }
29
-
30
- export function on(name?: string, options: any = {}) {
31
- return function (target: any, key: string) {
32
- name = name || key;
33
- Reflect.defineMetadata(`apprun-update:${name}`,
34
- { name, key, options }, target)
35
- }
36
- }
package/src/router.ts DELETED
@@ -1,19 +0,0 @@
1
- import app from './app';
2
-
3
- const ROUTER_EVENT = '//';
4
-
5
- export default function route(url: string) {
6
- if (!url) url = '#';
7
- if (url.startsWith('#')) {
8
- const [name, ...rest] = url.split('/');
9
- app.run(name, ...rest);
10
- app.run(ROUTER_EVENT, name, ...rest);
11
- } else if (url.startsWith('/')) {
12
- const [_, name, ...rest] = url.split('/');
13
- app.run('/' + name, ...rest);
14
- app.run(ROUTER_EVENT, '/' + name, ...rest);
15
- } else {
16
- app.run(url);
17
- app.run(ROUTER_EVENT, url);
18
- }
19
- }
package/src/types.ts DELETED
@@ -1,9 +0,0 @@
1
- export type VNode = {
2
- tag: string | Function,
3
- props: {},
4
- children: Array<VNode|string>
5
- }
6
- export type VDOM = string | VNode | Array<VNode | string>;
7
- export type View<T> = (state: T) => VDOM | void;
8
- export type Action<T> = (state: T, ...p: any[]) => T | Promise<T>;
9
- export type Update<T> = { [name: string]: Action<T> | {}[] | void; };
package/src/vdom-html.ts DELETED
@@ -1,17 +0,0 @@
1
- import { createElement, updateElement, Fragment } from './vdom-my';
2
- import * as morphdom from 'morphdom';
3
-
4
- export function render(element, html, parent?) {
5
- if (typeof html === 'string') {
6
- html = html.trim();
7
- if (element.firstChild) {
8
- morphdom(element.firstChild, html);
9
- } else {
10
- element.innerHTML = html;
11
- }
12
- } else {
13
- updateElement(element, html, parent);
14
- }
15
- }
16
- export { createElement, Fragment };
17
-
package/src/vdom-my.ts DELETED
@@ -1,191 +0,0 @@
1
- import createComponent from './createComponent';
2
- import { VNode } from './types';
3
- export type Element = any; //HTMLElement | SVGSVGElement | SVGElement;
4
-
5
- const ATTR_PROPS = '_props';
6
-
7
- function collect(children) {
8
- const ch = [];
9
- const push = (c) => {
10
- if (c !== null && c !== undefined && c !== '' && c !== false) {
11
- ch.push((typeof c === 'function' || typeof c === 'object') ? c : `${c}`);
12
- }
13
- }
14
- children && children.forEach(c => {
15
- if (Array.isArray(c)) {
16
- c.forEach(i => push(i));
17
- } else {
18
- push(c);
19
- }
20
- });
21
- return ch;
22
- }
23
-
24
- export function createElement (tag: string | Function, props: {}, ...children) {
25
- const ch = collect(children);
26
- if (typeof tag === 'string') return { tag, props, children: ch };
27
- else if (tag === undefined && children) return ch; // JSX fragments
28
- else if (Object.getPrototypeOf(tag).__isAppRunComponent) {
29
- return { tag, props, children:ch } // createComponent(tag, { ...props, children });
30
- }
31
- else
32
- return tag(props, ch);
33
- };
34
-
35
- const keyCache = {};
36
-
37
- export const updateElement = render;
38
-
39
- export function render(element: Element, nodes: VNode | VNode[], parent = {}) {
40
- // console.log('render', element, node);
41
- if (nodes == null) return;
42
-
43
- nodes = createComponent(nodes, parent);
44
-
45
- if (!element) return;
46
- if (Array.isArray(nodes)) {
47
- updateChildren(element, nodes);
48
- } else {
49
- const node = nodes;
50
- if (!element.firstChild) {
51
- element.appendChild(create(node));
52
- } else {
53
- update(element.firstChild, node);
54
- }
55
- }
56
- }
57
-
58
- function same(el: Element, node: VNode) {
59
- // if (!el || !node) return false;
60
- const key1 = el.nodeName;
61
- const key2 = `${node.tag || ''}`;
62
- return key1 === key2.toUpperCase();
63
- }
64
-
65
- function update(element: Element, node: VNode) {
66
- console.assert(!!element);
67
- //console.log('update', element, node);
68
- if (!same(element, node)) {
69
- element.parentNode.replaceChild(create(node), element);
70
- return;
71
- }
72
- updateChildren(element, node.children);
73
- updateProps(element, node.props);
74
- }
75
-
76
- function updateChildren(element, children) {
77
- const len = Math.min(element.childNodes.length, children.length);
78
- for (let i = 0; i < len; i++) {
79
- const child = children[i];
80
- const el = element.childNodes[i];
81
- if (typeof child === 'string') {
82
- if (el.textContent !== child) {
83
- if (el.nodeType === 3) {
84
- el.textContent = child
85
- } else {
86
- element.replaceChild(createText(child), el);
87
- }
88
- }
89
- } else {
90
- const key = child.props && child.props['key'];
91
- if (key) {
92
- if (el.key === key) {
93
- update(element.childNodes[i], child);
94
- } else {
95
- const old = key && keyCache[key];
96
- if (old) {
97
- element.replaceChild(old, el);
98
- element.appendChild(el);
99
- update(element.childNodes[i], child);
100
- } else {
101
- element.appendChild(create(child), el);
102
- update(element.childNodes[i], child);
103
- }
104
- }
105
- } else {
106
- update(element.childNodes[i], child);
107
- }
108
- }
109
- }
110
-
111
- let n = element.childNodes.length;
112
- while (n > len) {
113
- element.removeChild(element.lastChild);
114
- n--;
115
- }
116
-
117
- if (children.length > len) {
118
- const d = document.createDocumentFragment();
119
- for (let i = len; i < children.length; i++) {
120
- d.appendChild(create(children[i]));
121
- }
122
- element.appendChild(d);
123
- }
124
- }
125
-
126
- function createText(node) {
127
- if (node.indexOf('_html:') === 0) { // ?
128
- const div = document.createElement('div');
129
- div.insertAdjacentHTML('afterbegin', node.substring(6))
130
- return div;
131
- } else {
132
- return document.createTextNode(node);
133
- }
134
- }
135
-
136
- function create(node: VNode | string): Element {
137
- console.assert(node !== null && node !== undefined);
138
- // console.log('create', node, typeof node);
139
-
140
- if (typeof node === "string") return createText(node);
141
- if (!node.tag || (typeof node.tag == 'function')) return createText(JSON.stringify(node));
142
-
143
- const element = (node.tag === "svg")
144
- ? document.createElementNS("http://www.w3.org/2000/svg", node.tag)
145
- : document.createElement(node.tag);
146
-
147
- updateProps(element, node.props);
148
-
149
- if (node.children) node.children.forEach(child => element.appendChild(create(child)));
150
-
151
- return element
152
- }
153
-
154
- function mergeProps(a: {}, b: {}): {} {
155
- const props = {};
156
- if (a) Object.keys(a).forEach(p => props[p] = '');
157
- if (b) Object.keys(b).forEach(p => props[p] = b[p]);
158
- return props;
159
- }
160
-
161
- function updateProps(element: Element, props: {}) {
162
- console.assert(!!element);
163
- // console.log('updateProps', element, props);
164
-
165
- const cached = element[ATTR_PROPS] || {};
166
- props = mergeProps(cached, props);
167
- element[ATTR_PROPS] = props;
168
- for (let name in props) {
169
- const value = props[name];
170
- // if (cached[name] === value) continue;
171
- // console.log('updateProps', name, value);
172
- if (name === 'style') {
173
- if (element.style.cssText) element.style.cssText = '';
174
- for (let s in value) {
175
- if (element.style[s] !== value[s]) element.style[s] = value[s];
176
- }
177
- } else if (name.startsWith('data-')) {
178
- const dname = name.substring(5);
179
- if (element.dataset[dname] !== value) element.dataset[dname] = value;
180
- } else if (name.startsWith("role") || name.startsWith("aria-")) {
181
- if (element.getAttribute(name) !== value) element.setAttribute(name, value)
182
- } else {
183
- if (element[name] !== value) element[name] = value;
184
- if (name === 'key' && value) keyCache[value] = element;
185
- }
186
- }
187
- }
188
-
189
- export function Fragment(props, ...children): any[] {
190
- return collect(children);
191
- }
@@ -1,45 +0,0 @@
1
-
2
- import { VDOM } from './types';
3
-
4
- function getProp(prop) {
5
- if (typeof prop === 'object') {
6
- return Object.keys(prop).map(name => `${name}:${prop[name]}`).join(';');
7
- }
8
- else return prop.toString();
9
- }
10
-
11
- function toProps(props) {
12
- return Object.keys(props)
13
- .map(name => ` ${name === 'className' ? 'class' : name}="${getProp(props[name])}"`)
14
- .join('');
15
- }
16
-
17
- function toHTMLArray(nodes) {
18
- return nodes.map(node => toHTML(node)).join('');
19
- }
20
-
21
- function clean(obj) {
22
- for (var i in obj) {
23
- if (obj[i] == null) {
24
- delete obj[i];
25
- } else if (typeof obj[i] === 'object') {
26
- clean(obj[i]);
27
- }
28
- }
29
- }
30
-
31
- function toHTML (vdom: VDOM) {
32
- if (!vdom) return '';
33
- clean(vdom);
34
- if (Array.isArray(vdom)) return toHTMLArray(vdom);
35
- if (typeof vdom === 'string') {
36
- return vdom.startsWith('_html:') ? vdom.substring(6) : vdom;
37
- } else if (vdom.tag) {
38
- const props = vdom.props ? toProps(vdom.props) : '';
39
- const children = vdom.children ? toHTMLArray(vdom.children) : '';
40
- return `<${vdom.tag}${props}>${children}</${vdom.tag}>`;
41
- }
42
- if (typeof vdom === 'object') return JSON.stringify(vdom);
43
- }
44
-
45
- export default toHTML;
package/src/vdom.ts DELETED
@@ -1,7 +0,0 @@
1
- import { createElement, updateElement, Fragment } from './vdom-my';
2
- export function render(element, html, parent?) {
3
- updateElement(element, html, parent);
4
- }
5
- export { createElement, Fragment };
6
-
7
-
@@ -1,29 +0,0 @@
1
- import { Component } from './component';
2
- declare var customElements;
3
-
4
- export const customElement = (componentClass, options={}) => class extends HTMLElement {
5
- private _shadowRoot;
6
- private _component;
7
- public on;
8
- public run;
9
- constructor() {
10
- super();
11
- const opts = { render: true, shadow: false, ...options };
12
- this._shadowRoot = opts.shadow ?
13
- this.attachShadow({ mode: 'open' }) : this;
14
- const props = {}
15
- Array.from(this.attributes).forEach(item => props[item.name] = item.value);
16
- if (this.children) {
17
- props['children'] = Array.from(this.children);
18
- props['children'].forEach(el => el.parentElement.removeChild(el));
19
- }
20
- this._component = new componentClass(props).mount(this._shadowRoot, opts);
21
- this.on = this._component.on.bind(this._component);
22
- this.run = this._component.run.bind(this._component);
23
- }
24
- get state() { return this._component.state; }
25
- }
26
-
27
- export default (name: string, componentClass, options?) => {
28
- customElements && customElements.define(name, customElement(componentClass, options))
29
- }
@@ -1,41 +0,0 @@
1
- import {App} from '../src/app';
2
-
3
- describe('app', () => {
4
-
5
- let app: App;
6
- beforeEach(() => app = new App());
7
-
8
- it ('should be able to cancel subscription', () => {
9
- let called = false;
10
- const fn = () => (called = true);
11
- const subscription: any = app.on('test', fn);
12
- subscription.unsubscribe();
13
- app.run('test');
14
- expect(called).toBeFalsy();
15
- });
16
-
17
- it ('should be able to return Observable<{}> from app.on', (done) => {
18
- let called = false;
19
- const subject:any = app.on('test');
20
- subject.debounceTime(200).subscribe(()=> called = true);
21
- app.run('test');
22
- expect(called).toBeFalsy();
23
- setTimeout(() => {
24
- expect(called).toBeTruthy();
25
- done();
26
- }, 250);
27
- });
28
-
29
- it ('should be able to return Subject<{}> from app.run', () => {
30
- let i=0, j=0
31
- const fn = () => {i++};
32
- const subscription: any = app.on('test', fn)
33
- const subject = app.run('test');
34
- subscription.unsubscribe();
35
- subject.subscribe(() => j++);
36
- subject.next();
37
- expect(i).toEqual(1);
38
- expect(j).toEqual(1);
39
- });
40
-
41
- });