lupine.web 1.1.3 → 1.1.5
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 +66 -3
- package/jsx-runtime/index.js +14 -14
- package/jsx-runtime/package.json +16 -16
- package/jsx-runtime/src/index.d.ts +2 -2
- package/package.json +53 -52
- package/src/core/bind-attributes.ts +61 -61
- package/src/core/bind-lang.ts +52 -52
- package/src/core/bind-links.ts +26 -16
- package/src/core/bind-meta.tsx +52 -52
- package/src/core/bind-ref.ts +51 -51
- package/src/core/bind-styles.ts +239 -239
- package/src/core/bind-theme.ts +53 -53
- package/src/core/camel-to-hyphens.ts +3 -3
- package/src/core/export-lupine.ts +80 -80
- package/src/core/index.ts +17 -17
- package/src/core/initialize.ts +116 -116
- package/src/core/mount-component.ts +72 -68
- package/src/core/page-loaded-events.ts +16 -16
- package/src/core/page-router.ts +180 -180
- package/src/core/render-component.ts +230 -233
- package/src/core/replace-innerhtml.ts +23 -23
- package/src/core/server-cookie.ts +24 -24
- package/src/global.d.ts +66 -66
- package/src/index.ts +14 -14
- package/src/jsx.ts +1044 -1043
- package/src/lib/cookie.ts +44 -44
- package/src/lib/debug-watch.ts +32 -32
- package/src/lib/index.ts +7 -7
- package/src/lib/is-frontend.ts +3 -3
- package/src/lib/logger.ts +55 -55
- package/src/lib/unique-id.ts +40 -40
- package/src/lib/web-config.ts +79 -77
- package/src/lib/web-env.ts +99 -99
- package/src/models/index.ts +4 -4
- package/src/models/json-props.ts +8 -8
- package/src/models/simple-storage-props.ts +9 -9
- package/src/models/theme-props.ts +7 -7
- package/src/models/to-client-delivery-props.ts +8 -8
- package/src/styles/css-styles.ts +814 -814
- package/src/styles/index.ts +4 -4
- package/tsconfig.json +113 -113
package/src/core/bind-theme.ts
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { setCookie } from '../lib/cookie';
|
|
2
|
-
import { ThemesProps } from '../models';
|
|
3
|
-
import { isFrontEnd } from '../lib/is-frontend';
|
|
4
|
-
import { getEitherCookie } from './server-cookie';
|
|
5
|
-
|
|
6
|
-
// theme doesn't need to reset, theme name is stored in cookie
|
|
7
|
-
|
|
8
|
-
export const defaultThemeName = 'light';
|
|
9
|
-
export const themeCookieName = 'theme';
|
|
10
|
-
export const updateThemeEventName = 'updateTheme';
|
|
11
|
-
export const themeAttributeName = 'data-theme';
|
|
12
|
-
const _themeCfg: { defaultTheme: string; themes: ThemesProps } = { defaultTheme: defaultThemeName, themes: {} };
|
|
13
|
-
export const bindTheme = (defaultTheme: string, themes: ThemesProps) => {
|
|
14
|
-
_themeCfg.defaultTheme = defaultTheme;
|
|
15
|
-
_themeCfg.themes = themes;
|
|
16
|
-
|
|
17
|
-
// set to cookie
|
|
18
|
-
getCurrentTheme();
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const getCurrentTheme = () => {
|
|
22
|
-
let themeName = getEitherCookie(themeCookieName) as string;
|
|
23
|
-
if (!themeName || !_themeCfg.themes[themeName]) {
|
|
24
|
-
themeName = _themeCfg.defaultTheme;
|
|
25
|
-
if (isFrontEnd()) {
|
|
26
|
-
setCookie(themeCookieName, _themeCfg.defaultTheme);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return { themeName, themes: _themeCfg.themes };
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const updateTheme = (themeName: string) => {
|
|
33
|
-
// Theme is only updated in Browser
|
|
34
|
-
_themeCfg.defaultTheme = themeName;
|
|
35
|
-
if (!isFrontEnd()) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
setCookie(themeCookieName, themeName);
|
|
40
|
-
document.documentElement.setAttribute(themeAttributeName, themeName);
|
|
41
|
-
|
|
42
|
-
// update theme for all iframe
|
|
43
|
-
// TODO: third-party domains?
|
|
44
|
-
const allIframe = document.querySelectorAll('iframe');
|
|
45
|
-
for (let i = 0; i < allIframe.length; i++) {
|
|
46
|
-
if (allIframe[i].contentWindow && allIframe[i].contentWindow!.top === window) {
|
|
47
|
-
allIframe[i].contentWindow!.document.documentElement.setAttribute(themeAttributeName, themeName);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const event = new CustomEvent(updateThemeEventName, { detail: themeName });
|
|
52
|
-
window.dispatchEvent(event);
|
|
53
|
-
};
|
|
1
|
+
import { setCookie } from '../lib/cookie';
|
|
2
|
+
import { ThemesProps } from '../models';
|
|
3
|
+
import { isFrontEnd } from '../lib/is-frontend';
|
|
4
|
+
import { getEitherCookie } from './server-cookie';
|
|
5
|
+
|
|
6
|
+
// theme doesn't need to reset, theme name is stored in cookie
|
|
7
|
+
|
|
8
|
+
export const defaultThemeName = 'light';
|
|
9
|
+
export const themeCookieName = 'theme';
|
|
10
|
+
export const updateThemeEventName = 'updateTheme';
|
|
11
|
+
export const themeAttributeName = 'data-theme';
|
|
12
|
+
const _themeCfg: { defaultTheme: string; themes: ThemesProps } = { defaultTheme: defaultThemeName, themes: {} };
|
|
13
|
+
export const bindTheme = (defaultTheme: string, themes: ThemesProps) => {
|
|
14
|
+
_themeCfg.defaultTheme = defaultTheme;
|
|
15
|
+
_themeCfg.themes = themes;
|
|
16
|
+
|
|
17
|
+
// set to cookie
|
|
18
|
+
getCurrentTheme();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getCurrentTheme = () => {
|
|
22
|
+
let themeName = getEitherCookie(themeCookieName) as string;
|
|
23
|
+
if (!themeName || !_themeCfg.themes[themeName]) {
|
|
24
|
+
themeName = _themeCfg.defaultTheme;
|
|
25
|
+
if (isFrontEnd()) {
|
|
26
|
+
setCookie(themeCookieName, _themeCfg.defaultTheme);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return { themeName, themes: _themeCfg.themes };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const updateTheme = (themeName: string) => {
|
|
33
|
+
// Theme is only updated in Browser
|
|
34
|
+
_themeCfg.defaultTheme = themeName;
|
|
35
|
+
if (!isFrontEnd()) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setCookie(themeCookieName, themeName);
|
|
40
|
+
document.documentElement.setAttribute(themeAttributeName, themeName);
|
|
41
|
+
|
|
42
|
+
// update theme for all iframe
|
|
43
|
+
// TODO: third-party domains?
|
|
44
|
+
const allIframe = document.querySelectorAll('iframe');
|
|
45
|
+
for (let i = 0; i < allIframe.length; i++) {
|
|
46
|
+
if (allIframe[i].contentWindow && allIframe[i].contentWindow!.top === window) {
|
|
47
|
+
allIframe[i].contentWindow!.document.documentElement.setAttribute(themeAttributeName, themeName);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const event = new CustomEvent(updateThemeEventName, { detail: themeName });
|
|
52
|
+
window.dispatchEvent(event);
|
|
53
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export const camelToHyphens = function (name: string) {
|
|
2
|
-
return name.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
3
|
-
};
|
|
1
|
+
export const camelToHyphens = function (name: string) {
|
|
2
|
+
return name.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
3
|
+
};
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import { VNode } from '../jsx';
|
|
2
|
-
import { PageRouter } from './page-router';
|
|
3
|
-
import { IToClientDelivery, JsonObject } from '../models';
|
|
4
|
-
|
|
5
|
-
export type RenderPageFunctionsType = {
|
|
6
|
-
fetchData: (
|
|
7
|
-
url: string,
|
|
8
|
-
postBody?: string | JsonObject,
|
|
9
|
-
returnRawResponse?: boolean,
|
|
10
|
-
returnHeaders?: boolean
|
|
11
|
-
) => Promise<any>;
|
|
12
|
-
// add host for mobile app, which needs the host
|
|
13
|
-
baseUrl: (urlWithoutHost?: string) => string;
|
|
14
|
-
[key: string]: Function;
|
|
15
|
-
};
|
|
16
|
-
export interface PageProps {
|
|
17
|
-
url: string;
|
|
18
|
-
// urlSections: string[];
|
|
19
|
-
query: { [key: string]: string };
|
|
20
|
-
urlParameters: { [key: string]: string };
|
|
21
|
-
renderPageFunctions: RenderPageFunctionsType;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type PageResultType = {
|
|
25
|
-
content: string;
|
|
26
|
-
title: string;
|
|
27
|
-
metaData: string;
|
|
28
|
-
themeName: string;
|
|
29
|
-
globalCss: string;
|
|
30
|
-
};
|
|
31
|
-
export type _LupineJs = {
|
|
32
|
-
// generatePage and initializePage are set in initialize.ts to avoid circular reference
|
|
33
|
-
generatePage: (props: any, toClientDelivery: IToClientDelivery) => Promise<PageResultType>;
|
|
34
|
-
initializePage: (newUrl?: string) => Promise<void>;
|
|
35
|
-
renderPageFunctions: RenderPageFunctionsType;
|
|
36
|
-
router: PageRouter | ((props: PageProps) => Promise<VNode<any>>);
|
|
37
|
-
renderPageProps: PageProps;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// main instance to be used in the FE and the BE
|
|
41
|
-
export const _lupineJs: _LupineJs = {} as _LupineJs;
|
|
42
|
-
|
|
43
|
-
// for SSR, it exports _lupineJs function for the server to call
|
|
44
|
-
// this should be loaded in a sandbox
|
|
45
|
-
if (typeof globalThis !== 'undefined') {
|
|
46
|
-
const gThis = globalThis as any;
|
|
47
|
-
if (gThis._lupineJs === null) {
|
|
48
|
-
gThis._lupineJs = () => {
|
|
49
|
-
return _lupineJs;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// if (typeof exports !== 'undefined') {
|
|
54
|
-
// // ignore esbuild's warnings:
|
|
55
|
-
// // The CommonJS "exports" variable is treated as a global variable in an ECMAScript module and may not work as expected [commonjs-variable-in-esm]
|
|
56
|
-
// exports._lupineJs = () => {
|
|
57
|
-
// return _lupineJs;
|
|
58
|
-
// };
|
|
59
|
-
// }
|
|
60
|
-
|
|
61
|
-
// this should be called by the FE and also by the server side to set fetchData and others for client and server side rendering.
|
|
62
|
-
// And the RenderPageFunctionsType will be passed to call (generate) a page through PageProps
|
|
63
|
-
export const bindRenderPageFunctions = (calls: RenderPageFunctionsType) => {
|
|
64
|
-
_lupineJs.renderPageFunctions = calls || {};
|
|
65
|
-
};
|
|
66
|
-
// export const getRenderPageFunctions = (): RenderPageFunctionsType => {
|
|
67
|
-
// return globalThis._lupineJs.renderPageFunctions;
|
|
68
|
-
// }
|
|
69
|
-
// this is only used inside the core
|
|
70
|
-
export const setRenderPageProps = (props: PageProps) => {
|
|
71
|
-
_lupineJs.renderPageProps = props;
|
|
72
|
-
};
|
|
73
|
-
// this is used by the code to get url info when it's executed in the FE or in the server side.
|
|
74
|
-
export const getRenderPageProps = (): PageProps => {
|
|
75
|
-
return _lupineJs.renderPageProps;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const bindRouter = (router: PageRouter | ((props: PageProps) => Promise<VNode<any>>)) => {
|
|
79
|
-
_lupineJs.router = router;
|
|
80
|
-
};
|
|
1
|
+
import { VNode } from '../jsx';
|
|
2
|
+
import { PageRouter } from './page-router';
|
|
3
|
+
import { IToClientDelivery, JsonObject } from '../models';
|
|
4
|
+
|
|
5
|
+
export type RenderPageFunctionsType = {
|
|
6
|
+
fetchData: (
|
|
7
|
+
url: string,
|
|
8
|
+
postBody?: string | JsonObject,
|
|
9
|
+
returnRawResponse?: boolean,
|
|
10
|
+
returnHeaders?: boolean
|
|
11
|
+
) => Promise<any>;
|
|
12
|
+
// add host for mobile app, which needs the host
|
|
13
|
+
baseUrl: (urlWithoutHost?: string) => string;
|
|
14
|
+
[key: string]: Function;
|
|
15
|
+
};
|
|
16
|
+
export interface PageProps {
|
|
17
|
+
url: string;
|
|
18
|
+
// urlSections: string[];
|
|
19
|
+
query: { [key: string]: string };
|
|
20
|
+
urlParameters: { [key: string]: string };
|
|
21
|
+
renderPageFunctions: RenderPageFunctionsType;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type PageResultType = {
|
|
25
|
+
content: string;
|
|
26
|
+
title: string;
|
|
27
|
+
metaData: string;
|
|
28
|
+
themeName: string;
|
|
29
|
+
globalCss: string;
|
|
30
|
+
};
|
|
31
|
+
export type _LupineJs = {
|
|
32
|
+
// generatePage and initializePage are set in initialize.ts to avoid circular reference
|
|
33
|
+
generatePage: (props: any, toClientDelivery: IToClientDelivery) => Promise<PageResultType>;
|
|
34
|
+
initializePage: (newUrl?: string) => Promise<void>;
|
|
35
|
+
renderPageFunctions: RenderPageFunctionsType;
|
|
36
|
+
router: PageRouter | ((props: PageProps) => Promise<VNode<any>>);
|
|
37
|
+
renderPageProps: PageProps;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// main instance to be used in the FE and the BE
|
|
41
|
+
export const _lupineJs: _LupineJs = {} as _LupineJs;
|
|
42
|
+
|
|
43
|
+
// for SSR, it exports _lupineJs function for the server to call
|
|
44
|
+
// this should be loaded in a sandbox
|
|
45
|
+
if (typeof globalThis !== 'undefined') {
|
|
46
|
+
const gThis = globalThis as any;
|
|
47
|
+
if (gThis._lupineJs === null) {
|
|
48
|
+
gThis._lupineJs = () => {
|
|
49
|
+
return _lupineJs;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// if (typeof exports !== 'undefined') {
|
|
54
|
+
// // ignore esbuild's warnings:
|
|
55
|
+
// // The CommonJS "exports" variable is treated as a global variable in an ECMAScript module and may not work as expected [commonjs-variable-in-esm]
|
|
56
|
+
// exports._lupineJs = () => {
|
|
57
|
+
// return _lupineJs;
|
|
58
|
+
// };
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
// this should be called by the FE and also by the server side to set fetchData and others for client and server side rendering.
|
|
62
|
+
// And the RenderPageFunctionsType will be passed to call (generate) a page through PageProps
|
|
63
|
+
export const bindRenderPageFunctions = (calls: RenderPageFunctionsType) => {
|
|
64
|
+
_lupineJs.renderPageFunctions = calls || {};
|
|
65
|
+
};
|
|
66
|
+
// export const getRenderPageFunctions = (): RenderPageFunctionsType => {
|
|
67
|
+
// return globalThis._lupineJs.renderPageFunctions;
|
|
68
|
+
// }
|
|
69
|
+
// this is only used inside the core
|
|
70
|
+
export const setRenderPageProps = (props: PageProps) => {
|
|
71
|
+
_lupineJs.renderPageProps = props;
|
|
72
|
+
};
|
|
73
|
+
// this is used by the code to get url info when it's executed in the FE or in the server side.
|
|
74
|
+
export const getRenderPageProps = (): PageProps => {
|
|
75
|
+
return _lupineJs.renderPageProps;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const bindRouter = (router: PageRouter | ((props: PageProps) => Promise<VNode<any>>)) => {
|
|
79
|
+
_lupineJs.router = router;
|
|
80
|
+
};
|
package/src/core/index.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export * from './bind-attributes';
|
|
2
|
-
export * from './bind-lang';
|
|
3
|
-
export * from './bind-links';
|
|
4
|
-
export * from './bind-meta';
|
|
5
|
-
export * from './bind-ref';
|
|
6
|
-
export * from './bind-styles';
|
|
7
|
-
export * from './bind-theme';
|
|
8
|
-
export * from './export-lupine';
|
|
9
|
-
export * from './camel-to-hyphens';
|
|
10
|
-
export * from './mount-component';
|
|
11
|
-
export * from './page-loaded-events';
|
|
12
|
-
export * from './page-router';
|
|
13
|
-
export * from './render-component';
|
|
14
|
-
export * from './replace-innerhtml';
|
|
15
|
-
export * from './server-cookie';
|
|
16
|
-
|
|
17
|
-
export * from './initialize';
|
|
1
|
+
export * from './bind-attributes';
|
|
2
|
+
export * from './bind-lang';
|
|
3
|
+
export * from './bind-links';
|
|
4
|
+
export * from './bind-meta';
|
|
5
|
+
export * from './bind-ref';
|
|
6
|
+
export * from './bind-styles';
|
|
7
|
+
export * from './bind-theme';
|
|
8
|
+
export * from './export-lupine';
|
|
9
|
+
export * from './camel-to-hyphens';
|
|
10
|
+
export * from './mount-component';
|
|
11
|
+
export * from './page-loaded-events';
|
|
12
|
+
export * from './page-router';
|
|
13
|
+
export * from './render-component';
|
|
14
|
+
export * from './replace-innerhtml';
|
|
15
|
+
export * from './server-cookie';
|
|
16
|
+
|
|
17
|
+
export * from './initialize';
|
package/src/core/initialize.ts
CHANGED
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
import { Logger } from '../lib/logger';
|
|
2
|
-
import { generateAllGlobalStyles } from './bind-styles';
|
|
3
|
-
import { defaultThemeName, getCurrentTheme, updateTheme } from './bind-theme';
|
|
4
|
-
import { mountInnerComponent } from './mount-component';
|
|
5
|
-
// import { callPageResetEvent } from './page-reset-events';
|
|
6
|
-
import { PageRouter } from './page-router';
|
|
7
|
-
import { callPageLoadedEvent } from './page-loaded-events';
|
|
8
|
-
import { initServerCookies } from './server-cookie';
|
|
9
|
-
import { IToClientDelivery } from '../models';
|
|
10
|
-
import { getMetaDataObject, getMetaDataTags, getPageTitle } from './bind-meta';
|
|
11
|
-
import { initWebEnv } from '../lib/web-env';
|
|
12
|
-
import { _lupineJs, PageProps, PageResultType, setRenderPageProps } from './export-lupine';
|
|
13
|
-
import { isFrontEnd } from '../lib/is-frontend';
|
|
14
|
-
import { WebConfig } from '../lib/web-config';
|
|
15
|
-
|
|
16
|
-
const logger = new Logger('initialize');
|
|
17
|
-
|
|
18
|
-
const renderTargetPage = async (props: PageProps, renderPartPage: boolean) => {
|
|
19
|
-
if (_lupineJs.router instanceof PageRouter) {
|
|
20
|
-
return _lupineJs.router.handleRoute(props.url, props, renderPartPage);
|
|
21
|
-
}
|
|
22
|
-
return await _lupineJs.router(props);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// this is called by server side for SSR (server-side-rendering)
|
|
26
|
-
const generatePage = async (props: PageProps, toClientDelivery: IToClientDelivery): Promise<PageResultType> => {
|
|
27
|
-
setRenderPageProps(props);
|
|
28
|
-
|
|
29
|
-
initWebEnv(toClientDelivery.getWebEnv());
|
|
30
|
-
WebConfig.initFromData(toClientDelivery.getWebSetting());
|
|
31
|
-
// initWebSetting(toClientDelivery.getWebSetting());
|
|
32
|
-
initServerCookies(toClientDelivery.getServerCookie());
|
|
33
|
-
// callPageResetEvent();
|
|
34
|
-
callPageLoadedEvent();
|
|
35
|
-
|
|
36
|
-
const jsxNodes = await renderTargetPage(props, false);
|
|
37
|
-
if (!jsxNodes || !jsxNodes.props) {
|
|
38
|
-
return {
|
|
39
|
-
content: `Unexpected url: ${props.url}`,
|
|
40
|
-
title: '',
|
|
41
|
-
metaData: '',
|
|
42
|
-
globalCss: '',
|
|
43
|
-
themeName: defaultThemeName,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
await mountInnerComponent(null, jsxNodes);
|
|
48
|
-
const currentTheme = getCurrentTheme();
|
|
49
|
-
const cssText = generateAllGlobalStyles();
|
|
50
|
-
const content = jsxNodes.props._html.join('');
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
content,
|
|
54
|
-
title: getPageTitle(),
|
|
55
|
-
metaData: getMetaDataTags(),
|
|
56
|
-
globalCss: cssText,
|
|
57
|
-
themeName: currentTheme.themeName,
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
_lupineJs.generatePage = generatePage;
|
|
61
|
-
|
|
62
|
-
const _initSaved = {
|
|
63
|
-
pageInitialized: false,
|
|
64
|
-
};
|
|
65
|
-
// this is called in the FE when the document is loaded
|
|
66
|
-
// to avoid circular reference, bindLinks can't call initializePage directly
|
|
67
|
-
export const initializePage = async (newUrl?: string) => {
|
|
68
|
-
const currentPageInitialized = _initSaved.pageInitialized;
|
|
69
|
-
_initSaved.pageInitialized = true;
|
|
70
|
-
logger.log('initializePage: ', newUrl);
|
|
71
|
-
if (newUrl) {
|
|
72
|
-
window.history.pushState({ urlPath: newUrl }, '', newUrl);
|
|
73
|
-
// prevents browser from storing history with each change:
|
|
74
|
-
// window.history.replaceState({ html: '', pageTitle: newUrl }, '', newUrl);
|
|
75
|
-
}
|
|
76
|
-
const splitUrl = newUrl ? newUrl.split('?') : [];
|
|
77
|
-
const url = splitUrl[0] || document.location.pathname;
|
|
78
|
-
const queryString = splitUrl[1] || document.location.search;
|
|
79
|
-
|
|
80
|
-
const props: PageProps = {
|
|
81
|
-
url,
|
|
82
|
-
// urlSections: url.split('/').filter((i) => !!i),
|
|
83
|
-
query: Object.fromEntries(new URLSearchParams(queryString)), // new URLSearchParams(queryString),
|
|
84
|
-
urlParameters: {},
|
|
85
|
-
renderPageFunctions: _lupineJs.renderPageFunctions,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
setRenderPageProps(props);
|
|
89
|
-
// !currentPageInitialized && callPageResetEvent();
|
|
90
|
-
!currentPageInitialized && callPageLoadedEvent();
|
|
91
|
-
|
|
92
|
-
const jsxNodes = await renderTargetPage(props, currentPageInitialized);
|
|
93
|
-
if (jsxNodes === null) return;
|
|
94
|
-
if (!jsxNodes || !jsxNodes.props) {
|
|
95
|
-
document.querySelector('.lupine-root')!.innerHTML = `
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// generateAllGlobalStyles will be updated directly in Browser
|
|
100
|
-
await mountInnerComponent('.lupine-root', jsxNodes);
|
|
101
|
-
updateTheme(getCurrentTheme().themeName);
|
|
102
|
-
|
|
103
|
-
// title
|
|
104
|
-
document.title = getPageTitle();
|
|
105
|
-
const metaData = getMetaDataObject();
|
|
106
|
-
// meta data?
|
|
107
|
-
};
|
|
108
|
-
if (isFrontEnd()) {
|
|
109
|
-
addEventListener('popstate', (event) => {
|
|
110
|
-
initializePage();
|
|
111
|
-
});
|
|
112
|
-
addEventListener('load', (event) => {
|
|
113
|
-
initializePage();
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
_lupineJs.initializePage = initializePage;
|
|
1
|
+
import { Logger } from '../lib/logger';
|
|
2
|
+
import { generateAllGlobalStyles } from './bind-styles';
|
|
3
|
+
import { defaultThemeName, getCurrentTheme, updateTheme } from './bind-theme';
|
|
4
|
+
import { mountInnerComponent } from './mount-component';
|
|
5
|
+
// import { callPageResetEvent } from './page-reset-events';
|
|
6
|
+
import { PageRouter } from './page-router';
|
|
7
|
+
import { callPageLoadedEvent } from './page-loaded-events';
|
|
8
|
+
import { initServerCookies } from './server-cookie';
|
|
9
|
+
import { IToClientDelivery } from '../models';
|
|
10
|
+
import { getMetaDataObject, getMetaDataTags, getPageTitle } from './bind-meta';
|
|
11
|
+
import { initWebEnv } from '../lib/web-env';
|
|
12
|
+
import { _lupineJs, PageProps, PageResultType, setRenderPageProps } from './export-lupine';
|
|
13
|
+
import { isFrontEnd } from '../lib/is-frontend';
|
|
14
|
+
import { WebConfig } from '../lib/web-config';
|
|
15
|
+
|
|
16
|
+
const logger = new Logger('initialize');
|
|
17
|
+
|
|
18
|
+
const renderTargetPage = async (props: PageProps, renderPartPage: boolean) => {
|
|
19
|
+
if (_lupineJs.router instanceof PageRouter) {
|
|
20
|
+
return _lupineJs.router.handleRoute(props.url, props, renderPartPage);
|
|
21
|
+
}
|
|
22
|
+
return await _lupineJs.router(props);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// this is called by server side for SSR (server-side-rendering)
|
|
26
|
+
const generatePage = async (props: PageProps, toClientDelivery: IToClientDelivery): Promise<PageResultType> => {
|
|
27
|
+
setRenderPageProps(props);
|
|
28
|
+
|
|
29
|
+
initWebEnv(toClientDelivery.getWebEnv());
|
|
30
|
+
WebConfig.initFromData(toClientDelivery.getWebSetting());
|
|
31
|
+
// initWebSetting(toClientDelivery.getWebSetting());
|
|
32
|
+
initServerCookies(toClientDelivery.getServerCookie());
|
|
33
|
+
// callPageResetEvent();
|
|
34
|
+
callPageLoadedEvent();
|
|
35
|
+
|
|
36
|
+
const jsxNodes = await renderTargetPage(props, false);
|
|
37
|
+
if (!jsxNodes || !jsxNodes.props) {
|
|
38
|
+
return {
|
|
39
|
+
content: `Unexpected url: ${props.url}`,
|
|
40
|
+
title: '',
|
|
41
|
+
metaData: '',
|
|
42
|
+
globalCss: '',
|
|
43
|
+
themeName: defaultThemeName,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await mountInnerComponent(null, jsxNodes);
|
|
48
|
+
const currentTheme = getCurrentTheme();
|
|
49
|
+
const cssText = generateAllGlobalStyles();
|
|
50
|
+
const content = jsxNodes.props._html.join('');
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
content,
|
|
54
|
+
title: getPageTitle(),
|
|
55
|
+
metaData: getMetaDataTags(),
|
|
56
|
+
globalCss: cssText,
|
|
57
|
+
themeName: currentTheme.themeName,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
_lupineJs.generatePage = generatePage;
|
|
61
|
+
|
|
62
|
+
const _initSaved = {
|
|
63
|
+
pageInitialized: false,
|
|
64
|
+
};
|
|
65
|
+
// this is called in the FE when the document is loaded
|
|
66
|
+
// to avoid circular reference, bindLinks can't call initializePage directly
|
|
67
|
+
export const initializePage = async (newUrl?: string) => {
|
|
68
|
+
const currentPageInitialized = _initSaved.pageInitialized;
|
|
69
|
+
_initSaved.pageInitialized = true;
|
|
70
|
+
logger.log('initializePage: ', newUrl);
|
|
71
|
+
if (newUrl) {
|
|
72
|
+
window.history.pushState({ urlPath: newUrl }, '', newUrl);
|
|
73
|
+
// prevents browser from storing history with each change:
|
|
74
|
+
// window.history.replaceState({ html: '', pageTitle: newUrl }, '', newUrl);
|
|
75
|
+
}
|
|
76
|
+
const splitUrl = newUrl ? newUrl.split('?') : [];
|
|
77
|
+
const url = splitUrl[0] || document.location.pathname;
|
|
78
|
+
const queryString = splitUrl[1] || document.location.search;
|
|
79
|
+
|
|
80
|
+
const props: PageProps = {
|
|
81
|
+
url,
|
|
82
|
+
// urlSections: url.split('/').filter((i) => !!i),
|
|
83
|
+
query: Object.fromEntries(new URLSearchParams(queryString)), // new URLSearchParams(queryString),
|
|
84
|
+
urlParameters: {},
|
|
85
|
+
renderPageFunctions: _lupineJs.renderPageFunctions,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
setRenderPageProps(props);
|
|
89
|
+
// !currentPageInitialized && callPageResetEvent();
|
|
90
|
+
!currentPageInitialized && callPageLoadedEvent();
|
|
91
|
+
|
|
92
|
+
const jsxNodes = await renderTargetPage(props, currentPageInitialized);
|
|
93
|
+
if (jsxNodes === null) return;
|
|
94
|
+
if (!jsxNodes || !jsxNodes.props) {
|
|
95
|
+
document.querySelector('.lupine-root')!.innerHTML = `Error happened or unexpected url: ${url}`;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// generateAllGlobalStyles will be updated directly in Browser
|
|
100
|
+
await mountInnerComponent('.lupine-root', jsxNodes);
|
|
101
|
+
updateTheme(getCurrentTheme().themeName);
|
|
102
|
+
|
|
103
|
+
// title
|
|
104
|
+
document.title = getPageTitle();
|
|
105
|
+
const metaData = getMetaDataObject();
|
|
106
|
+
// meta data?
|
|
107
|
+
};
|
|
108
|
+
if (isFrontEnd()) {
|
|
109
|
+
addEventListener('popstate', (event) => {
|
|
110
|
+
initializePage();
|
|
111
|
+
});
|
|
112
|
+
addEventListener('load', (event) => {
|
|
113
|
+
initializePage();
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
_lupineJs.initializePage = initializePage;
|