mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
feat: Support for building ImHex for the web (#1328)
Co-authored-by: WerWolv <werwolv98@gmail.com> Co-authored-by: AnnsAnn <git@annsann.eu>
This commit is contained in:
75
dist/web/source/enable-threads.js
vendored
Normal file
75
dist/web/source/enable-threads.js
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// NOTE: This file creates a service worker that cross-origin-isolates the page (read more here: https://web.dev/coop-coep/) which allows us to use wasm threads.
|
||||
// Normally you would set the COOP and COEP headers on the server to do this, but Github Pages doesn't allow this, so this is a hack to do that.
|
||||
|
||||
/* Edited version of: coi-serviceworker v0.1.6 - Guido Zuidhof, licensed under MIT */
|
||||
// From here: https://github.com/gzuidhof/coi-serviceworker
|
||||
if(typeof window === 'undefined') {
|
||||
self.addEventListener("install", () => self.skipWaiting());
|
||||
self.addEventListener("activate", e => e.waitUntil(self.clients.claim()));
|
||||
|
||||
async function handleFetch(request) {
|
||||
if(request.cache === "only-if-cached" && request.mode !== "same-origin") {
|
||||
return;
|
||||
}
|
||||
|
||||
if(request.mode === "no-cors") { // We need to set `credentials` to "omit" for no-cors requests, per this comment: https://bugs.chromium.org/p/chromium/issues/detail?id=1309901#c7
|
||||
request = new Request(request.url, {
|
||||
cache: request.cache,
|
||||
credentials: "omit",
|
||||
headers: request.headers,
|
||||
integrity: request.integrity,
|
||||
destination: request.destination,
|
||||
keepalive: request.keepalive,
|
||||
method: request.method,
|
||||
mode: request.mode,
|
||||
redirect: request.redirect,
|
||||
referrer: request.referrer,
|
||||
referrerPolicy: request.referrerPolicy,
|
||||
signal: request.signal,
|
||||
});
|
||||
}
|
||||
|
||||
let r = await fetch(request).catch(e => console.error(e));
|
||||
|
||||
if(r.status === 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
const headers = new Headers(r.headers);
|
||||
headers.set("Cross-Origin-Embedder-Policy", "require-corp"); // or: require-corp
|
||||
headers.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||
|
||||
return new Response(r.body, { status: r.status, statusText: r.statusText, headers });
|
||||
}
|
||||
|
||||
self.addEventListener("fetch", function(e) {
|
||||
e.respondWith(handleFetch(e.request)); // respondWith must be executed synchonously (but can be passed a Promise)
|
||||
});
|
||||
|
||||
} else {
|
||||
(async function() {
|
||||
if(window.crossOriginIsolated !== false) return;
|
||||
|
||||
let registration = await navigator.serviceWorker.register(window.document.currentScript.src).catch(e => console.error("COOP/COEP Service Worker failed to register:", e));
|
||||
if(registration) {
|
||||
console.log("COOP/COEP Service Worker registered", registration.scope);
|
||||
|
||||
registration.addEventListener("updatefound", () => {
|
||||
console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
// If the registration is active, but it's not controlling the page
|
||||
if(registration.active && !navigator.serviceWorker.controller) {
|
||||
console.log("Reloading page to make use of COOP/COEP Service Worker.");
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
// Code to deregister:
|
||||
// let registrations = await navigator.serviceWorker.getRegistrations();
|
||||
// for(let registration of registrations) {
|
||||
// await registration.unregister();
|
||||
// }
|
||||
BIN
dist/web/source/favicon.ico
vendored
Normal file
BIN
dist/web/source/favicon.ico
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
73
dist/web/source/index.html
vendored
Normal file
73
dist/web/source/index.html
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>ImHex - Hex Editor</title>
|
||||
<meta name="title" content="ImHex">
|
||||
<meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="og:title" content="ImHex Web">
|
||||
<meta property="og:description">
|
||||
<meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
|
||||
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="twitter:title" content="ImHex Web">
|
||||
<meta property="twitter:description"
|
||||
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
|
||||
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"alumni": "WerWolv",
|
||||
"email": "hey@werwolv.net",
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.png"
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "ImHex",
|
||||
"operatingSystem": "Windows, MacOS, Linux",
|
||||
"applicationCategory": "DeveloperApplication",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<title>ImHex Web</title>
|
||||
<script src="enable-threads.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<p id="loading_text">ImHex is loading...</p>
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" style="display: none; image-rendering: crisp-edges"></canvas>
|
||||
|
||||
<script type="text/javascript" src="wasm-config.js"></script>
|
||||
<script async type="text/javascript" src="imhex.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
28
dist/web/source/style.css
vendored
Normal file
28
dist/web/source/style.css
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #121212;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.emscripten {
|
||||
padding-right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
border: 0px none;
|
||||
}
|
||||
|
||||
#loading_text {
|
||||
color: #F0F0F0;
|
||||
font-size: 30px;
|
||||
font-family: monospace;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
68
dist/web/source/wasm-config.js
vendored
Normal file
68
dist/web/source/wasm-config.js
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
function glfwSetCursorCustom(wnd, shape) {
|
||||
let body = document.getElementsByTagName("body")[0]
|
||||
switch (shape) {
|
||||
case 0x00036001: // GLFW_ARROW_CURSOR
|
||||
body.style.cursor = "default";
|
||||
break;
|
||||
case 0x00036002: // GLFW_IBEAM_CURSOR
|
||||
body.style.cursor = "text";
|
||||
break;
|
||||
case 0x00036003: // GLFW_CROSSHAIR_CURSOR
|
||||
body.style.cursor = "crosshair";
|
||||
break;
|
||||
case 0x00036004: // GLFW_HAND_CURSOR
|
||||
body.style.cursor = "pointer";
|
||||
break;
|
||||
case 0x00036005: // GLFW_HRESIZE_CURSOR
|
||||
body.style.cursor = "ew-resize";
|
||||
break;
|
||||
case 0x00036006: // GLFW_VRESIZE_CURSOR
|
||||
body.style.cursor = "ns-resize";
|
||||
break;
|
||||
default:
|
||||
body.style.cursor = "default";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function glfwCreateStandardCursorCustom(shape) {
|
||||
return shape
|
||||
}
|
||||
|
||||
var Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
onRuntimeInitialized: function() {
|
||||
// Triggered when the wasm module is loaded and ready to use.
|
||||
document.getElementById("loading_text").style.display = "none"
|
||||
document.getElementById("canvas").style.display = "initial"
|
||||
},
|
||||
print: (function() { })(),
|
||||
printErr: function(text) { },
|
||||
canvas: (function() {
|
||||
let canvas = document.getElementById('canvas');
|
||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
||||
// application robust, you may want to override this behavior before shipping!
|
||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||
|
||||
return canvas;
|
||||
})(),
|
||||
setStatus: function(text) { },
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) { },
|
||||
instantiateWasm: function(imports, successCallback) {
|
||||
imports.env.glfwSetCursor = glfwSetCursorCustom
|
||||
imports.env.glfwCreateStandardCursor = glfwCreateStandardCursorCustom
|
||||
instantiateAsync(wasmBinary, wasmBinaryFile, imports, (result) => successCallback(result.instance, result.module));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
window.addEventListener('resize', js_resizeCanvas, false);
|
||||
function js_resizeCanvas() {
|
||||
let canvas = document.getElementById('canvas');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
Reference in New Issue
Block a user