-
Notifications
You must be signed in to change notification settings - Fork 8
/
riot-ts.ts
161 lines (134 loc) · 4.52 KB
/
riot-ts.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import * as riot from "riot/riot+compiler";
export class Observable {
on(events: string, callback: Function) {}
one(events: string, callback: Function) {}
off(events: string) {}
trigger(eventName: string, ...args) {}
constructor() {
riot.observable(this);
}
}
export interface LifeCycle
{
mounted?(F: Function);
unmounted?(F: Function);
updating?(F: Function);
updated?(F: Function);
}
export interface HTMLRiotElement extends HTMLElement
{
_tag: Element;
}
export class Element implements Observable, LifeCycle {
opts: any;
parent: Element;
root: HTMLElement;
tags: any;
tagName: string;
template: string;
isMounted: boolean;
update(data?: any) { }
unmount(keepTheParent?: boolean) { }
on(eventName: string,fun: Function) { }
one(eventName: string,fun: Function) { }
off(events: string) {}
trigger(eventName: string,...args) {}
mixin(mixinObject: Object|Function|string, instance?: any) {}
static createElement(options?:any): HTMLRiotElement {
var tagName = (this.prototype as any).tagName;
var el = document.createElement(tagName);
riot.mount(el, tagName, options);
return el as any as HTMLRiotElement;
}
}
// new extend, works with getters and setters
function extend(d, element) {
var map = Object.keys(element.prototype).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(element.prototype, key);
return descriptors;
},{}) as PropertyDescriptorMap;
Object.defineProperties(d, map);
}
/* old extend, without getters and setters
function extend(d, element) {
Object.keys(element.prototype).forEach((key) => d[key] = element.prototype[key]);
}
*/
export var precompiledTags: { [fileName: string]: CompilerResult } = {};
export function registerClass(element: Function) {
function registerTag(compiledTag: CompilerResult) {
var transformFunction = function (opts) {
extend(this,element); // copies prototype into "this"
element.apply(this, [opts]); // calls class constructor applying it on "this"
if(element.prototype.mounted !== undefined) this.on("mount" , this.mounted);
if(element.prototype.unmounted !== undefined) this.on("unmount" , this.unmounted);
if(element.prototype.updating !== undefined) this.on("update" , this.updating);
if(element.prototype.updated !== undefined) this.on("updated" , this.updated);
// TODO support for init(opts) ?
};
riot.tag2(compiledTag.tagName, compiledTag.html, compiledTag.css, compiledTag.attribs, transformFunction, riot.settings.brackets);
return compiledTag.tagName;
}
function loadTemplateFromHTTP(template) {
var req = new XMLHttpRequest();
req.open("GET", template, false);
req.send();
if (req.status == 200) return req.responseText;
else throw req.responseText;
};
let compiled: CompilerResult;
// gets string template: inlined, via http request or via precompiled cache
if(element.prototype.template !== undefined) {
let tagTemplate = element.prototype.template;
if(tagTemplate.indexOf("<")<0) {
// tag is a file
if(precompiledTags[tagTemplate]!==undefined)
{
// loads it from precompiled cache
compiled = precompiledTags[tagTemplate];
}
else
{
// loads from HTTP and compile on the fly
tagTemplate = loadTemplateFromHTTP(tagTemplate);
compiled = riot.compile(tagTemplate, true, {entities: true})[0];
}
}
else
{
// tag is inlined, compile on the fly
compiled = riot.compile(tagTemplate, true, {entities: true})[0];
}
element.prototype.tagName = registerTag(compiled);
}
else throw "template property not specified";
}
// @template decorator
export function template(template: string) {
return function(target: Function) {
target.prototype["template"] = template;
registerClass(target);
}
}
export interface Router {
(callback: Function): void;
(filter: string, callback: Function): void;
(to: string, title?: string): void;
create(): Router;
start(autoExec?: boolean): void;
stop(): void;
exec(): void;
query(): any;
base(base: string): any;
parser(parser: (path: string)=>string, secondParser?: Function ): any;
}
export interface CompilerResult {
tagName: string;
html: string;
css: string;
attribs: string;
js: string;
}
export interface Settings {
brackets: string;
}