@webqit/webflo 0.20.34 → 0.20.36
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/package.json +9 -3
- package/src/index.js +7 -7
- package/src/{build-pi → webflo-build}/index.js +4 -4
- package/src/{config-pi → webflo-config}/deployment/Env.js +0 -4
- package/src/{config-pi → webflo-config}/deployment/Layout.js +0 -4
- package/src/{config-pi → webflo-config}/deployment/Origins.js +0 -4
- package/src/{config-pi → webflo-config}/deployment/Proxy.js +0 -4
- package/src/{config-pi → webflo-config}/deployment/index.js +0 -7
- package/src/{config-pi → webflo-config}/index.js +0 -7
- package/src/{config-pi → webflo-config}/static/Init.js +0 -4
- package/src/{config-pi → webflo-config}/static/Manifest.js +0 -4
- package/src/{config-pi → webflo-config}/static/Ssg.js +0 -4
- package/src/{config-pi → webflo-config}/static/index.js +0 -7
- package/src/{deployment-pi → webflo-deployment}/index.js +0 -7
- package/src/{deployment-pi → webflo-deployment}/origins/index.js +0 -13
- package/src/webflo-exports/ui/index.js +1 -0
- package/src/{init-pi → webflo-init}/index.js +1 -1
- package/src/webflo-runtime/webflo-client/DeviceViewport.js +173 -0
- package/src/{runtime-pi → webflo-runtime}/webflo-client/WebfloClient.js +0 -65
- package/src/{runtime-pi → webflo-runtime}/webflo-client/WebfloRootClientA.js +14 -4
- package/src/{runtime-pi → webflo-runtime}/webflo-client/bootstrap.js +1 -1
- package/src/{runtime-pi → webflo-runtime}/webflo-client/webflo-elements.js +210 -130
- package/src/webflo-runtime/webflo-client/webflo-embedded.js +56 -0
- package/src/{runtime-pi → webflo-runtime}/webflo-server/WebfloServer.js +1 -1
- package/src/{runtime-pi → webflo-runtime}/webflo-server/bootstrap.js +1 -1
- package/src/{runtime-pi → webflo-runtime}/webflo-worker/bootstrap.js +1 -1
- package/src/{services-pi → webflo-services}/cert/http-auth-hook.js +1 -1
- package/test/browser/elements.src.build.js +1239 -0
- package/test/browser/elements.src.build.js.map +7 -0
- package/test/browser/elements.src.js +3 -0
- package/test/browser/index.html +419 -0
- package/src/runtime-pi/webflo-client/webflo-embedded.js +0 -54
- package/test/index.test.js +0 -26
- package/test/site/package.json +0 -9
- package/test/site/public/bundle.html +0 -6
- package/test/site/public/bundle.html.json +0 -4
- package/test/site/public/bundle.js +0 -2
- package/test/site/public/bundle.js.gz +0 -0
- package/test/site/public/bundle.webflo.js +0 -15
- package/test/site/public/bundle.webflo.js.gz +0 -0
- package/test/site/public/index.html +0 -30
- package/test/site/public/index1.html +0 -35
- package/test/site/public/page-2/bundle.html +0 -5
- package/test/site/public/page-2/bundle.html.json +0 -1
- package/test/site/public/page-2/bundle.js +0 -2
- package/test/site/public/page-2/bundle.js.gz +0 -0
- package/test/site/public/page-2/index.html +0 -46
- package/test/site/public/page-2/logo-130x130.png +0 -0
- package/test/site/public/page-2/main.html +0 -3
- package/test/site/public/page-3/logo-130x130.png +0 -0
- package/test/site/public/page-4/subpage/bundle.html.json +0 -1
- package/test/site/public/page-4/subpage/bundle.js +0 -2
- package/test/site/public/page-4/subpage/bundle.js.gz +0 -0
- package/test/site/public/page-4/subpage/index.html +0 -31
- package/test/site/public/sparoots.json +0 -5
- package/test/site/public/worker.js +0 -3
- package/test/site/public/worker.js.gz +0 -0
- package/test/site/server/index.js +0 -16
- /package/src/{build-pi → webflo-build}/esbuild-plugin-uselive-transform.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/Client.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/Server.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/client/Worker.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/client/index.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/index.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/server/Headers.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/server/Redirects.js +0 -0
- /package/src/{config-pi → webflo-config}/runtime/server/index.js +0 -0
- /package/src/{deployment-pi → webflo-deployment}/util.js +0 -0
- /package/{test/site/public/page-4/subpage/bundle.html → src/webflo-exports/index.js} +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/.gitignore +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/.webqit/webflo/client.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/.webqit/webflo/layout.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/app/handler.server.js +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/app/page.html +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/package.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/public/assets/app.css +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/public/index.html +0 -0
- /package/src/{init-pi → webflo-init}/templates/pwa/public/manifest.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/.gitignore +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/.webqit/webflo/client.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/.webqit/webflo/layout.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/app/handler.server.js +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/app/page.html +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/package.json +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/public/assets/app.css +0 -0
- /package/src/{init-pi → webflo-init}/templates/web/public/index.html +0 -0
- /package/src/{runtime-pi → webflo-runtime}/AppBootstrap.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/AppRuntime.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/index.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/ClientSideWorkport.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/DeviceCapabilities.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/WebfloRootClientB.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/WebfloSubClient.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/index.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-client/webflo-devmode.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/ClientPortMixin.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/ClientRequestPort001.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/ClientRequestPort010.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/ClientRequestPort100.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/WebfloTenancy001.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-messaging/WebfloTenant001.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpCookies101.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpCookies110.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpEvent111.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpKeyvalInterface.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpSession001.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpSession110.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpThread111.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/HttpUser111.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/KeyvalsFactory001.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/KeyvalsFactory110.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/KeyvalsFactoryInterface.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-routing/WebfloRouter111.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-server/index.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-server/webflo-devmode.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-worker/WebfloWorker.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-worker/WorkerSideWorkport.js +0 -0
- /package/src/{runtime-pi → webflo-runtime}/webflo-worker/index.js +0 -0
- /package/src/{services-pi → webflo-services}/cert/http-cleanup-hook.js +0 -0
- /package/src/{services-pi → webflo-services}/cert/index.js +0 -0
- /package/src/{services-pi → webflo-services}/index.js +0 -0
- /package/src/{services-pi → webflo-services}/push/index.js +0 -0
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"vanila-javascript"
|
|
13
13
|
],
|
|
14
14
|
"homepage": "https://webqit.io/tooling/webflo",
|
|
15
|
-
"version": "0.20.
|
|
15
|
+
"version": "0.20.36",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -22,10 +22,16 @@
|
|
|
22
22
|
"url": "https://github.com/webqit/webflo/issues"
|
|
23
23
|
},
|
|
24
24
|
"type": "module",
|
|
25
|
-
"main": "./src/index.js",
|
|
25
|
+
"main": "./src/webflo-exports/index.js",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./src/webflo-exports/index.js",
|
|
28
|
+
"./*": "./src/webflo-exports/*/index.js",
|
|
29
|
+
"./*.js": "./src/webflo-exports/*.js"
|
|
30
|
+
},
|
|
26
31
|
"scripts": {
|
|
27
32
|
"test": "echo \"Nothing to test yet\"",
|
|
28
33
|
"build": "echo \"Nothing to build yet\"",
|
|
34
|
+
"build:test": "esbuild test/browser/*.src.js --bundle --minify --sourcemap --outdir=test/browser --entry-names=[name].build",
|
|
29
35
|
"preversion": "npm run test",
|
|
30
36
|
"postversion": "git push && git push --tags",
|
|
31
37
|
"version:next": "npm version prerelease --preid=next",
|
|
@@ -51,7 +57,7 @@
|
|
|
51
57
|
"@webqit/util": "^0.8.11",
|
|
52
58
|
"chokidar": "^4.0.3",
|
|
53
59
|
"dotenv": "^16.4.7",
|
|
54
|
-
"esbuild": "^0.14.
|
|
60
|
+
"esbuild": "^0.14.54",
|
|
55
61
|
"fast-glob": "^3.3.3",
|
|
56
62
|
"idb": "^8.0.3",
|
|
57
63
|
"mime-types": "^2.1.33",
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as config from './config
|
|
2
|
-
import * as deployment from './deployment
|
|
3
|
-
import * as runtime from './runtime
|
|
4
|
-
import * as services from './services
|
|
5
|
-
import * as
|
|
6
|
-
import * as build from './build
|
|
1
|
+
import * as config from './webflo-config/index.js';
|
|
2
|
+
import * as deployment from './webflo-deployment/index.js';
|
|
3
|
+
import * as runtime from './webflo-runtime/index.js';
|
|
4
|
+
import * as services from './webflo-services/index.js';
|
|
5
|
+
import * as init from './webflo-init/index.js';
|
|
6
|
+
import * as build from './webflo-build/index.js';
|
|
7
7
|
|
|
8
8
|
export { CLIContext } from './CLIContext.js';
|
|
9
9
|
export {
|
|
@@ -11,6 +11,6 @@ export {
|
|
|
11
11
|
deployment,
|
|
12
12
|
runtime,
|
|
13
13
|
services,
|
|
14
|
-
|
|
14
|
+
init,
|
|
15
15
|
build,
|
|
16
16
|
}
|
|
@@ -8,9 +8,9 @@ import { _afterLast, _beforeLast } from '@webqit/util/str/index.js';
|
|
|
8
8
|
import { _isObject, _isArray } from '@webqit/util/js/index.js';
|
|
9
9
|
import { jsFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
10
10
|
import { URLPatternPlus } from '@webqit/url-plus';
|
|
11
|
-
import { bootstrap as serverBootstrap } from '../runtime
|
|
12
|
-
import { bootstrap as clientBootstrap } from '../runtime
|
|
13
|
-
import { bootstrap as workerBootstrap } from '../runtime
|
|
11
|
+
import { bootstrap as serverBootstrap } from '../webflo-runtime/webflo-server/bootstrap.js';
|
|
12
|
+
import { bootstrap as clientBootstrap } from '../webflo-runtime/webflo-client/bootstrap.js';
|
|
13
|
+
import { bootstrap as workerBootstrap } from '../webflo-runtime/webflo-worker/bootstrap.js';
|
|
14
14
|
import { UseLiveTransform } from './esbuild-plugin-uselive-transform.js';
|
|
15
15
|
import { CLIContext } from '../CLIContext.js';
|
|
16
16
|
|
|
@@ -83,7 +83,7 @@ function declareRoutes({ $context, $source, bootstrap }) {
|
|
|
83
83
|
|
|
84
84
|
function writeImportWebflo($source, which) {
|
|
85
85
|
const importUrl = Url.fileURLToPath(import.meta.url);
|
|
86
|
-
const importPath = Path.join(Path.dirname(importUrl), `../runtime
|
|
86
|
+
const importPath = Path.join(Path.dirname(importUrl), `../webflo-runtime/webflo-${which}/index.js`);
|
|
87
87
|
$source.imports[importPath] = `{ start }`;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
1
|
import Fs from 'fs';
|
|
6
2
|
import Path from 'path';
|
|
7
3
|
import SimpleGit from 'simple-git';
|
|
@@ -11,16 +7,10 @@ import { _beforeLast } from '@webqit/util/str/index.js';
|
|
|
11
7
|
import { _isObject, _isNumeric } from '@webqit/util/js/index.js';
|
|
12
8
|
import Webhooks from '@octokit/webhooks';
|
|
13
9
|
|
|
14
|
-
/**
|
|
15
|
-
* @desc
|
|
16
|
-
*/
|
|
17
10
|
export const desc = {
|
|
18
11
|
deploy: 'Deploy project from a remote origin.',
|
|
19
12
|
};
|
|
20
13
|
|
|
21
|
-
/**
|
|
22
|
-
* @deploy
|
|
23
|
-
*/
|
|
24
14
|
export async function deploy(origin) {
|
|
25
15
|
const cx = this || {};
|
|
26
16
|
if (!cx.config.deployment?.Origins) {
|
|
@@ -149,9 +139,6 @@ export async function deploy(origin) {
|
|
|
149
139
|
|
|
150
140
|
}
|
|
151
141
|
|
|
152
|
-
/**
|
|
153
|
-
* @hook
|
|
154
|
-
*/
|
|
155
142
|
export async function webhook(httpEvent, router, next) {
|
|
156
143
|
const cx = this || {};
|
|
157
144
|
if (!cx.config.deployment?.Origins) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../webflo-runtime/webflo-client/webflo-elements.js';
|
|
@@ -3,7 +3,7 @@ import Fs2 from 'fs/promises';
|
|
|
3
3
|
import Path from 'path';
|
|
4
4
|
import { exec } from 'child_process';
|
|
5
5
|
import { _toTitle } from '@webqit/util/str/index.js';
|
|
6
|
-
import { readInitConfig } from '../deployment
|
|
6
|
+
import { readInitConfig } from '../webflo-deployment/util.js';
|
|
7
7
|
import { CLIContext } from '../CLIContext.js';
|
|
8
8
|
|
|
9
9
|
export const desc = {
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
class DeviceViewport {
|
|
2
|
+
|
|
3
|
+
#stack = [];
|
|
4
|
+
#ownedElements = new Set(); // Stores elements created by this class
|
|
5
|
+
#elements = {}; // Map of active elements/selectors
|
|
6
|
+
#timer = null; // For commit batching
|
|
7
|
+
|
|
8
|
+
#specials = {
|
|
9
|
+
themeColor: { name: 'theme-color', type: 'meta' },
|
|
10
|
+
appleStatusBarStyle: { name: 'apple-mobile-web-app-status-bar-style', type: 'meta' },
|
|
11
|
+
colorScheme: { name: 'color-scheme', type: 'meta' },
|
|
12
|
+
manifest: { name: 'manifest', type: 'link' }
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
const initialState = { _isInitial: true };
|
|
17
|
+
|
|
18
|
+
// 1. Ingest Viewport
|
|
19
|
+
const vMeta = document.querySelector('meta[name="viewport"]');
|
|
20
|
+
if (vMeta) {
|
|
21
|
+
this.#elements.viewport = vMeta;
|
|
22
|
+
Object.assign(initialState, this.#parseViewport(vMeta.content));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 2. Ingest Title & Specials
|
|
26
|
+
initialState.title = document.title;
|
|
27
|
+
Object.entries(this.#specials).forEach(([jsKey, config]) => {
|
|
28
|
+
const el = this.#findDom(config);
|
|
29
|
+
if (el) {
|
|
30
|
+
this.#elements[jsKey] = el;
|
|
31
|
+
initialState[jsKey] = config.type === 'link' ? el.getAttribute('href') : el.getAttribute('content');
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
this.#stack.push(initialState);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#findDom({ name, type }) {
|
|
39
|
+
return type === 'link'
|
|
40
|
+
? document.querySelector(`link[rel="${name}"]`)
|
|
41
|
+
: document.querySelector(`meta[name="${name}"]`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#getOrCreate(jsKey, media = null) {
|
|
45
|
+
const cacheKey = media ? `${jsKey}-${media}` : jsKey;
|
|
46
|
+
if (this.#elements[cacheKey]) return this.#elements[cacheKey];
|
|
47
|
+
|
|
48
|
+
const config = this.#specials[jsKey] || { name: 'viewport', type: 'meta' };
|
|
49
|
+
const el = document.createElement(config.type);
|
|
50
|
+
|
|
51
|
+
if (config.type === 'link') el.rel = config.name;
|
|
52
|
+
else el.name = config.name;
|
|
53
|
+
if (media) el.setAttribute('media', media);
|
|
54
|
+
|
|
55
|
+
document.head.appendChild(el);
|
|
56
|
+
this.#ownedElements.add(el);
|
|
57
|
+
this.#elements[cacheKey] = el;
|
|
58
|
+
return el;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#scheduleRender() {
|
|
62
|
+
if (this.#timer) return;
|
|
63
|
+
this.#timer = requestAnimationFrame(() => {
|
|
64
|
+
this.#render();
|
|
65
|
+
this.#timer = null;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#render() {
|
|
70
|
+
const state = this.peek();
|
|
71
|
+
const viewportDirectives = [];
|
|
72
|
+
const activeKeys = new Set(Object.keys(state).filter(k => !k.startsWith('_')));
|
|
73
|
+
|
|
74
|
+
// 1. Handle Title
|
|
75
|
+
if ('title' in state) {
|
|
76
|
+
document.title = state.title || '';
|
|
77
|
+
activeKeys.delete('title');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 2. Handle Specials (with Media Query Support)
|
|
81
|
+
Object.keys(this.#specials).forEach(jsKey => {
|
|
82
|
+
const val = state[jsKey]; // Can be string or { default, dark, light, "(media)": color }
|
|
83
|
+
activeKeys.delete(jsKey);
|
|
84
|
+
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
|
|
87
|
+
if (val && typeof val === 'object' && jsKey === 'themeColor') {
|
|
88
|
+
// Media Query Logic
|
|
89
|
+
Object.entries(val).forEach(([query, color]) => {
|
|
90
|
+
const mediaStr = query === 'dark' ? '(prefers-color-scheme: dark)' :
|
|
91
|
+
query === 'light' ? '(prefers-color-scheme: light)' :
|
|
92
|
+
query === 'default' ? '' : query;
|
|
93
|
+
seen.add(mediaStr);
|
|
94
|
+
this.#setAttr(jsKey, color, mediaStr);
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
seen.add('');
|
|
98
|
+
this.#setAttr(jsKey, val);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// cleanup
|
|
102
|
+
Object.keys(this.#elements)
|
|
103
|
+
.filter(k => k === jsKey || k.startsWith(`${jsKey}-`))
|
|
104
|
+
.forEach(k => {
|
|
105
|
+
const keyId = k === jsKey ? '' : k.slice(jsKey.length + 1);
|
|
106
|
+
if (!seen.has(keyId)) {
|
|
107
|
+
this.#setAttr(jsKey, null, keyId);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 3. Handle Viewport
|
|
113
|
+
activeKeys.forEach(key => {
|
|
114
|
+
const val = state[key];
|
|
115
|
+
if (val === null) return;
|
|
116
|
+
const kebab = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
117
|
+
viewportDirectives.push(val === true ? kebab : `${kebab}=${val}`);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const vContent = viewportDirectives.join(', ');
|
|
121
|
+
const vEl = this.#elements.viewport || (vContent ? this.#getOrCreate('viewport') : null);
|
|
122
|
+
if (vEl) {
|
|
123
|
+
vEl.setAttribute('content', vContent);
|
|
124
|
+
if (!vContent && this.#ownedElements.has(vEl)) {
|
|
125
|
+
vEl.remove();
|
|
126
|
+
delete this.#elements.viewport;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#setAttr(jsKey, val, media = null) {
|
|
132
|
+
const cacheKey = media ? `${jsKey}-${media}` : jsKey;
|
|
133
|
+
const config = this.#specials[jsKey];
|
|
134
|
+
|
|
135
|
+
if (val !== undefined && val !== null) {
|
|
136
|
+
const el = this.#getOrCreate(jsKey, media);
|
|
137
|
+
el.setAttribute(config.type === 'link' ? 'href' : 'content', val);
|
|
138
|
+
} else {
|
|
139
|
+
const el = this.#elements[cacheKey];
|
|
140
|
+
if (el) {
|
|
141
|
+
if (this.#ownedElements.has(el)) {
|
|
142
|
+
el.remove();
|
|
143
|
+
delete this.#elements[cacheKey];
|
|
144
|
+
} else {
|
|
145
|
+
el.setAttribute(config.type === 'link' ? 'href' : 'content', '');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#parseViewport = (c) => Object.fromEntries(c.split(',').filter(Boolean).map(s => {
|
|
152
|
+
const [k, v] = s.split('=').map(p => p.trim());
|
|
153
|
+
return [k.replace(/-([a-z])/g, g => g.toUpperCase()), v || true];
|
|
154
|
+
}));
|
|
155
|
+
|
|
156
|
+
push(id, config) {
|
|
157
|
+
if (!id) throw new Error("push() requires a unique ID");
|
|
158
|
+
if (this.#stack.some(e => e.id === id)) return;
|
|
159
|
+
this.#stack.push({ ...this.peek(), ...config, id, _isInitial: false });
|
|
160
|
+
this.#scheduleRender();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
pop(id) {
|
|
164
|
+
if (!id) throw new Error("pop() requires a target ID");
|
|
165
|
+
const idx = this.#stack.findIndex(e => e.id === id);
|
|
166
|
+
if (idx > 0) { // Never pop the initial state at index 0
|
|
167
|
+
this.#stack.splice(idx, 1);
|
|
168
|
+
this.#scheduleRender();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
peek() { return this.#stack[this.#stack.length - 1]; }
|
|
173
|
+
}
|
|
@@ -35,9 +35,6 @@ export class WebfloClient extends AppRuntime {
|
|
|
35
35
|
#background;
|
|
36
36
|
get background() { return this.#background; }
|
|
37
37
|
|
|
38
|
-
#viewport;
|
|
39
|
-
get viewport() { return this.#viewport; }
|
|
40
|
-
|
|
41
38
|
get isClientSide() { return true; }
|
|
42
39
|
|
|
43
40
|
constructor(bootstrap, host) {
|
|
@@ -59,68 +56,6 @@ export class WebfloClient extends AppRuntime {
|
|
|
59
56
|
phase: 0
|
|
60
57
|
};
|
|
61
58
|
this.#background = new StarPort({ handshake: 1, autoClose: false });
|
|
62
|
-
|
|
63
|
-
// ---------------------
|
|
64
|
-
// Dynamic viewport styling
|
|
65
|
-
|
|
66
|
-
const oskToken = 'interactive-widget=resizes-content';
|
|
67
|
-
const hasOsk = (content) => content?.includes(oskToken);
|
|
68
|
-
const removeOsk = (content) => {
|
|
69
|
-
if (content?.includes('interactive-widget')) {
|
|
70
|
-
return content
|
|
71
|
-
.split(',')
|
|
72
|
-
.filter((s) => !s.includes('interactive-widget'))
|
|
73
|
-
.map((s) => s.trim())
|
|
74
|
-
.join(', ');
|
|
75
|
-
}
|
|
76
|
-
return content;
|
|
77
|
-
};
|
|
78
|
-
const addOsk = (content) => {
|
|
79
|
-
if (content?.includes('interactive-widget')) {
|
|
80
|
-
return content
|
|
81
|
-
.split(',')
|
|
82
|
-
.map((s) => s.includes('interactive-widget') ? oskToken : s.trim())
|
|
83
|
-
.join(', ');
|
|
84
|
-
}
|
|
85
|
-
return content + ', ' + oskToken;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const viewportMeta = document.querySelector('meta[name="viewport"]');
|
|
89
|
-
const viewportMetaInitialContent = viewportMeta?.content;
|
|
90
|
-
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
|
|
91
|
-
const renderViewportMetas = (entry) => {
|
|
92
|
-
viewportMeta?.setAttribute('content', entry.osk ? addOsk(viewportMetaInitialContent) : removeOsk(viewportMetaInitialContent));
|
|
93
|
-
themeColorMeta?.setAttribute('content', entry.themeColor);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const initial = {
|
|
97
|
-
themeColor: themeColorMeta?.content,
|
|
98
|
-
osk: hasOsk(viewportMetaInitialContent),
|
|
99
|
-
};
|
|
100
|
-
const viewportStack = [initial];
|
|
101
|
-
|
|
102
|
-
this.#viewport = {
|
|
103
|
-
push(entryId, { themeColor = viewportStack[0].themeColor, osk = viewportStack[0].osk }) {
|
|
104
|
-
if (typeof entryId !== 'string' || !entryId?.trim()) {
|
|
105
|
-
throw new Error('entryId cannot be ommited');
|
|
106
|
-
}
|
|
107
|
-
if (viewportStack.find((e) => e.entryId === entryId)) return;
|
|
108
|
-
viewportStack.unshift({ entryId, themeColor, osk });
|
|
109
|
-
renderViewportMetas(viewportStack[0]);
|
|
110
|
-
},
|
|
111
|
-
pop(entryId) {
|
|
112
|
-
if (typeof entryId !== 'string' || !entryId?.trim()) {
|
|
113
|
-
throw new Error('entryId cannot be ommited');
|
|
114
|
-
}
|
|
115
|
-
const index = viewportStack.findIndex((e) => e.entryId === entryId);
|
|
116
|
-
if (index === -1) return;
|
|
117
|
-
viewportStack.splice(index, 1);
|
|
118
|
-
renderViewportMetas(viewportStack[0]);
|
|
119
|
-
},
|
|
120
|
-
current() {
|
|
121
|
-
return viewportStack[0];
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
59
|
}
|
|
125
60
|
|
|
126
61
|
async initialize() {
|
|
@@ -3,6 +3,7 @@ import { LiveResponse } from '@webqit/fetch-plus';
|
|
|
3
3
|
import { HttpEvent111 } from '../webflo-routing/HttpEvent111.js';
|
|
4
4
|
import { ClientSideWorkport } from './ClientSideWorkport.js';
|
|
5
5
|
import { DeviceCapabilities } from './DeviceCapabilities.js';
|
|
6
|
+
import { DeviceViewport } from './DeviceViewport.js';
|
|
6
7
|
import { WebfloClient } from './WebfloClient.js';
|
|
7
8
|
import { WebfloHMR } from './webflo-devmode.js';
|
|
8
9
|
|
|
@@ -12,6 +13,8 @@ export class WebfloRootClientA extends WebfloClient {
|
|
|
12
13
|
|
|
13
14
|
static get DeviceCapabilities() { return DeviceCapabilities; }
|
|
14
15
|
|
|
16
|
+
static get DeviceViewport() { return DeviceViewport; }
|
|
17
|
+
|
|
15
18
|
static create(bootstrap, host) {
|
|
16
19
|
return new this(bootstrap, host);
|
|
17
20
|
}
|
|
@@ -19,12 +22,15 @@ export class WebfloRootClientA extends WebfloClient {
|
|
|
19
22
|
#network;
|
|
20
23
|
get network() { return this.#network; }
|
|
21
24
|
|
|
22
|
-
#
|
|
23
|
-
get
|
|
25
|
+
#viewport;
|
|
26
|
+
get viewport() { return this.#viewport; }
|
|
24
27
|
|
|
25
28
|
#capabilities;
|
|
26
29
|
get capabilities() { return this.#capabilities; }
|
|
27
30
|
|
|
31
|
+
#workport;
|
|
32
|
+
get workport() { return this.#workport; }
|
|
33
|
+
|
|
28
34
|
#hmr;
|
|
29
35
|
|
|
30
36
|
get withViewTransitions() {
|
|
@@ -67,10 +73,14 @@ export class WebfloRootClientA extends WebfloClient {
|
|
|
67
73
|
|
|
68
74
|
async setupCapabilities() {
|
|
69
75
|
const instanceController = await super.setupCapabilities();
|
|
70
|
-
const cleanups = [];
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
const cleanups = [];
|
|
73
78
|
instanceController.signal.addEventListener('abort', () => cleanups.forEach((c) => c()), { once: true });
|
|
79
|
+
|
|
80
|
+
// DeviceViewport, DeviceCapabilities, & Service Worker
|
|
81
|
+
|
|
82
|
+
this.#viewport = new this.constructor.DeviceViewport();
|
|
83
|
+
|
|
74
84
|
this.#capabilities = await this.constructor.DeviceCapabilities.initialize(this, this.config.CLIENT.capabilities);
|
|
75
85
|
cleanups.push(() => this.#capabilities.close());
|
|
76
86
|
|