ewvjs 1.0.12 → 1.0.14
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.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/js/api.js +100 -1
- package/dist/platforms/windows.d.ts.map +1 -1
- package/dist/platforms/windows.js +8 -9
- package/dist/webview.d.ts +1 -2
- package/dist/webview.d.ts.map +1 -1
- package/dist/webview.js +25 -57
- package/native/WebView.dll +0 -0
- package/native/runtimes/win-arm64/native/WebView2Loader.dll +0 -0
- package/native/runtimes/win-x64/native/WebView2Loader.dll +0 -0
- package/native/runtimes/win-x86/native/WebView2Loader.dll +0 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { Window } from './window.js';
|
|
|
4
4
|
import { WebView } from './webview.js';
|
|
5
5
|
declare const ewvjs: WebView;
|
|
6
6
|
export default ewvjs;
|
|
7
|
-
export declare const create_window: (title: string, url_or_html?: string, options?: Partial<import("./types.js").WindowOptions>) => import("./window.js").Window
|
|
7
|
+
export declare const create_window: (title: string, url_or_html?: string, options?: Partial<import("./types.js").WindowOptions>) => Promise<import("./window.js").Window>;
|
|
8
8
|
export declare const start: () => Promise<void>;
|
|
9
9
|
export declare const expose: (name: string, func: Function) => void;
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAA,MAAM,KAAK,SAAgB,CAAC;AAC5B,eAAe,KAAK,CAAC;AAGrB,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAA,MAAM,KAAK,SAAgB,CAAC;AAC5B,eAAe,KAAK,CAAC;AAGrB,eAAO,MAAM,aAAa,uIAAkC,CAAC;AAC7D,eAAO,MAAM,KAAK,qBAA0B,CAAC;AAC7C,eAAO,MAAM,MAAM,wCAA2B,CAAC"}
|
package/dist/js/api.js
CHANGED
|
@@ -6,15 +6,113 @@ window.ewvjs = {
|
|
|
6
6
|
_returnValuesCallbacks: {},
|
|
7
7
|
|
|
8
8
|
_hookDrag: function () {
|
|
9
|
+
var lastClickTime = 0;
|
|
9
10
|
window.addEventListener('mousedown', function (e) {
|
|
10
11
|
if (e.target.classList.contains('ewvjs-drag-region') || e.target.closest('.ewvjs-drag-region')) {
|
|
11
12
|
if (e.button === 0) { // Left click
|
|
12
|
-
|
|
13
|
+
var now = e.timeStamp;
|
|
14
|
+
if (now - lastClickTime < 500) {
|
|
15
|
+
if (window.__isWindowMaximized) {
|
|
16
|
+
window.restore();
|
|
17
|
+
} else {
|
|
18
|
+
window.maximize();
|
|
19
|
+
}
|
|
20
|
+
lastClickTime = 0;
|
|
21
|
+
} else {
|
|
22
|
+
window.chrome.webview.postMessage("drag");
|
|
23
|
+
lastClickTime = now;
|
|
24
|
+
}
|
|
13
25
|
}
|
|
14
26
|
}
|
|
15
27
|
});
|
|
16
28
|
},
|
|
17
29
|
|
|
30
|
+
_hookResize: function () {
|
|
31
|
+
var resizeBorder = 8;
|
|
32
|
+
var styleEl = null;
|
|
33
|
+
|
|
34
|
+
function getDirection(e) {
|
|
35
|
+
if (!window.__isTitleBarDisabled || window.__isWindowMaximized) return null;
|
|
36
|
+
|
|
37
|
+
var x = e.clientX;
|
|
38
|
+
var y = e.clientY;
|
|
39
|
+
var w = window.innerWidth;
|
|
40
|
+
var h = window.innerHeight;
|
|
41
|
+
|
|
42
|
+
var onLeft = x < resizeBorder;
|
|
43
|
+
var onRight = x > w - resizeBorder;
|
|
44
|
+
var onTop = y < resizeBorder;
|
|
45
|
+
var onBottom = y > h - resizeBorder;
|
|
46
|
+
|
|
47
|
+
if (onTop && onLeft) return "topleft";
|
|
48
|
+
if (onTop && onRight) return "topright";
|
|
49
|
+
if (onBottom && onLeft) return "bottomleft";
|
|
50
|
+
if (onBottom && onRight) return "bottomright";
|
|
51
|
+
if (onTop) return "top";
|
|
52
|
+
if (onBottom) return "bottom";
|
|
53
|
+
if (onLeft) return "left";
|
|
54
|
+
if (onRight) return "right";
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function setOverrideCursor(cursor) {
|
|
59
|
+
if (!styleEl) {
|
|
60
|
+
styleEl = document.getElementById("ewvjs-cursor-override-style");
|
|
61
|
+
if (!styleEl) {
|
|
62
|
+
styleEl = document.createElement("style");
|
|
63
|
+
styleEl.id = "ewvjs-cursor-override-style";
|
|
64
|
+
styleEl.type = "text/css";
|
|
65
|
+
(document.head || document.documentElement).appendChild(styleEl);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
var css = "* { cursor: " + cursor + " !important; }";
|
|
69
|
+
if (styleEl.textContent !== css) {
|
|
70
|
+
styleEl.textContent = css;
|
|
71
|
+
}
|
|
72
|
+
if (document.documentElement.style.getPropertyValue("cursor") !== cursor) {
|
|
73
|
+
document.documentElement.style.setProperty("cursor", cursor, "important");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function clearOverrideCursor() {
|
|
78
|
+
if (styleEl) {
|
|
79
|
+
styleEl.textContent = "";
|
|
80
|
+
} else {
|
|
81
|
+
var el = document.getElementById("ewvjs-cursor-override-style");
|
|
82
|
+
if (el) {
|
|
83
|
+
el.textContent = "";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (document.documentElement.style.getPropertyValue("cursor")) {
|
|
87
|
+
document.documentElement.style.removeProperty("cursor");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
window.addEventListener('mousemove', function (e) {
|
|
92
|
+
var dir = getDirection(e);
|
|
93
|
+
if (dir) {
|
|
94
|
+
var cursor = "";
|
|
95
|
+
if (dir === "top" || dir === "bottom") cursor = "ns-resize";
|
|
96
|
+
else if (dir === "left" || dir === "right") cursor = "ew-resize";
|
|
97
|
+
else if (dir === "topleft" || dir === "bottomright") cursor = "nwse-resize";
|
|
98
|
+
else if (dir === "topright" || dir === "bottomleft") cursor = "nesw-resize";
|
|
99
|
+
|
|
100
|
+
setOverrideCursor(cursor);
|
|
101
|
+
} else {
|
|
102
|
+
clearOverrideCursor();
|
|
103
|
+
}
|
|
104
|
+
}, true);
|
|
105
|
+
|
|
106
|
+
window.addEventListener('mousedown', function (e) {
|
|
107
|
+
var dir = getDirection(e);
|
|
108
|
+
if (dir && e.button === 0) {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
e.stopPropagation();
|
|
111
|
+
window.chrome.webview.postMessage("resize:" + dir);
|
|
112
|
+
}
|
|
113
|
+
}, true);
|
|
114
|
+
},
|
|
115
|
+
|
|
18
116
|
_createApi: function (funcList) {
|
|
19
117
|
function sanitize_params(params) {
|
|
20
118
|
var reservedWords = [
|
|
@@ -263,6 +361,7 @@ window.ewvjs._hookConsole = function () {
|
|
|
263
361
|
|
|
264
362
|
window.ewvjs._hookConsole();
|
|
265
363
|
window.ewvjs._hookDrag();
|
|
364
|
+
window.ewvjs._hookResize();
|
|
266
365
|
|
|
267
366
|
// Add window state methods directly to window object
|
|
268
367
|
window.close = function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windows.d.ts","sourceRoot":"","sources":["../../src/platforms/windows.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"windows.d.ts","sourceRoot":"","sources":["../../src/platforms/windows.ts"],"names":[],"mappings":"AAaA,qBAAa,eAAe;;IAKxB,YAAY,CAAC,OAAO,EAAE,GAAG;CA0G5B"}
|
|
@@ -6,6 +6,8 @@ import { createRequire } from 'module';
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
9
|
+
// Cache the injected API script so it's only read from disk once
|
|
10
|
+
let _cachedApiScript = null;
|
|
9
11
|
export class WindowsPlatform {
|
|
10
12
|
constructor() {
|
|
11
13
|
}
|
|
@@ -56,20 +58,17 @@ export class WindowsPlatform {
|
|
|
56
58
|
console.error("Failed to load native module from " + dllDir, e);
|
|
57
59
|
throw e;
|
|
58
60
|
}
|
|
59
|
-
// Prepare initScript
|
|
61
|
+
// Prepare initScript — read & cache once, then reuse
|
|
60
62
|
const token = Math.random().toString(36).substring(2, 15);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
if (_cachedApiScript === null) {
|
|
64
|
+
_cachedApiScript = fs.readFileSync(apiPath, 'utf8');
|
|
65
|
+
}
|
|
66
|
+
const apiScript = _cachedApiScript.replace('%(token)s', token);
|
|
63
67
|
options.initScript = apiScript;
|
|
64
68
|
// Handle messages from WebView
|
|
65
|
-
// options.onMessage will be called by C#
|
|
66
|
-
// We must keep the Node process alive while the window is open, similar to how edge-js performed.
|
|
67
|
-
const keepAlive = setInterval(() => { }, 5000);
|
|
68
69
|
options.onMessage = (message, callback) => {
|
|
69
|
-
// Check for close message
|
|
70
|
-
// Message from C# on close is explicit string: "[\"closed\", \"\"]"
|
|
70
|
+
// Check for close message
|
|
71
71
|
if (message === '["closed", ""]' || (Array.isArray(message) && message[0] === 'closed')) {
|
|
72
|
-
clearInterval(keepAlive);
|
|
73
72
|
}
|
|
74
73
|
if (typeof message === 'string') {
|
|
75
74
|
try {
|
package/dist/webview.d.ts
CHANGED
|
@@ -12,13 +12,12 @@ export declare class WebView {
|
|
|
12
12
|
private _resolveOnce;
|
|
13
13
|
private _httpServers;
|
|
14
14
|
constructor();
|
|
15
|
-
create_window(title: string, url_or_html?: string, options?: Partial<WindowOptions>): Window
|
|
15
|
+
create_window(title: string, url_or_html?: string, options?: Partial<WindowOptions>): Promise<Window>;
|
|
16
16
|
start(): Promise<void>;
|
|
17
17
|
private _cleanup;
|
|
18
18
|
expose(name: string, func: Function): void;
|
|
19
19
|
_handle_message(message: any): Promise<void>;
|
|
20
20
|
private _getMimeType;
|
|
21
|
-
private _findFreePort;
|
|
22
21
|
private _createHttpServer;
|
|
23
22
|
private _buildWindowOptions;
|
|
24
23
|
}
|
package/dist/webview.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview.d.ts","sourceRoot":"","sources":["../src/webview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"webview.d.ts","sourceRoot":"","sources":["../src/webview.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAU3C,qBAAa,OAAO;IACnB,QAAQ,EAAE,GAAG,CAAC;IACd,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAM;IACpD,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,YAAY,CAAuC;;IAUrD,aAAa,CAClB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,MAAW,EACxB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,OAAO,CAAC,QAAQ;IAyBhB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAIpC,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,iBAAiB;YAiDX,mBAAmB;CAwCjC"}
|
package/dist/webview.js
CHANGED
|
@@ -4,7 +4,6 @@ import * as http from "http";
|
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import mime from "mime-types";
|
|
7
|
-
import { execSync } from "child_process";
|
|
8
7
|
import { fileURLToPath } from 'url';
|
|
9
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
9
|
const __dirname = path.dirname(__filename);
|
|
@@ -25,8 +24,8 @@ export class WebView {
|
|
|
25
24
|
throw new Error("Platform not supported: " + process.platform);
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
|
-
create_window(title, url_or_html = "", options = {}) {
|
|
29
|
-
const opts = this._buildWindowOptions(title, url_or_html, options);
|
|
27
|
+
async create_window(title, url_or_html = "", options = {}) {
|
|
28
|
+
const opts = await this._buildWindowOptions(title, url_or_html, options);
|
|
30
29
|
const window = new Window(this.platform, opts, this.exposed_functions);
|
|
31
30
|
this._windows.add(window);
|
|
32
31
|
window.closed.then(() => {
|
|
@@ -80,59 +79,22 @@ export class WebView {
|
|
|
80
79
|
const ext = path.extname(filePath).toLowerCase();
|
|
81
80
|
return mime.lookup(ext) || "application/octet-stream";
|
|
82
81
|
}
|
|
83
|
-
_findFreePort() {
|
|
84
|
-
// Use execSync to find a free port synchronously
|
|
85
|
-
const script = `
|
|
86
|
-
import net from 'net';
|
|
87
|
-
const server = net.createServer();
|
|
88
|
-
server.listen(0, 'localhost', () => {
|
|
89
|
-
console.log(server.address().port);
|
|
90
|
-
server.close();
|
|
91
|
-
});
|
|
92
|
-
`;
|
|
93
|
-
try {
|
|
94
|
-
const output = execSync(`node --input-type=module -e "${script.replace(/"/g, '\\"').replace(/\n/g, " ")}"`, {
|
|
95
|
-
encoding: "utf-8",
|
|
96
|
-
timeout: 5000,
|
|
97
|
-
});
|
|
98
|
-
const port = parseInt(output.trim(), 10);
|
|
99
|
-
if (isNaN(port)) {
|
|
100
|
-
throw new Error("Failed to parse port");
|
|
101
|
-
}
|
|
102
|
-
return port;
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
// Fallback to port range
|
|
106
|
-
return 3000 + Math.floor(Math.random() * 1000);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
82
|
_createHttpServer(filePath) {
|
|
110
|
-
//
|
|
83
|
+
// Return cached server URL if already serving this file
|
|
111
84
|
if (this._httpServers.has(filePath)) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return `http://localhost:${addr.port}`;
|
|
117
|
-
}
|
|
85
|
+
const existing = this._httpServers.get(filePath);
|
|
86
|
+
const addr = existing.address();
|
|
87
|
+
if (addr && typeof addr === "object") {
|
|
88
|
+
return Promise.resolve(`http://localhost:${addr.port}`);
|
|
118
89
|
}
|
|
119
90
|
}
|
|
120
|
-
// Resolve relative
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
mainDir = path.dirname(process.argv[1]);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
mainDir = process.cwd();
|
|
129
|
-
}
|
|
130
|
-
absolutePath = path.resolve(mainDir, filePath);
|
|
131
|
-
console.log(`Serving ${absolutePath} at ${filePath}`);
|
|
91
|
+
// Resolve the file path relative to the main script directory
|
|
92
|
+
const mainDir = process.argv[1]
|
|
93
|
+
? path.dirname(process.argv[1])
|
|
94
|
+
: process.cwd();
|
|
95
|
+
const absolutePath = path.resolve(mainDir, filePath);
|
|
132
96
|
const dir = path.dirname(absolutePath);
|
|
133
97
|
const fileName = path.basename(absolutePath);
|
|
134
|
-
// Find a free port first
|
|
135
|
-
const port = this._findFreePort();
|
|
136
98
|
const server = http.createServer((req, res) => {
|
|
137
99
|
const requestPath = req.url === "/" ? fileName : req.url.substring(1);
|
|
138
100
|
const fullPath = path.join(dir, requestPath);
|
|
@@ -152,12 +114,17 @@ export class WebView {
|
|
|
152
114
|
res.end(data);
|
|
153
115
|
});
|
|
154
116
|
});
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
117
|
+
// listen(0) asks the OS to assign a free port instantly — no external process needed
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
server.on("error", reject);
|
|
120
|
+
server.listen(0, "localhost", () => {
|
|
121
|
+
const addr = server.address();
|
|
122
|
+
this._httpServers.set(filePath, server);
|
|
123
|
+
resolve(`http://localhost:${addr.port}`);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
159
126
|
}
|
|
160
|
-
_buildWindowOptions(title, url_or_html, options) {
|
|
127
|
+
async _buildWindowOptions(title, url_or_html, options) {
|
|
161
128
|
const opts = {
|
|
162
129
|
title: title,
|
|
163
130
|
width: options.width || 800,
|
|
@@ -181,8 +148,9 @@ export class WebView {
|
|
|
181
148
|
opts.url = url_or_html;
|
|
182
149
|
}
|
|
183
150
|
else if (url_or_html.toLowerCase().endsWith(".html")) {
|
|
184
|
-
//
|
|
185
|
-
|
|
151
|
+
// Serve the HTML file via a local HTTP server;
|
|
152
|
+
// listen(0) lets the OS pick a free port with zero overhead
|
|
153
|
+
opts.url = await this._createHttpServer(url_or_html);
|
|
186
154
|
}
|
|
187
155
|
else {
|
|
188
156
|
opts.html = url_or_html;
|
package/native/WebView.dll
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|