@makano/rew 1.3.0 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/rew/modules/compiler.js +13 -19
- package/lib/rew/pkgs/serve.js +4 -3
- package/lib/rew/pkgs/web.js +109 -5
- package/package.json +1 -1
- package/runtime.d.ts +13 -10
@@ -27,24 +27,21 @@ function tokenizeCoffeeScript(code) {
|
|
27
27
|
const nextNextChar = code[i + 2];
|
28
28
|
|
29
29
|
if (char === '#') {
|
30
|
-
// Comment
|
31
30
|
const commentEnd = code.indexOf('\n', i);
|
32
31
|
const comment = code.substring(i, commentEnd < 0 ? code.length : commentEnd + 1);
|
33
32
|
tokens.push({ type: 'COMMENT', value: comment });
|
34
33
|
i += comment.length - 1;
|
35
34
|
} else if (char === '"' && nextChar === '"' && nextNextChar === '"') {
|
36
|
-
// Triple-quoted string
|
37
35
|
let string = '"""';
|
38
36
|
i += 3;
|
39
37
|
while (i < code.length && !(code[i] === '"' && code[i + 1] === '"' && code[i + 2] === '"')) {
|
40
38
|
string += code[i];
|
41
39
|
i++;
|
42
40
|
}
|
43
|
-
string += '"""';
|
41
|
+
string += '"""';
|
44
42
|
tokens.push({ type: 'TRIPLE_STRING', value: string });
|
45
|
-
i += 2;
|
43
|
+
i += 2;
|
46
44
|
} else if (char === '"' || char === "'") {
|
47
|
-
// Single or double-quoted string
|
48
45
|
let string = char;
|
49
46
|
let escaped = false;
|
50
47
|
i++;
|
@@ -57,10 +54,9 @@ function tokenizeCoffeeScript(code) {
|
|
57
54
|
}
|
58
55
|
i++;
|
59
56
|
}
|
60
|
-
string += char;
|
57
|
+
string += char;
|
61
58
|
tokens.push({ type: 'STRING', value: string });
|
62
59
|
} else if (char === '/' && nextChar !== ' ' && nextChar !== '/' && nextChar !== '*' && prevChar !== '<') {
|
63
|
-
// Regular expression
|
64
60
|
let regex = char;
|
65
61
|
i++;
|
66
62
|
while (i < code.length && (code[i] !== '/' || regex.endsWith('\\'))) {
|
@@ -70,14 +66,12 @@ function tokenizeCoffeeScript(code) {
|
|
70
66
|
regex += '/';
|
71
67
|
tokens.push({ type: 'REGEX', value: regex });
|
72
68
|
} else if (/\s/.test(char)) {
|
73
|
-
// Whitespace
|
74
69
|
if (tokens[tokens.length - 1]?.type === 'WHITESPACE') {
|
75
70
|
tokens[tokens.length - 1].value += char;
|
76
71
|
} else {
|
77
72
|
tokens.push({ type: 'WHITESPACE', value: char });
|
78
73
|
}
|
79
74
|
} else if (/[a-zA-Z_$@]/.test(char)) {
|
80
|
-
// Identifier
|
81
75
|
let identifier = char;
|
82
76
|
i++;
|
83
77
|
while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) {
|
@@ -85,18 +79,17 @@ function tokenizeCoffeeScript(code) {
|
|
85
79
|
i++;
|
86
80
|
}
|
87
81
|
tokens.push({ type: 'IDENTIFIER', value: identifier });
|
88
|
-
i--;
|
89
|
-
} else if (/[a-f0-9.
|
82
|
+
i--;
|
83
|
+
} else if (/[a-f0-9.xn]/.test(char)) {
|
90
84
|
let num = char;
|
91
85
|
i++;
|
92
|
-
while (i < code.length && /[a-f0-9.
|
86
|
+
while (i < code.length && /[a-f0-9.nx]/.test(code[i])) {
|
93
87
|
num += code[i];
|
94
88
|
i++;
|
95
89
|
}
|
96
90
|
tokens.push({ type: 'NUMBER', value: num });
|
97
|
-
i--;
|
91
|
+
i--;
|
98
92
|
} else {
|
99
|
-
// Other characters
|
100
93
|
tokens.push({ type: 'OTHER', value: char });
|
101
94
|
}
|
102
95
|
i++;
|
@@ -397,12 +390,12 @@ function compileRewStuff(content, options) {
|
|
397
390
|
}
|
398
391
|
|
399
392
|
|
400
|
-
if (token.type === 'IDENTIFIER' && token.value === 'export' && !options.keepImports) {
|
393
|
+
if (tokens[i-1]?.value !== '.' && token.type === 'IDENTIFIER' && token.value === 'export' && !options.keepImports) {
|
401
394
|
token.value = 'pub';
|
402
395
|
straceLog('EXPORT() => TRANSLATING TO pub');
|
403
396
|
}
|
404
397
|
|
405
|
-
if (token.type === 'IDENTIFIER' && token.value === 'package' && nextToken.type == 'STRING') {
|
398
|
+
if (tokens[i-1]?.value !== '.' && token.type === 'IDENTIFIER' && token.value === 'package' && nextToken.type == 'STRING') {
|
406
399
|
token.value = 'appPackage';
|
407
400
|
straceLog('APP_PACKAGE_CHANGE()');
|
408
401
|
}
|
@@ -421,7 +414,7 @@ function compileRewStuff(content, options) {
|
|
421
414
|
}
|
422
415
|
}
|
423
416
|
|
424
|
-
if (token.type === 'IDENTIFIER' && token.value === 'using' && !options.disableUse) {
|
417
|
+
if (tokens[i-1]?.value !== '.' && token.type === 'IDENTIFIER' && token.value === 'using' && !options.disableUse) {
|
425
418
|
straceLog('USING()');
|
426
419
|
const next = nextToken.value;
|
427
420
|
if(next in USING_DEFAULT) {
|
@@ -448,7 +441,7 @@ function compileRewStuff(content, options) {
|
|
448
441
|
}
|
449
442
|
}
|
450
443
|
|
451
|
-
if (token.type === 'IDENTIFIER' && token.value === 'import' && !options.keepImports) {
|
444
|
+
if (tokens[i-1]?.value !== '.' && token.type === 'IDENTIFIER' && token.value === 'import' && !options.keepImports) {
|
452
445
|
// console.log(nextToken.type);
|
453
446
|
straceLog('IMPORT()');
|
454
447
|
straceLog('==> WARN: SLOWS DOWN COMPILATION');
|
@@ -539,7 +532,7 @@ function compileRewStuff(content, options) {
|
|
539
532
|
continue;
|
540
533
|
}
|
541
534
|
|
542
|
-
if (token.type === 'IDENTIFIER' && (token.value === 'imp' || token.value === 'inc')) {
|
535
|
+
if (tokens[i-1]?.value !== '.' && token.type === 'IDENTIFIER' && (token.value === 'imp' || token.value === 'inc')) {
|
543
536
|
straceLog('IMP() Detected');
|
544
537
|
let { token: t1 } = gnextToken(i, 1, tokens) || {};
|
545
538
|
let { token: t2 } = gnextToken(i, 2, tokens) || {};
|
@@ -559,6 +552,7 @@ function compileRewStuff(content, options) {
|
|
559
552
|
}
|
560
553
|
|
561
554
|
if (
|
555
|
+
tokens[i-1]?.value !== '.' &&
|
562
556
|
token.type === 'IDENTIFIER' &&
|
563
557
|
token.value === 'pub' &&
|
564
558
|
nextToken &&
|
package/lib/rew/pkgs/serve.js
CHANGED
@@ -166,9 +166,9 @@ module.exports = (context) => {
|
|
166
166
|
|
167
167
|
render = (req, data) ->
|
168
168
|
target = renderers.pop()
|
169
|
-
page = target.render req, data
|
169
|
+
page = target.render.call @, req, data
|
170
170
|
for renderer in renderers
|
171
|
-
page = renderer.render req, data, page
|
171
|
+
page = renderer.render.call @, req, data, page
|
172
172
|
page
|
173
173
|
|
174
174
|
exports { render, staticRendering }
|
@@ -241,7 +241,8 @@ module.exports = (context) => {
|
|
241
241
|
const layouts = findLayoutFiles(file, root, false);
|
242
242
|
const fileContext = runPath(file, { code: ssrBundlerEntry(file, layouts) }).context.module.exports || {};
|
243
243
|
if(typeof fileContext.render !== "function") throw new ReferenceError("Route does not export function render");
|
244
|
-
|
244
|
+
const props = { page, ...getReqProps(req) };
|
245
|
+
let pageContent = fileContext.render.call(props, req, props);
|
245
246
|
if(fileContext.staticRendering) staticRendering = true;
|
246
247
|
if(!w.isNode(pageContent)) throw new TypeError("Route.render does not return an element");
|
247
248
|
if(pageContent?.type?.element == 'head'){
|
package/lib/rew/pkgs/web.js
CHANGED
@@ -245,6 +245,95 @@ function renderToString(element, js = false) {
|
|
245
245
|
return js ? js === 'raw' ? eltJSON : JSON.stringify(eltJSON) : element instanceof TextNode ? `${type.text}` : `<${type.element}${propsString}>${selfClosingElements.has(type.element) ? '' : childrenHTML}${selfClosingElements.has(type.element) ? '' : `</${type.element}>`}`;
|
246
246
|
}
|
247
247
|
|
248
|
+
function createStyles(styles) {
|
249
|
+
let css = "";
|
250
|
+
const variables = {};
|
251
|
+
const mixins = {};
|
252
|
+
|
253
|
+
const parseValue = (v, self, name, vars) => {
|
254
|
+
const vs = {...variables, ...vars, name, ...Object.fromEntries(Object.entries(self).map(i => ['prop_'+i[0], i[1]]))};
|
255
|
+
return v.startsWith('@v') ? vs[v.split('@v')[1].trim()] : v
|
256
|
+
.toString()
|
257
|
+
.replace(/\$([A-Za-z0-9-_]+)/g, (_, name) => (vs)[name])
|
258
|
+
}
|
259
|
+
|
260
|
+
const declectProp = (value, name, selector, start, parent, self, vars = {}) => {
|
261
|
+
let prop = `${name}: `;
|
262
|
+
self.__parent = parent;
|
263
|
+
if (typeof value == 'object') {
|
264
|
+
prop += parseValue(value.default || 'unset', self, name, vars) + ';';
|
265
|
+
prop += '}\n';
|
266
|
+
for (let state in value) {
|
267
|
+
if (state == 'default') continue;
|
268
|
+
else if (state.startsWith('@media')) {
|
269
|
+
prop += `${state} { ${start} ${name}: ${parseValue(value[state], self, name, vars)}; } }\n`
|
270
|
+
} else if (state.startsWith(':')) {
|
271
|
+
prop += `${selector}${state} { ${name}: ${parseValue(value[state], self, name, vars)}; }\n`
|
272
|
+
}
|
273
|
+
}
|
274
|
+
prop += start;
|
275
|
+
} else {
|
276
|
+
let v = parseValue(value, self, name, vars);
|
277
|
+
if(typeof v == 'object') return declectProp(v, name, selector, start, parent, self, vars);
|
278
|
+
prop += v + ';';
|
279
|
+
}
|
280
|
+
return prop;
|
281
|
+
}
|
282
|
+
|
283
|
+
const declectNames = (names, $name, parent, values = {}) => {
|
284
|
+
const start = $name ? $name + ' {' : '';
|
285
|
+
let nameStyles = start;
|
286
|
+
for (let name in names) {
|
287
|
+
let selector = name.replace(/,/g, ', &').replace(/&/g, $name || '');
|
288
|
+
if (name == '@variables') {
|
289
|
+
for (let i in names[name]) {
|
290
|
+
variables[i] = names[name][i];
|
291
|
+
}
|
292
|
+
} else if (name.startsWith('@mixin')) {
|
293
|
+
const mame = name.split('@mixin')[1].trim();
|
294
|
+
const mname = mame.split('(')[0];
|
295
|
+
const args = mame.replace(mname, '').slice(1, -1);
|
296
|
+
mixins[mname] = {
|
297
|
+
args: args.split(','),
|
298
|
+
value: names[name]
|
299
|
+
}
|
300
|
+
} else if (name.startsWith('@keyframes')) {
|
301
|
+
nameStyles += $name ? '' : name + '{';
|
302
|
+
|
303
|
+
for(let keyFrame in names[name]){
|
304
|
+
nameStyles += declectNames(names[name][keyFrame], keyFrame, names[name], values);
|
305
|
+
}
|
306
|
+
|
307
|
+
if(!$name) nameStyles += '}\n';
|
308
|
+
} else if ($name) {
|
309
|
+
if (name.startsWith('&')) {
|
310
|
+
nameStyles += '}\n';
|
311
|
+
nameStyles += declectNames(names[name], selector, names, values);
|
312
|
+
nameStyles += start;
|
313
|
+
} else if(name.startsWith('@include')) {
|
314
|
+
const mame = names[name];
|
315
|
+
const mname = mame.split('(')[0];
|
316
|
+
const args = mame.replace(mname, '').slice(1, -1).split(',');
|
317
|
+
if(mixins[mname]){
|
318
|
+
nameStyles += declectNames(mixins[mname].value, selector, names, {...values, ...Object.fromEntries(mixins[mname].args.map((n, i) => [n, args[i]]))}).trim().replace('@include ', '').slice(1, -1);
|
319
|
+
}
|
320
|
+
} else {
|
321
|
+
nameStyles += declectProp(names[name], name, $name, start, parent || styles, names, values);
|
322
|
+
}
|
323
|
+
} else {
|
324
|
+
nameStyles += declectNames(names[name], selector, names, values);
|
325
|
+
}
|
326
|
+
}
|
327
|
+
if ($name) nameStyles += '}\n';
|
328
|
+
return nameStyles;
|
329
|
+
}
|
330
|
+
|
331
|
+
css += declectNames(styles);
|
332
|
+
|
333
|
+
return css.replace(/(.+) \{\}/g, '');
|
334
|
+
}
|
335
|
+
|
336
|
+
|
248
337
|
class Page extends Node {
|
249
338
|
constructor() {
|
250
339
|
super();
|
@@ -270,6 +359,8 @@ class Page extends Node {
|
|
270
359
|
style(styleString) {
|
271
360
|
if (typeof styleString == "object" && styleString.href)
|
272
361
|
return this.head.add(createElement('link', { href: styleString.href, rel: 'stylesheet' }));
|
362
|
+
else if(typeof styleString == "object")
|
363
|
+
return this.head.add(createElement('style', null, createTextNode(createStyles(styleString))))
|
273
364
|
else
|
274
365
|
return this.head.add(createElement('style', null, createTextNode(styleString)));
|
275
366
|
}
|
@@ -301,13 +392,17 @@ class Page extends Node {
|
|
301
392
|
${State}
|
302
393
|
const states = [];
|
303
394
|
|
395
|
+
function styleAttribute(value, el){
|
396
|
+
for(let i in value){
|
397
|
+
const v = value[i];
|
398
|
+
el.style.setProperty(i, value[i]);
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
304
402
|
function setAttribute(el, key, value){
|
305
403
|
let defVal = value;
|
306
404
|
if(key == 'style'){
|
307
|
-
|
308
|
-
const v = value[i];
|
309
|
-
el.style.setProperty(i, value[i]);
|
310
|
-
}
|
405
|
+
styleAttribute(value, el);
|
311
406
|
return;
|
312
407
|
} else if(key.startsWith('on')){
|
313
408
|
if(!el.listeners) el.listeners = [];
|
@@ -453,12 +548,21 @@ module.exports = (context, importOptions) => {
|
|
453
548
|
createElement(...args) {
|
454
549
|
return createElement(...args);
|
455
550
|
}
|
551
|
+
createStyles(...args){
|
552
|
+
return createStyles(...args);
|
553
|
+
}
|
456
554
|
state(value) {
|
457
555
|
return new State(value);
|
458
556
|
}
|
459
557
|
invokeState(states, callback){
|
460
558
|
const statesMapped = states.map(i => i instanceof State ? `getState('${i.id}')` : (typeof i == "function" ? i.toString() : JSON.stringify(i)));
|
461
|
-
return `((${callback})(event, ...[${statesMapped}]))`;
|
559
|
+
return `((${callback})(typof event !== "undefined" ? event : null, ...[${statesMapped}]))`;
|
560
|
+
}
|
561
|
+
async bundleCode(code, options){
|
562
|
+
return Web.prototype.bundle(generateRandomID(), {
|
563
|
+
...options,
|
564
|
+
code
|
565
|
+
});
|
462
566
|
}
|
463
567
|
async bundle(filepath, options = {}) {
|
464
568
|
const virtualModuleId = `virtual:${filepath}`;
|
package/package.json
CHANGED
package/runtime.d.ts
CHANGED
@@ -500,6 +500,7 @@ declare namespace Rew {
|
|
500
500
|
add(...children: nodable[]): typeof this.body;
|
501
501
|
|
502
502
|
script(script: string): ReturnType<typeof this.add>;
|
503
|
+
style(style: string | Record<string, any>): ReturnType<typeof this.add>;
|
503
504
|
|
504
505
|
serializeState(): string;
|
505
506
|
|
@@ -522,11 +523,13 @@ declare namespace Rew {
|
|
522
523
|
|
523
524
|
createText(text: string): Node;
|
524
525
|
createElement(...args: any[]): ElementNode;
|
526
|
+
createStyles(styles: Record<string, any>): string;
|
525
527
|
|
526
528
|
state(value): ModuleWebState | any;
|
527
529
|
// @ts-ignore
|
528
530
|
invokeState(states: State[], callback: CallableFunction): any;
|
529
531
|
|
532
|
+
bundleCode(code: string, options?: Record<string, any>): string;
|
530
533
|
bundle(filePath: string, options?: Record<string, any>): string;
|
531
534
|
}
|
532
535
|
|
@@ -1006,16 +1009,16 @@ declare namespace Rew {
|
|
1006
1009
|
group(...group: any[]): { g: T, with: (props: any) => { g: T, [key: string]: any }, [key: string]: any }
|
1007
1010
|
}
|
1008
1011
|
|
1009
|
-
declare const std
|
1010
|
-
curl: curl,
|
1011
|
-
int: int,
|
1012
|
-
str: str,
|
1013
|
-
bool: bool,
|
1014
|
-
float: float,
|
1015
|
-
num: num,
|
1016
|
-
typeis: typeis,
|
1017
|
-
typex: typex,
|
1018
|
-
typei: typei,
|
1012
|
+
declare const std: {
|
1013
|
+
curl: typeof curl,
|
1014
|
+
int: typeof int,
|
1015
|
+
str: typeof str,
|
1016
|
+
bool: typeof bool,
|
1017
|
+
float: typeof float,
|
1018
|
+
num: typeof num,
|
1019
|
+
typeis: typeof typeis,
|
1020
|
+
typex: typeof typex,
|
1021
|
+
typei: typeof typei,
|
1019
1022
|
|
1020
1023
|
prototype: {
|
1021
1024
|
void: () => void 0,
|