amateras 0.1.0 → 0.2.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/README.md CHANGED
@@ -83,8 +83,9 @@ $(document.body).content([
83
83
  ```
84
84
 
85
85
  ## Packages
86
- |-|-|
87
- |Package name|Size|Size(gzip)|Description|
88
- |amateras|5.51 kB|2.33 kB|Core
89
- |amateras/html|0.66 kB|0.28 kB|Import HTMLElement types and methods|
90
- |[amateras/css](./ext/css/README.md)|3.73 kB|1.4 kB|Style in JS|
86
+ | Package name | Size | Size(gzip) | Description |
87
+ | --- | --- | --- | --- |
88
+ | amateras | 5.50 kB | 2.26 kB | Core |
89
+ | amateras/html | 0.97 kB | 0.26 kB | Import HTMLElement types and methods |
90
+ | [amateras/css](./ext/css/README.md) | 3.45 kB | 1.29 kB | Style in JS |
91
+ | [amateras/router](./ext/router/README.md) | 2.92 kB | 1.27 kB | Amateras Router |
@@ -18,7 +18,6 @@ declare module 'amateras/core' {
18
18
  export function variables(value: string): $CSSVariable;
19
19
  export function variables<T extends $CSSVariableType>(options: T, conditions?: $CSSVariableConditionType<T>): { [key in keyof T]: $CSSVariable }
20
20
  export function keyframes<T extends { [key: string]: $CSSKeyframesType }>(options: T): { [key in keyof T]: $CSSKeyframesRule };
21
- export const stylesheet: CSSStyleSheet;
22
21
  }
23
22
  }
24
23
  }
@@ -37,8 +36,7 @@ function generateId(lettercase?: 'any' | 'lower' | 'upper'): string {
37
36
  return id;
38
37
  }
39
38
 
40
- const stylesheet = new CSSStyleSheet();
41
- document.adoptedStyleSheets.push(stylesheet);
39
+ const stylesheet = $.stylesheet;
42
40
 
43
41
  function processCSSOptions<T extends $CSSStyleRule | $CSSKeyframeRule>(
44
42
  rule: T,
@@ -90,8 +88,9 @@ function createKeyframesRule(name: string, options: $CSSKeyframesType) {
90
88
  function insertRule(rule: $CSSRule, recursive = false) {
91
89
  if (_instanceof(rule, $CSSStyleRule) && !CSS.supports(`selector(${rule.selector})`)) return rule;
92
90
  stylesheet.insertRule(rule.css, stylesheet.cssRules.length);
93
- if (!_instanceof(rule, $CSSMediaRule)) rule.rules.forEach(rule => insertRule(rule))
94
- else if (!recursive) rule.mediaRules.forEach(rule => insertRule(rule, true))
91
+ if (_instanceof(rule, $CSSKeyframesRule)) return rule;
92
+ if (!_instanceof(rule, $CSSMediaRule)) rule.rules.forEach(rule => insertRule(rule));
93
+ else if (!recursive) rule.mediaRules.forEach(rule => insertRule(rule, true));
95
94
  return rule;
96
95
  }
97
96
 
@@ -111,7 +110,6 @@ _Object_assign($, {
111
110
  })
112
111
 
113
112
  _Object_assign($.css, {
114
- stylesheet: stylesheet,
115
113
  variables<T extends $CSSVariableType | string>(options: T, conditions?: $CSSVariableConditionType<T>) {
116
114
  if (isObject(options)) {
117
115
  const variables = _Object_fromEntries(_Object_entries(options).map(([key, value]) => [
@@ -1,4 +1,5 @@
1
1
  import { $CSSStyleRule } from "#structure/$CSSStyleRule";
2
+ import { _Array_from } from "../../../../src/lib/native";
2
3
 
3
4
  export class $CSSKeyframeRule extends $CSSStyleRule {
4
5
  keyframe: string
@@ -8,6 +9,6 @@ export class $CSSKeyframeRule extends $CSSStyleRule {
8
9
  }
9
10
 
10
11
  get css(): string {
11
- return `${this.keyframe} { ${Array.from(this.declarations).map(([_, dec]) => `${dec}`).join(' ')} }`
12
+ return `${this.keyframe} { ${_Array_from(this.declarations).map(([_, dec]) => `${dec}`).join(' ')} }`
12
13
  }
13
14
  }
@@ -1,4 +1,5 @@
1
1
  import { $CSSRule } from "#structure/$CSSRule";
2
+ import { _Array_from } from "../../../../src/lib/native";
2
3
 
3
4
  export class $CSSKeyframesRule extends $CSSRule {
4
5
  name: string;
@@ -12,6 +13,6 @@ export class $CSSKeyframesRule extends $CSSRule {
12
13
  }
13
14
 
14
15
  get css() {
15
- return `@keyframes ${this.name} { ${Array.from(this.rules).map(rule => rule.css).join(' ')} }`
16
+ return `@keyframes ${this.name} { ${_Array_from(this.rules).map(rule => rule.css).join(' ')} }`
16
17
  }
17
18
  }
package/ext/html/html.ts CHANGED
@@ -1,59 +1,25 @@
1
1
  import '#core';
2
- import { $Node } from '#node/$Node';
3
- import { $HTMLElement } from './node/$HTMLElement';
4
- import './node/type';
5
- import { assignHelper } from '#lib/assignHelper';
6
- export * from './node/type';
7
- export * from './node/$HTMLElement';
8
-
9
- // create element classes
10
- export const [
11
- $Input,
12
- $Anchor,
13
- $Image,
14
- $Canvas,
15
- $Dialog,
16
- $Form,
17
- $Label,
18
- $Media,
19
- $Select,
20
- $Option,
21
- $OptGroup,
22
- $TextArea,
23
- ] = [
24
- $HTMLElementBuilder<HTMLInputElement>('input'),
25
- $HTMLElementBuilder<HTMLAnchorElement>('a'),
26
- $HTMLElementBuilder<HTMLImageElement>('img'),
27
- $HTMLElementBuilder<HTMLCanvasElement>('canvas'),
28
- $HTMLElementBuilder<HTMLDialogElement>('dialog'),
29
- $HTMLElementBuilder<HTMLFormElement>('form'),
30
- $HTMLElementBuilder<HTMLLabelElement>('label'),
31
- $HTMLElementBuilder<HTMLMediaElement>('media'),
32
- $HTMLElementBuilder<HTMLSelectElement>('select'),
33
- $HTMLElementBuilder<HTMLOptionElement>('option'),
34
- $HTMLElementBuilder<HTMLOptGroupElement>('optgroup'),
35
- $HTMLElementBuilder<HTMLTextAreaElement>('textarea'),
36
- ]
37
-
38
- const targets: [object: Constructor<Node>, target: Constructor<$Node>, tagname?: string][] = [
39
- [HTMLElement, $HTMLElement],
40
- [HTMLInputElement, $Input, 'input'],
41
- [HTMLAnchorElement, $Anchor, 'a'],
42
- [HTMLImageElement, $Image, 'img'],
43
- [HTMLCanvasElement, $Canvas, 'canvas'],
44
- [HTMLDialogElement, $Dialog, 'dialog'],
45
- [HTMLFormElement, $Form, 'form'],
46
- [HTMLLabelElement, $Label, 'label'],
47
- [HTMLMediaElement, $Media, 'media'],
48
- [HTMLSelectElement, $Select, 'select'],
49
- [HTMLOptionElement, $Option, 'option'],
50
- [HTMLOptGroupElement, $OptGroup, 'optgroup'],
51
- [HTMLTextAreaElement, $TextArea, 'textarea'],
52
- ];
53
- assignHelper(targets);
54
-
55
- function $HTMLElementBuilder<Ele extends HTMLElement>(tagName: string) {
56
- return class extends $HTMLElement<Ele> {
57
- constructor() { super(tagName) }
58
- }
59
- }
2
+ import './node/$Anchor';
3
+ import './node/$Dialog';
4
+ import './node/$Form';
5
+ import './node/$Image';
6
+ import './node/$Canvas';
7
+ import './node/$Input';
8
+ import './node/$Label';
9
+ import './node/$Media';
10
+ import './node/$OptGroup';
11
+ import './node/$Option';
12
+ import './node/$Select';
13
+ import './node/$TextArea';
14
+ export * from './node/$Anchor';
15
+ export * from './node/$Canvas';
16
+ export * from './node/$Dialog';
17
+ export * from './node/$Form';
18
+ export * from './node/$Image';
19
+ export * from './node/$Input';
20
+ export * from './node/$Label';
21
+ export * from './node/$Media';
22
+ export * from './node/$OptGroup';
23
+ export * from './node/$Option';
24
+ export * from './node/$Select';
25
+ export * from './node/$TextArea';
@@ -0,0 +1,19 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Anchor extends $HTMLElement<HTMLAnchorElement> {
5
+ constructor() {
6
+ super('a')
7
+ }
8
+ }
9
+
10
+ export interface $Anchor extends $HTMLElement<HTMLAnchorElement> {
11
+ href(href: string): this;
12
+ href(): string;
13
+ }
14
+
15
+ declare module '#core' {
16
+ export function $(nodeName: 'a'): $Anchor
17
+ }
18
+
19
+ assignHelper(HTMLAnchorElement, $Anchor, 'a');
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Canvas extends $HTMLElement<HTMLCanvasElement> {
5
+ constructor() {
6
+ super('canvas')
7
+ }
8
+ }
9
+
10
+ export interface $Canvas extends $HTMLElement<HTMLCanvasElement> {}
11
+
12
+ assignHelper(HTMLCanvasElement, $Canvas, 'canvas');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'canvas'): $Canvas
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Dialog extends $HTMLElement<HTMLDialogElement> {
5
+ constructor() {
6
+ super('dialog')
7
+ }
8
+ }
9
+
10
+ export interface $Dialog extends $HTMLElement<HTMLDialogElement> {}
11
+
12
+ assignHelper(HTMLDialogElement, $Dialog, 'dialog');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'dialog'): $Dialog
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Form extends $HTMLElement<HTMLFormElement> {
5
+ constructor() {
6
+ super('form')
7
+ }
8
+ }
9
+
10
+ export interface $Form extends $HTMLElement<HTMLFormElement> {}
11
+
12
+ assignHelper(HTMLFormElement, $Form, 'form');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'form'): $Form
16
+ }
@@ -0,0 +1,19 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Image extends $HTMLElement<HTMLImageElement> {
5
+ constructor() {
6
+ super('img')
7
+ }
8
+ }
9
+
10
+ export interface $Image extends $HTMLElement<HTMLImageElement> {
11
+ src(src: string): this;
12
+ src(): string;
13
+ }
14
+
15
+ assignHelper(HTMLImageElement, $Image, 'img');
16
+
17
+ declare module '#core' {
18
+ export function $(nodeName: 'img'): $Image
19
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Input extends $HTMLElement<HTMLInputElement> {
5
+ constructor() {
6
+ super('input')
7
+ }
8
+ }
9
+
10
+ export interface $Input extends $HTMLElement<HTMLInputElement> {}
11
+
12
+ assignHelper(HTMLInputElement, $Input, 'input');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'input'): $Input
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Label extends $HTMLElement<HTMLLabelElement> {
5
+ constructor() {
6
+ super('label')
7
+ }
8
+ }
9
+
10
+ export interface $Label extends $HTMLElement<HTMLLabelElement> {}
11
+
12
+ assignHelper(HTMLLabelElement, $Label, 'label');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'label'): $Label
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Media extends $HTMLElement<HTMLMediaElement> {
5
+ constructor() {
6
+ super('media')
7
+ }
8
+ }
9
+
10
+ export interface $Media extends $HTMLElement<HTMLMediaElement> {}
11
+
12
+ assignHelper(HTMLMediaElement, $Media, 'media');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'media'): $Media
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $OptGroup extends $HTMLElement<HTMLOptGroupElement> {
5
+ constructor() {
6
+ super('optgroup')
7
+ }
8
+ }
9
+
10
+ export interface $OptGroup extends $HTMLElement<HTMLOptGroupElement> {}
11
+
12
+ assignHelper(HTMLOptGroupElement, $OptGroup, 'optgroup');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'optgroup'): $OptGroup
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Option extends $HTMLElement<HTMLOptionElement> {
5
+ constructor() {
6
+ super('option')
7
+ }
8
+ }
9
+
10
+ export interface $Option extends $HTMLElement<HTMLOptionElement> {}
11
+
12
+ assignHelper(HTMLOptionElement, $Option, 'option');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'option'): $Option
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $Select extends $HTMLElement<HTMLSelectElement> {
5
+ constructor() {
6
+ super('select')
7
+ }
8
+ }
9
+
10
+ export interface $Select extends $HTMLElement<HTMLSelectElement> {}
11
+
12
+ assignHelper(HTMLSelectElement, $Select, 'select');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'select'): $Select
16
+ }
@@ -0,0 +1,16 @@
1
+ import { assignHelper } from "#lib/assignHelper";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+
4
+ export class $TextArea extends $HTMLElement<HTMLTextAreaElement> {
5
+ constructor() {
6
+ super('textarea')
7
+ }
8
+ }
9
+
10
+ export interface $TextArea extends $HTMLElement<HTMLTextAreaElement> {}
11
+
12
+ assignHelper(HTMLTextAreaElement, $TextArea, 'textarea');
13
+
14
+ declare module '#core' {
15
+ export function $(nodeName: 'textarea'): $TextArea
16
+ }
@@ -0,0 +1,81 @@
1
+ # amateras/router
2
+
3
+ ## Usage
4
+ ```ts
5
+ import 'amateras';
6
+ import 'amateras/router';
7
+ ```
8
+
9
+ ## Create Route Map
10
+ ```ts
11
+ // create home page route
12
+ const HomePage = $('route', '/', page => page
13
+ .pageTitle('Home')
14
+ .content([
15
+ $('h1').content('Home')
16
+ ])
17
+ )
18
+ // append router and mapping home page route into router
19
+ $(document.body).content([
20
+ $('router')
21
+ .route('/', HomePage)
22
+ .route('/hello', page => 'Hello!')
23
+ .listen() // start to listen path change
24
+ ])
25
+ ```
26
+
27
+ ## Router Anchor
28
+ Use `RouterAnchor` to prevent load page when open link by default `HTMLAnchorElement` element.
29
+ ```ts
30
+ $('ra').content('Contact').href('/contact');
31
+ ```
32
+
33
+ ## Common Methods
34
+ - `$.open(url)`: Open page without load page.
35
+ - `$.replace(url)`: Replace history state with url and open page.
36
+ - `$.forward()`: Forward page.
37
+ - `$.back()`: Back page.
38
+
39
+ ## Path Parameter and Query
40
+ ```ts
41
+ $('router')
42
+ .route('/user/@:username', page => {
43
+ console.log(page.params)
44
+ })
45
+ .route('/posts?search'), page => {
46
+ console.log(page.query)
47
+ }
48
+ .listen()
49
+ // simulate page open
50
+ .resolve('/user/@amateras') // { username: 'amateras' }
51
+ .resolve('/posts"') // { }
52
+ .resolve('/posts?search=tsukimi&user') // { search: 'tsukimi', user: '' }
53
+ ```
54
+
55
+ ## Nesting Route
56
+ ```ts
57
+ const ContactPage = $('route', '/contact', page => page
58
+ .pageTitle('Home')
59
+ .content([
60
+ $('h1').content('Contact'),
61
+ // append router with page, nested routes will show in this router
62
+ $('router', page)
63
+ ])
64
+ )
65
+
66
+ const ContactEmailPage = $('route', '/contact/email', () => 'amateras@example.com')
67
+
68
+ $('router')
69
+ .route('/', HomePage)
70
+ .route('/contact', ContactPage, route => route
71
+ .route('/', () => 'My name is Amateras.')
72
+ .route('/phone', () => '0123456789')
73
+ .route('/email', ContactEmailPage)
74
+ )
75
+ ```
76
+
77
+ ## Async Route
78
+ ```ts
79
+ $('router')
80
+ .route('/about', () => import('./pages/about.ts'))
81
+ ```
@@ -0,0 +1,64 @@
1
+ import { _Object_assign } from "#lib/native";
2
+ import type { $NodeContentResolver } from "#node/$Node";
3
+ import type { Page } from "./node/Page";
4
+ import { Route } from "./node/Route";
5
+ import { Router } from "./node/Router";
6
+ import { RouterAnchor } from "./node/RouterAnchor";
7
+ export * from "./node/Route";
8
+ export * from "./node/Router";
9
+ export * from "./node/Page";
10
+
11
+ declare module 'amateras/core' {
12
+ export function $<P extends string>(nodeName: 'route', path: P, builder: RouteBuilder<Route<P>, RouteDataResolver<P>>): Route<P>;
13
+ export function $(nodeName: 'router', page?: Page<any>): Router;
14
+ export function $(nodeName: 'ra'): RouterAnchor;
15
+ export namespace $ {
16
+ export function open(url: string | URL | Nullish): typeof Router;
17
+ export function replace(url: string | URL | Nullish): typeof Router;
18
+ export function back(): typeof Router;
19
+ export function forward(): typeof Router;
20
+ }
21
+ }
22
+ // assign methods
23
+ _Object_assign($, {
24
+ open: Router.open.bind(Router),
25
+ replace: Router.replace.bind(Router),
26
+ back: Router.back.bind(Router),
27
+ forward: Router.forward.bind(Router)
28
+ });
29
+ // define styles
30
+ [
31
+ `router{display:block}`,
32
+ `page{display:block}`
33
+ ].forEach(rule => $.stylesheet.insertRule(rule));
34
+ // assign nodes
35
+ $.assign([
36
+ ['router', Router],
37
+ ['route', Route],
38
+ ['ra', RouterAnchor]
39
+ ])
40
+
41
+ export type RouteData = { params: any, query: any }
42
+ export type RouteDataResolver<P extends string> = { params: Prettify<PathParams<P>>, query: Prettify<PathQuery<P>> }
43
+ export type AsyncRoute<P extends string> = () => Promise<{default: Route<P>}>
44
+ export type RouteBuilder<R extends Route<any>, D extends RouteData> = (page: Page<R, D>) => OrPromise<$NodeContentResolver<Page<R, D>>>;
45
+
46
+ type PathParams<Path> = Path extends `${infer Segment}/${infer Rest}`
47
+ ? Segment extends `${string}:${infer Param}`
48
+ ? Record<Param, string> & PathParams<Rest>
49
+ : PathParams<Rest>
50
+ : Path extends `${string}:${infer Param}?${infer Query}`
51
+ ? Record<Param, string>
52
+ : Path extends `${string}:${infer Param}`
53
+ ? Record<Param, string>
54
+ : {}
55
+
56
+ type PathQuery<Path> = Path extends `${string}?${infer Segment}`
57
+ ? PathQuery_SetRecord<Segment>
58
+ : Path extends `&${infer Segment}`
59
+ ? PathQuery_SetRecord<Segment>
60
+ : {}
61
+
62
+ type PathQuery_SetRecord<Segment extends string> = Segment extends `${infer Param}&${infer Rest}`
63
+ ? Record<Param, string> & PathQuery<`&${Rest}`>
64
+ : Record<Segment, string>
@@ -0,0 +1,27 @@
1
+ import { isUndefined } from "#lib/native";
2
+ import { $HTMLElement } from "#node/$HTMLElement";
3
+ import type { RouteData } from "..";
4
+ import type { Route } from "./Route";
5
+
6
+ export class Page<R extends Route<any> = any, Data extends RouteData = any> extends $HTMLElement {
7
+ route: R;
8
+ page: this;
9
+ params: Data['params'];
10
+ query: Data['query'];
11
+ #pageTitle: null | string = null;
12
+ constructor(route: R, data?: {params: any, query: any}) {
13
+ super('page');
14
+ this.route = route;
15
+ this.page = this;
16
+ this.params = data?.params ?? {};
17
+ this.query = data?.query ?? {};
18
+ }
19
+
20
+ pageTitle(): string | null;
21
+ pageTitle(title: string | null): this;
22
+ pageTitle(title?: string | null) {
23
+ if (!arguments.length) return this.#pageTitle;
24
+ if (!isUndefined(title)) this.#pageTitle = title;
25
+ return this;
26
+ }
27
+ }
@@ -0,0 +1,53 @@
1
+ import { _instanceof, _Object_fromEntries, _Array_from } from "#lib/native";
2
+ import { $Element } from "#node/node";
3
+ import type { AsyncRoute, RouteBuilder, RouteDataResolver } from "..";
4
+ import { Page } from "./Page";
5
+
6
+ export abstract class BaseRouteNode<Path extends string = string> extends $Element {
7
+ readonly path: Path;
8
+ routes = new Map<string, Route<any>>()
9
+ parent: BaseRouteNode<any> | null = null;
10
+ builder: RouteBuilder<Route<Path>, RouteDataResolver<Path>> | AsyncRoute<Path>
11
+ constructor(path: Path, builder: RouteBuilder<Route<Path>, RouteDataResolver<Path>> | AsyncRoute<Path>, nodeName: string) {
12
+ super(nodeName);
13
+ this.path = path;
14
+ this.builder = builder;
15
+ }
16
+
17
+ route<P extends string, J extends `${Path}${P}`>(
18
+ path: P,
19
+ resolver: RouteBuilder<Route<J>, RouteDataResolver<J>> | Route<J> | AsyncRoute<J>,
20
+ fn?: (route: Route<J>) => Route<J>
21
+ ) {
22
+ const fullPath = `${this.path}${path}`;
23
+ if (_instanceof(resolver, Route) && fullPath !== resolver.path) throw `Pathname not matched: ${path}`
24
+ const route = resolver instanceof Route ? resolver : new Route(fullPath as J, resolver);
25
+ route.parent = this;
26
+ fn && fn(route);
27
+ this.routes.set(path, route);
28
+ return this;
29
+ }
30
+ }
31
+
32
+ export class Route<Path extends string = string> extends BaseRouteNode<Path> {
33
+ constructor(path: Path, builder: RouteBuilder<Route<Path>, RouteDataResolver<Path>> | AsyncRoute<Path>) {
34
+ super(path, builder, 'route');
35
+ }
36
+
37
+ async build(data: {params: any, query: any} = {params: {}, query: {}}) {
38
+ const page = new Page(this, data);
39
+ page.params = data.params;
40
+ let resolver: any = this.builder(page);
41
+ if (_instanceof(resolver, Promise)) {
42
+ const result = await resolver as any;
43
+ // Module import
44
+ if (result[Symbol.toStringTag] === 'Module') {
45
+ page.route = this;
46
+ resolver = result.default.builder(page);
47
+ }
48
+ else resolver = result;
49
+ }
50
+ if (!_instanceof(resolver, Page)) page.content(resolver);
51
+ return page;
52
+ }
53
+ }