revojs 0.0.29 → 0.0.31
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/dist/index.js +122 -65
- package/dist/locale/index.d.ts +23 -10
- package/dist/radix/index.d.ts +1 -1
- package/dist/router/index.d.ts +41 -7
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import { h } from "revojs/jsx-runtime";
|
|
|
3
3
|
|
|
4
4
|
//#region src/app/index.ts
|
|
5
5
|
const getRoutes = async () => {
|
|
6
|
-
return await import("#virtual/routes").then((module) => module.
|
|
6
|
+
return await import("#virtual/routes").then((module) => module.routes);
|
|
7
7
|
};
|
|
8
8
|
const getAssets = async () => {
|
|
9
|
-
return await import("#virtual/assets").then((module) => module.
|
|
9
|
+
return await import("#virtual/assets").then((module) => module.assets);
|
|
10
10
|
};
|
|
11
11
|
const createApp = (config) => {
|
|
12
12
|
return {
|
|
@@ -252,14 +252,15 @@ const renderToString = async (scope, slot) => {
|
|
|
252
252
|
if (typeof slot === "object") {
|
|
253
253
|
if (Array.isArray(slot)) return await Promise.all(slot.map((slot$1) => renderToString(scope, slot$1))).then((chunks) => chunks.join(""));
|
|
254
254
|
if (isTemplate(slot)) {
|
|
255
|
-
const
|
|
255
|
+
const CustomElement = components.get(slot.tag);
|
|
256
256
|
const prefix = Object.entries(slot.attributes).reduce((chunks, [name, value]) => {
|
|
257
257
|
if (!name.startsWith("on")) chunks.push(`${name}='${toString(value)}'`);
|
|
258
258
|
return chunks;
|
|
259
259
|
}, [slot.tag]).join(" ");
|
|
260
260
|
const children = await renderToString(scope, slot.children);
|
|
261
|
-
if (
|
|
262
|
-
const element = new
|
|
261
|
+
if (CustomElement) {
|
|
262
|
+
const element = new CustomElement(slot.attributes, scope);
|
|
263
|
+
scope.onStop(() => element.scope.stop());
|
|
263
264
|
const template = await renderToString(element.scope, await element.setup());
|
|
264
265
|
if (element.shadowRoot) {
|
|
265
266
|
const shadow = await renderToString(element.scope, {
|
|
@@ -556,7 +557,7 @@ var Radix = class Radix {
|
|
|
556
557
|
children;
|
|
557
558
|
constructor(input) {
|
|
558
559
|
this.input = input;
|
|
559
|
-
this.children =
|
|
560
|
+
this.children = {};
|
|
560
561
|
}
|
|
561
562
|
insert = (path, value) => {
|
|
562
563
|
let node = this;
|
|
@@ -566,10 +567,10 @@ var Radix = class Radix {
|
|
|
566
567
|
input = segment.substring(1);
|
|
567
568
|
segment = ":";
|
|
568
569
|
}
|
|
569
|
-
let childNode = node.children
|
|
570
|
+
let childNode = node.children[segment];
|
|
570
571
|
if (childNode === void 0) {
|
|
571
572
|
childNode = new Radix(input);
|
|
572
|
-
node.children
|
|
573
|
+
node.children[segment] = childNode;
|
|
573
574
|
}
|
|
574
575
|
node = childNode;
|
|
575
576
|
}
|
|
@@ -580,7 +581,7 @@ var Radix = class Radix {
|
|
|
580
581
|
let node = this;
|
|
581
582
|
const match = { inputs: {} };
|
|
582
583
|
for (const segment of path.split("/")) {
|
|
583
|
-
node = node?.children
|
|
584
|
+
node = node?.children[segment] ?? node?.children[":"];
|
|
584
585
|
if (node?.input) match.inputs[node.input] = segment;
|
|
585
586
|
}
|
|
586
587
|
match.value = node?.value;
|
|
@@ -597,7 +598,7 @@ const fileName = (path) => {
|
|
|
597
598
|
return path.split("/").pop()?.split(".").slice(0, -1).join(".");
|
|
598
599
|
};
|
|
599
600
|
const toPath = (value) => {
|
|
600
|
-
const path = (value.startsWith("/") ? value : "/" + value).replaceAll(/\/index/g, "").replaceAll(/\[(
|
|
601
|
+
const path = (value.startsWith("/") ? value : "/" + value).replaceAll(/\/index/g, "").replaceAll(/\[(.*?)\]/g, (_, name) => ":" + name);
|
|
601
602
|
const route = path.startsWith("/") ? path : "/" + path;
|
|
602
603
|
const split = route.split(".");
|
|
603
604
|
return split.length === 3 ? [split.at(0), split.at(1)] : [split.at(0)];
|
|
@@ -629,8 +630,12 @@ const createRuntime = async () => {
|
|
|
629
630
|
if (typeof route === "object") return route.fetch(event);
|
|
630
631
|
if (route) {
|
|
631
632
|
const scope = new Scope();
|
|
632
|
-
|
|
633
|
-
|
|
633
|
+
try {
|
|
634
|
+
scope.setContext(RUNTIME_CONTEXT, { event });
|
|
635
|
+
return sendHtml(event, await renderToString(scope, await import("#virtual/client").then((module) => module.client)));
|
|
636
|
+
} finally {
|
|
637
|
+
scope.stop();
|
|
638
|
+
}
|
|
634
639
|
}
|
|
635
640
|
} }));
|
|
636
641
|
}
|
|
@@ -658,9 +663,9 @@ const createRuntime = async () => {
|
|
|
658
663
|
if (response) return response;
|
|
659
664
|
}
|
|
660
665
|
return sendText(event, "Not found");
|
|
661
|
-
} catch (
|
|
662
|
-
if (
|
|
663
|
-
throw
|
|
666
|
+
} catch (exception) {
|
|
667
|
+
if (exception instanceof Response) return exception;
|
|
668
|
+
throw exception;
|
|
664
669
|
}
|
|
665
670
|
}
|
|
666
671
|
};
|
|
@@ -669,72 +674,124 @@ const RUNTIME_CONTEXT = defineContext("RUNTIME_CONTEXT");
|
|
|
669
674
|
|
|
670
675
|
//#endregion
|
|
671
676
|
//#region src/router/index.tsx
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const state = window.history.state;
|
|
676
|
-
window.history.pushState(state, "", url);
|
|
677
|
-
window.dispatchEvent(new PopStateEvent("popstate", { state }));
|
|
677
|
+
var NavigateEvent = class extends Event {
|
|
678
|
+
constructor() {
|
|
679
|
+
super("navigate");
|
|
678
680
|
}
|
|
679
681
|
};
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
for (const path in routes) {
|
|
692
|
-
const [name] = toPath(path);
|
|
693
|
-
if (name) radix.insert(name, routes[path]);
|
|
682
|
+
const ROUTER_CONTEXT = defineContext("ROUTER_CONTEXT");
|
|
683
|
+
const createRouter = (options) => {
|
|
684
|
+
const navigator = new EventTarget();
|
|
685
|
+
const radix = new Radix();
|
|
686
|
+
const route = createState();
|
|
687
|
+
const inputs = createState();
|
|
688
|
+
for (const path in options.routes) {
|
|
689
|
+
const [name] = toPath(path);
|
|
690
|
+
if (name) {
|
|
691
|
+
const value = options.routes[path];
|
|
692
|
+
if (value) radix.insert(name, value);
|
|
694
693
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
694
|
+
}
|
|
695
|
+
const registerRouterContext = async (scope) => {
|
|
696
|
+
const { event } = scope.getContext(RUNTIME_CONTEXT);
|
|
697
|
+
const fetch$1 = async () => {
|
|
698
|
+
const url = new URL(event ? event.request.url : window.location.href);
|
|
699
|
+
const match = radix.match(url.pathname);
|
|
700
|
+
inputs.value = match.inputs;
|
|
701
|
+
const Page$1 = await match.value?.();
|
|
702
|
+
if (Page$1) route.value = /* @__PURE__ */ h(Page$1, inputs.value);
|
|
704
703
|
};
|
|
704
|
+
if (isClient()) useEvent(scope, window, "popstate", () => navigator.dispatchEvent(new NavigateEvent()));
|
|
705
|
+
if (event) inputs.value = event.context.inputs;
|
|
706
|
+
await fetch$1().then(() => useEvent(scope, navigator, "navigate", fetch$1));
|
|
707
|
+
scope.setContext(ROUTER_CONTEXT, {
|
|
708
|
+
options,
|
|
709
|
+
navigator,
|
|
710
|
+
radix,
|
|
711
|
+
route,
|
|
712
|
+
inputs
|
|
713
|
+
});
|
|
714
|
+
return useRouter(scope);
|
|
715
|
+
};
|
|
716
|
+
return {
|
|
717
|
+
ROUTER_CONTEXT,
|
|
718
|
+
registerRouterContext
|
|
719
|
+
};
|
|
720
|
+
};
|
|
721
|
+
const useRouter = (scope, context) => {
|
|
722
|
+
const { route, inputs, navigator } = scope.getContext(context ?? ROUTER_CONTEXT);
|
|
723
|
+
const navigate = (path) => {
|
|
724
|
+
if (isClient()) window.history.pushState(window.history.state, "", path);
|
|
725
|
+
navigator.dispatchEvent(new NavigateEvent());
|
|
726
|
+
};
|
|
727
|
+
const anchorNavigate = (event) => {
|
|
728
|
+
event.preventDefault();
|
|
729
|
+
navigate(event.currentTarget?.getAttribute("href") ?? "/");
|
|
730
|
+
};
|
|
731
|
+
return {
|
|
732
|
+
route,
|
|
733
|
+
inputs,
|
|
734
|
+
navigator,
|
|
735
|
+
navigate,
|
|
736
|
+
anchorNavigate
|
|
737
|
+
};
|
|
738
|
+
};
|
|
739
|
+
const Page = defineComponent({
|
|
740
|
+
name: "x-page",
|
|
741
|
+
shadowRoot: false,
|
|
742
|
+
setup: ({ scope }) => {
|
|
743
|
+
const { route } = scope.getContext(ROUTER_CONTEXT);
|
|
744
|
+
if (route === void 0) return;
|
|
745
|
+
return () => route.value;
|
|
705
746
|
}
|
|
706
747
|
});
|
|
707
748
|
|
|
708
749
|
//#endregion
|
|
709
750
|
//#region src/locale/index.ts
|
|
710
|
-
const
|
|
711
|
-
|
|
712
|
-
const
|
|
713
|
-
|
|
751
|
+
const LOCALE_CONTEXT = defineContext("LOCALE_CONTEXT");
|
|
752
|
+
const createLocale = (options) => {
|
|
753
|
+
const locale = createState(options.defaultLocale);
|
|
754
|
+
const messages = createState();
|
|
755
|
+
const registerLocaleContext = async (scope) => {
|
|
756
|
+
const { inputs, navigator, navigate } = useRouter(scope);
|
|
757
|
+
const fetch$1 = async () => {
|
|
758
|
+
if (options.input) {
|
|
759
|
+
const input = inputs.value?.[options.input];
|
|
760
|
+
if (input && input in options.locales) locale.value = input;
|
|
761
|
+
else navigate("/" + (locale.value ?? ""));
|
|
762
|
+
}
|
|
763
|
+
if (locale.value) {
|
|
764
|
+
const target = options.locales[locale.value];
|
|
765
|
+
messages.value = typeof target === "function" ? await target() : target;
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
await fetch$1().then(() => useEvent(scope, navigator, "navigate", fetch$1));
|
|
769
|
+
scope.setContext(LOCALE_CONTEXT, {
|
|
770
|
+
locale,
|
|
771
|
+
messages,
|
|
772
|
+
options
|
|
773
|
+
});
|
|
774
|
+
return useLocale(scope);
|
|
714
775
|
};
|
|
715
776
|
return {
|
|
716
777
|
LOCALE_CONTEXT,
|
|
717
778
|
registerLocaleContext
|
|
718
779
|
};
|
|
719
780
|
};
|
|
720
|
-
const
|
|
721
|
-
const {
|
|
722
|
-
const { inputs } = scope.getContext(ROUTE_CONTEXT);
|
|
723
|
-
const { locales, defaultLocale, cookie, input } = scope.getContext(context);
|
|
724
|
-
const entries = await import("#virtual/locales").then((module) => module.index);
|
|
725
|
-
let locale;
|
|
726
|
-
if (cookie) {
|
|
727
|
-
if (event) locale = getCookies(event)[cookie];
|
|
728
|
-
}
|
|
729
|
-
if (input) if (event) locale = event.context.inputs[input];
|
|
730
|
-
else locale = inputs[input];
|
|
731
|
-
locale ??= defaultLocale;
|
|
732
|
-
if (locale) locales[locale] = await entries[locale]?.() ?? {};
|
|
781
|
+
const useLocale = (scope, context) => {
|
|
782
|
+
const { locale, messages } = scope.getContext(context ?? LOCALE_CONTEXT);
|
|
733
783
|
const $ = (key) => {
|
|
734
|
-
|
|
735
|
-
|
|
784
|
+
return () => messages.value?.[key] ?? key;
|
|
785
|
+
};
|
|
786
|
+
const prefix = (input) => {
|
|
787
|
+
return () => `/${locale.value}` + (input ?? "");
|
|
788
|
+
};
|
|
789
|
+
return {
|
|
790
|
+
locale,
|
|
791
|
+
messages,
|
|
792
|
+
prefix,
|
|
793
|
+
$
|
|
736
794
|
};
|
|
737
|
-
return { $ };
|
|
738
795
|
};
|
|
739
796
|
|
|
740
797
|
//#endregion
|
|
@@ -831,4 +888,4 @@ const markdownToSlot = (input, options) => {
|
|
|
831
888
|
};
|
|
832
889
|
|
|
833
890
|
//#endregion
|
|
834
|
-
export { $fetch, Compute, Handler, MountedEvent,
|
|
891
|
+
export { $fetch, Compute, Handler, LOCALE_CONTEXT, MountedEvent, NavigateEvent, Page, ROUTER_CONTEXT, RUNTIME_CONTEXT, Radix, Scope, StopEvent, activeCompute, components, createApp, createCompute, createElement, createEvent, createLocale, createMemo, createRouter, createRuntime, createState, defineComponent, defineContext, defineRoute, fileName, fromValue, getAssets, getCookies, getCustomElement, getGlobalStyles, getMimeType, getRequestUrl, getRoutes, getSetCookies, getVariables, isClient, isServer, isTemplate, markdownToSlot, preventDefault, registerComponent, renderToNode, renderToString, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, stopImmediatePropagation, stopPropagation, targets, toCustomElement, toFragment, toPath, toString, useEvent, useLocale, useRouter };
|
package/dist/locale/index.d.ts
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
import { type Descriptor, Scope } from "../signals";
|
|
2
|
-
export type Locales = Record<string, Record<string, string
|
|
3
|
-
export type LocaleOptions<T extends Locales> = {
|
|
1
|
+
import { type Descriptor, Scope, type State } from "../signals";
|
|
2
|
+
export type Locales = Record<string, Record<string, string> | (() => Promise<Record<string, string>>)>;
|
|
3
|
+
export type LocaleOptions<T extends Locales = Locales> = {
|
|
4
4
|
locales: T;
|
|
5
5
|
defaultLocale?: keyof T;
|
|
6
|
-
cookie?: string;
|
|
7
6
|
input?: string;
|
|
8
7
|
};
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export type LocaleContext<T extends LocaleOptions = LocaleOptions> = {
|
|
9
|
+
locale: State<string | undefined>;
|
|
10
|
+
messages: State<Record<string, string> | undefined>;
|
|
11
|
+
options: T;
|
|
12
|
+
};
|
|
13
|
+
export declare const LOCALE_CONTEXT: Descriptor<LocaleContext<LocaleOptions<Locales>>>;
|
|
14
|
+
export declare const createLocale: <T extends LocaleOptions>(options: T) => {
|
|
15
|
+
LOCALE_CONTEXT: Descriptor<LocaleContext<T>>;
|
|
16
|
+
registerLocaleContext: (scope: Scope) => Promise<{
|
|
17
|
+
locale: State<string | undefined>;
|
|
18
|
+
messages: State<Record<string, string> | undefined>;
|
|
19
|
+
prefix: (input?: string) => () => string;
|
|
20
|
+
$: (key: never) => () => string | number | symbol;
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
export declare const useLocale: <T extends LocaleContext>(scope: Scope, context?: Descriptor<T>) => {
|
|
24
|
+
locale: State<string | undefined>;
|
|
25
|
+
messages: State<Record<string, string> | undefined>;
|
|
26
|
+
prefix: (input?: string) => () => string;
|
|
27
|
+
$: (key: keyof T["options"]["locales"][keyof T["options"]["locales"]]) => () => string | number | symbol;
|
|
12
28
|
};
|
|
13
|
-
export declare const useLocaleContext: <T extends LocaleOptions<Locales>>(scope: Scope, context: Descriptor<T>) => Promise<{
|
|
14
|
-
$: (key: keyof T["locales"][keyof T["locales"]]) => string | number | symbol | keyof T["locales"][keyof T["locales"]];
|
|
15
|
-
}>;
|
package/dist/radix/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type Match<T> = {
|
|
|
5
5
|
export declare class Radix<T> {
|
|
6
6
|
value?: T;
|
|
7
7
|
input?: string;
|
|
8
|
-
children:
|
|
8
|
+
children: Record<string, Radix<T>>;
|
|
9
9
|
constructor(input?: string);
|
|
10
10
|
insert: (path: string, value: T) => this;
|
|
11
11
|
match: (path: string) => Match<T>;
|
package/dist/router/index.d.ts
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
|
-
import { type ComponentConstructor } from "../html";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { type Attributes, type ComponentConstructor, type Events, type Slot } from "../html";
|
|
2
|
+
import { Radix } from "../radix";
|
|
3
|
+
import { type Descriptor, Scope, type State } from "../signals";
|
|
4
|
+
export type Routes = Record<string, () => Promise<ComponentConstructor<Events, Attributes>>>;
|
|
5
|
+
export type RouterOptions<T extends Routes = Routes> = {
|
|
6
|
+
routes: T;
|
|
7
|
+
};
|
|
8
|
+
export type RouterContext<T extends RouterOptions = RouterOptions> = {
|
|
9
|
+
options: T;
|
|
10
|
+
navigator: EventTarget;
|
|
11
|
+
radix: Radix<() => Promise<ComponentConstructor<Events, Attributes>>>;
|
|
12
|
+
route: State<Slot | undefined>;
|
|
13
|
+
inputs: State<Record<string, string> | undefined>;
|
|
14
|
+
};
|
|
15
|
+
export declare class NavigateEvent extends Event {
|
|
16
|
+
constructor();
|
|
17
|
+
}
|
|
18
|
+
export declare const ROUTER_CONTEXT: Descriptor<RouterContext<RouterOptions<Routes>>>;
|
|
19
|
+
export declare const createRouter: <T extends RouterOptions>(options: T) => {
|
|
20
|
+
ROUTER_CONTEXT: Descriptor<RouterContext<T>>;
|
|
21
|
+
registerRouterContext: (scope: Scope) => Promise<{
|
|
22
|
+
route: State<unknown>;
|
|
23
|
+
inputs: State<Record<string, string> | undefined>;
|
|
24
|
+
navigator: EventTarget;
|
|
25
|
+
navigate: (path: string) => void;
|
|
26
|
+
anchorNavigate: (event: Event) => void;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
export declare const useRouter: <T extends RouterContext>(scope: Scope, context?: Descriptor<T>) => {
|
|
30
|
+
route: State<unknown>;
|
|
31
|
+
inputs: State<Record<string, string> | undefined>;
|
|
32
|
+
navigator: EventTarget;
|
|
33
|
+
navigate: (path: string) => void;
|
|
34
|
+
anchorNavigate: (event: Event) => void;
|
|
35
|
+
};
|
|
36
|
+
export declare const Page: ComponentConstructor<{}, {}>;
|
|
37
|
+
declare global {
|
|
38
|
+
interface ElementEventMap {
|
|
39
|
+
navigate: NavigateEvent;
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "revojs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": "coverbase/revojs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,12 +16,15 @@
|
|
|
16
16
|
"./jsx-runtime": {
|
|
17
17
|
"types": "./dist/jsx/index.d.ts",
|
|
18
18
|
"import": "./dist/jsx/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./types": {
|
|
21
|
+
"types": "./src/types/index.d.ts"
|
|
19
22
|
}
|
|
20
23
|
},
|
|
21
24
|
"types": "./dist/index.d.ts",
|
|
22
25
|
"module": "./dist/index.js",
|
|
23
26
|
"main": "./dist/index.js",
|
|
24
|
-
"files": ["dist"],
|
|
27
|
+
"files": ["dist", "src/virtual"],
|
|
25
28
|
"scripts": {
|
|
26
29
|
"build": "rolldown -c rolldown.config.ts && tsc",
|
|
27
30
|
"watch": "rolldown -w -c rolldown.config.ts && tsc --watch"
|