Support for import as module, wabac.js 2.20 (#364)

- Extensibility for AWP (customizable toolbar, pass replay iframe messages to parent)
- Support export as module, build separate index.js for module in addition to ui.js
- Update to wabac.js 2.20.0
- bump to 2.2.0
This commit is contained in:
Ilya Kreymer
2024-10-16 20:22:11 -07:00
committed by GitHub
parent 91dd5addd1
commit 95c9be6c5b
18 changed files with 430 additions and 402 deletions
+14 -2
View File
@@ -2,30 +2,42 @@
## CHANGES ## CHANGES
v2.2.0
- Extensability: additional override options for AWP, make location toolbar more extensible
- Extensability: support importing as module via dist/index.js, separate from ui.js
- Deps: update to wabac.js 2.20.0, typescript support
v2.1.5 v2.1.5
- Fidelity: updated rewriting rules for instagram - Fidelity: updated rewriting rules for instagram
- Fidelity: disable window online/offline events in replay (via wabac.js) - Fidelity: disable window online/offline events in replay (via wabac.js)
- Dependencies: update to wabac.js 2.19.9 + wombat 3.8.2, electron 32.1.0 - Dependencies: update to wabac.js 2.19.9 + wombat 3.8.2, electron 32.1.0
v2.1.4 v2.1.4
- Fidelity: improvements to FB rewriting, eval() rewriting, 'object' tag rewriting (via wabac.js 2.19.7, wombat 3.7.14) - Fidelity: improvements to FB rewriting, eval() rewriting, 'object' tag rewriting (via wabac.js 2.19.7, wombat 3.7.14)
v2.1.3 v2.1.3
- Fidelity: edge-case rewriting improvements, avoid rewriting inside of strings, detect old-html framesets (via wabac.js 2.19.5, wombat 3.7.12) - Fidelity: edge-case rewriting improvements, avoid rewriting inside of strings, detect old-html framesets (via wabac.js 2.19.5, wombat 3.7.12)
v2.1.2 v2.1.2
- Fidelity: Video replay improvements, fix rewriting of DASH manifests (via wabac.js 2.19.4, wombat 3.7.11) - Fidelity: Video replay improvements, fix rewriting of DASH manifests (via wabac.js 2.19.4, wombat 3.7.11)
v2.1.1 v2.1.1
- Fidelity: fixes to Sharepoint site replay (via wabac.js 2.19.2, wombat 3.7.10) - Fidelity: fixes to Sharepoint site replay (via wabac.js 2.19.2, wombat 3.7.10)
- UI: default URL resources search to 'prefix' as contains only works after prefix search - UI: default URL resources search to 'prefix' as contains only works after prefix search
v2.1.0 v2.1.0
- More fidelity fixes (via wabac.js 2.19.1, wombat 3.7.8) - More fidelity fixes (via wabac.js 2.19.1, wombat 3.7.8)
- Improved messaging: embed tag emits @rwp-page-loading and @rwp-url-change events - Improved messaging: embed tag emits @rwp-page-loading and @rwp-url-change events
- Remove multiTs from hashtag, avoid double history nav as it was being set - Remove multiTs from hashtag, avoid double history nav as it was being set
v2.0.2 v2.0.2
- Fidelity improvements (via wabac.js 2.18.4 and wombat 3.7.7), including improved encoding detection - Fidelity improvements (via wabac.js 2.18.4 and wombat 3.7.7), including improved encoding detection
- Upgrade Shoelace & Lit by @SuaYoo in https://github.com/webrecorder/replayweb.page/pull/329 - Upgrade Shoelace & Lit by @SuaYoo in https://github.com/webrecorder/replayweb.page/pull/329
- Adds multi-resolution ICO file for Windows by @Shrinks99 in https://github.com/webrecorder/replayweb.page/pull/325 - Adds multi-resolution ICO file for Windows by @Shrinks99 in https://github.com/webrecorder/replayweb.page/pull/325
@@ -33,9 +45,10 @@ v2.0.2
- Configure package exports explicitly by @emma-sg in https://github.com/webrecorder/replayweb.page/pull/336 - Configure package exports explicitly by @emma-sg in https://github.com/webrecorder/replayweb.page/pull/336
v2.0.1 v2.0.1
- Fidelity improvements (via wabac.js and wombat), including fixes ebay carousel #326 (via wombat) - Fidelity improvements (via wabac.js and wombat), including fixes ebay carousel #326 (via wombat)
- partial fix to error page escaping #323 (via wabac) - partial fix to error page escaping #323 (via wabac)
fixes to reddit pages #317 - fixes to reddit pages #317
- Fixes to twitter/x replay (via wabac / wombat) - Fixes to twitter/x replay (via wabac / wombat)
- Build improvements: run mkdocs gh-deploy --force in gh action, instead of publish-docs to avoid accidental updates - Build improvements: run mkdocs gh-deploy --force in gh action, instead of publish-docs to avoid accidental updates
- Auto install ruffle from download script, remove from git, add 'update-ruffle' script - Auto install ruffle from download script, remove from git, add 'update-ruffle' script
@@ -69,7 +82,6 @@ v2.0.0
- build(deps): bump loader-utils from 2.0.0 to 2.0.4 by @dependabot in https://github.com/webrecorder/replayweb.page/pull/316 - build(deps): bump loader-utils from 2.0.0 to 2.0.4 by @dependabot in https://github.com/webrecorder/replayweb.page/pull/316
- 2.0.0 Release by @SuaYoo in https://github.com/webrecorder/replayweb.page/pull/269 - 2.0.0 Release by @SuaYoo in https://github.com/webrecorder/replayweb.page/pull/269
v1.8.17 v1.8.17
- Dependencies: update to wabac.js 2.17.3, wombat 3.7.3 - Dependencies: update to wabac.js 2.17.3, wombat 3.7.3
-1
View File
@@ -72,7 +72,6 @@ The static assets are placed in the root `index.html`, `sw.js`, and `ui.js`, and
The full site with docs is built using MkDocs. Using the `yarn build-docs` command, the static assets are copied into `mkdocs/site/` and using Markdown in `mkdocs/site/docs`, the final static site is built to `mkdocs/_genhtml`. This is what is published to https://replayweb.page/ via CI. The full site with docs is built using MkDocs. Using the `yarn build-docs` command, the static assets are copied into `mkdocs/site/` and using Markdown in `mkdocs/site/docs`, the final static site is built to `mkdocs/_genhtml`. This is what is published to https://replayweb.page/ via CI.
### Service Worker Requirements ### Service Worker Requirements
Note that for the 'backend' service worker to work, the static site must be served from either localhost or an HTTPS endpoint. Note that for the 'backend' service worker to work, the static site must be served from either localhost or an HTTPS endpoint.
+4 -9
View File
@@ -1,7 +1,7 @@
{ {
"name": "replaywebpage", "name": "replaywebpage",
"productName": "ReplayWeb.page", "productName": "ReplayWeb.page",
"version": "2.1.5", "version": "2.2.0",
"description": "Serverless Web Archive Replay", "description": "Serverless Web Archive Replay",
"repository": "https://github.com/webrecorder/replayweb.page", "repository": "https://github.com/webrecorder/replayweb.page",
"homepage": "https://replayweb.page/", "homepage": "https://replayweb.page/",
@@ -10,11 +10,7 @@
"exports": { "exports": {
".": { ".": {
"types": "./dist/types/index.d.ts", "types": "./dist/types/index.d.ts",
"default": "./ui.js" "default": "./dist/index.js"
},
"./misc": {
"types": "./dist/types/misc.d.ts",
"default": "./dist/misc.js"
}, },
"./src/electron-*": "./src/electron-*.ts", "./src/electron-*": "./src/electron-*.ts",
"./index.html": "./index.html" "./index.html": "./index.html"
@@ -22,7 +18,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-free": "^5.15.4",
"@shoelace-style/shoelace": "~2.15.1", "@shoelace-style/shoelace": "~2.15.1",
"@webrecorder/wabac": "^2.19.9", "@webrecorder/wabac": "^2.20.0",
"bulma": "^0.9.3", "bulma": "^0.9.3",
"electron-log": "^4.4.1", "electron-log": "^4.4.1",
"electron-updater": "^6.3.2", "electron-updater": "^6.3.2",
@@ -75,8 +71,7 @@
"webpack-merge": "^5.10.0" "webpack-merge": "^5.10.0"
}, },
"resolutions": { "resolutions": {
"**/lit": "3.1.1", "**/lit": "3.1.1"
"@webrecorder/wabac": "^2.19.9"
}, },
"files": [ "files": [
"/dist", "/dist",
+1 -1
View File
@@ -27,7 +27,7 @@ const git = (args) => cp.spawnSync("git", args, { stdio: "inherit" });
// That's why status value needs to be checked explicitly // That's why status value needs to be checked explicitly
if (git(["rev-parse"]).status !== 0 || process.argv.includes("--force")) { if (git(["rev-parse"]).status !== 0 || process.argv.includes("--force")) {
l(`git command not found, running build`); l(`git command not found, running build`);
const compiler = webpack(config.map((c) => c())); const compiler = webpack(config.map((c) => c(process.env, process.argv)));
compiler.run((err) => { compiler.run((err) => {
if (err) { if (err) {
+1 -1
View File
@@ -78,7 +78,7 @@ export class ReplayWebApp extends LitElement {
swErrorMsg: TemplateResult<1> | string | null = null; swErrorMsg: TemplateResult<1> | string | null = null;
protected swName?: string; protected swName?: string;
private swmanager: SWManager | null; protected swmanager: SWManager | null;
private useRuffle = false; private useRuffle = false;
private droppedFile: File | null = null; private droppedFile: File | null = null;
+11 -1
View File
@@ -5,9 +5,15 @@ import fasUpload from "@fortawesome/fontawesome-free/svgs/solid/upload.svg";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
export interface FileWithPath extends File { export interface FileWithPath extends File {
readonly path: string; path: string;
} }
declare let window: Window & {
electron?: {
getPath: (file: File) => string;
};
};
// =========================================================================== // ===========================================================================
@customElement("wr-chooser") @customElement("wr-chooser")
export class Chooser extends LitElement { export class Chooser extends LitElement {
@@ -89,6 +95,10 @@ export class Chooser extends LitElement {
setFile(file: FileWithPath) { setFile(file: FileWithPath) {
this.file = file; this.file = file;
// file.path only available in electron app // file.path only available in electron app
if (IS_APP && window.electron?.getPath) {
this.file.path = window.electron.getPath(this.file);
}
this.fileDisplayName = "file://" + (file.path || file.name); this.fileDisplayName = "file://" + (file.path || file.name);
} }
+8 -4
View File
@@ -1,12 +1,16 @@
/*eslint-env node */ /*eslint-env node */
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7016 - Could not find a declaration file for module '@webrecorder/wabac/src/loaders'. 'node_modules/@webrecorder/wabac/src/loaders.js' implicitly has an 'any' type. import { CollectionLoader } from "@webrecorder/wabac/swlib";
import { CollectionLoader } from "@webrecorder/wabac/src/loaders";
import { type IpcRendererEvent } from "electron"; import { type IpcRendererEvent } from "electron";
const { ipcRenderer, contextBridge } = require("electron"); const { ipcRenderer, contextBridge, webUtils } = require("electron");
contextBridge.exposeInMainWorld("electron", { IS_APP: true }); contextBridge.exposeInMainWorld("electron", {
IS_APP: true,
getPath(file: File) {
return webUtils.getPathForFile(file);
},
});
const dbs = {}; const dbs = {};
+7 -5
View File
@@ -16,8 +16,7 @@ import {
import path from "path"; import path from "path";
import fs from "fs"; import fs from "fs";
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7016 - Could not find a declaration file for module '@webrecorder/wabac/src/rewrite'. 'node_modules/@webrecorder/wabac/src/rewrite/index.js' implicitly has an 'any' type. import { ArchiveResponse, Rewriter } from "@webrecorder/wabac";
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac/src/rewrite";
import { PassThrough, Readable } from "stream"; import { PassThrough, Readable } from "stream";
@@ -414,7 +413,7 @@ class ElectronReplayApp {
headers = new Headers(headers); headers = new Headers(headers);
const date = new Date(); const date = new Date();
let response = new ArchiveResponse({ let response: ArchiveResponse = new ArchiveResponse({
payload, payload,
headers, headers,
status, status,
@@ -443,6 +442,9 @@ class ElectronReplayApp {
headers = Object.fromEntries(response.headers.entries()); headers = Object.fromEntries(response.headers.entries());
let data = await response.getBuffer(); let data = await response.getBuffer();
if (!data) {
data = new Uint8Array();
}
if (status === 206 || status === 200) { if (status === 206 || status === 200) {
const { statusCode, start, end } = this.parseRange( const { statusCode, start, end } = this.parseRange(
@@ -456,9 +458,9 @@ class ElectronReplayApp {
status = statusCode; status = statusCode;
} }
data = this._bufferToStream(data); const result = this._bufferToStream(data);
callback({ statusCode: status, headers, data }); callback({ statusCode: status, headers, data: result });
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
} }
+1 -4
View File
@@ -85,7 +85,7 @@ class Embed extends LitElement {
replayfile = defaultReplayFile; replayfile = defaultReplayFile;
mainElementName = "replay-app-main"; mainElementName = "replay-app-main";
appName = "ReplayWeb.page"; appName = "ReplayWeb.page";
customConfig = null; customConfig: Record<string, string | boolean> | null = null;
reloadCount = 0; reloadCount = 0;
isCrossOrigin: boolean | undefined; isCrossOrigin: boolean | undefined;
@@ -255,14 +255,11 @@ class Embed extends LitElement {
} }
mergeConfigs() { mergeConfigs() {
// TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!this.customConfig) { if (!this.customConfig) {
return this.config; return this.config;
} }
if (this.config) { if (this.config) {
// @ts-expect-error - TS2339 - Property 'customConfig' does not exist on type 'Embed'. | TS2339 - Property 'config' does not exist on type 'Embed'.
const config = { ...this.customConfig, ...JSON.parse(this.config) }; const config = { ...this.customConfig, ...JSON.parse(this.config) };
return JSON.stringify(config); return JSON.stringify(config);
} else { } else {
+4
View File
@@ -10,6 +10,7 @@ import { Pages } from "./pages";
import { PageEntry } from "./pageentry"; import { PageEntry } from "./pageentry";
import { Replay } from "./replay"; import { Replay } from "./replay";
import { Sorter } from "./sorter"; import { Sorter } from "./sorter";
import { SWManager } from "./swmanager";
import { URLResources } from "./url-resources"; import { URLResources } from "./url-resources";
import { Embed } from "./embed"; import { Embed } from "./embed";
import "./shoelace"; import "./shoelace";
@@ -41,6 +42,9 @@ export {
Sorter, Sorter,
URLResources, URLResources,
Embed, Embed,
SWManager,
}; };
export type { ItemType, URLResource } from "./types"; export type { ItemType, URLResource } from "./types";
export * from "./misc";
+5 -3
View File
@@ -89,7 +89,7 @@ class ItemIndex extends LitElement {
for (const item of this.items) { for (const item of this.items) {
if ( if (
item.sourceUrl.indexOf(this.query) >= 0 || item.sourceUrl.indexOf(this.query) >= 0 ||
item.filename.indexOf(this.query) >= 0 || (item.filename && item.filename.indexOf(this.query) >= 0) ||
Boolean(item.loadUrl && item.loadUrl.indexOf(this.query) >= 0) || Boolean(item.loadUrl && item.loadUrl.indexOf(this.query) >= 0) ||
(item.title && item.title.indexOf(this.query) >= 0) (item.title && item.title.indexOf(this.query) >= 0)
) { ) {
@@ -383,8 +383,10 @@ class ItemIndex extends LitElement {
>ArchiveWeb.page</a >ArchiveWeb.page</a
> >
to save pages as you browse the web, or to save pages as you browse the web, or
<a href="https://browsertrix.com" target="_blank">sign up for Browsertrix</a> to archive <a href="https://browsertrix.com" target="_blank"
entire websites with automated crawling! >sign up for Browsertrix</a
>
to archive entire websites with automated crawling!
</p> </p>
`; `;
} }
+49 -48
View File
@@ -1,10 +1,4 @@
import { import { LitElement, html, css, type PropertyValues } from "lit";
LitElement,
html,
css,
type PropertyValues,
type TemplateResult,
} from "lit";
import { property } from "lit/decorators.js"; import { property } from "lit/decorators.js";
import { ref, createRef, type Ref } from "lit/directives/ref.js"; import { ref, createRef, type Ref } from "lit/directives/ref.js";
import type { import type {
@@ -216,7 +210,8 @@ class Item extends LitElement {
constructor() { constructor() {
super(); super();
this.showSidebar = localStorage.getItem("pages:showSidebar") === "1"; this.showSidebar =
localStorage.getItem("pages:showSidebar") === "1" && this.browsable;
} }
firstUpdated() { firstUpdated() {
@@ -547,7 +542,7 @@ class Item extends LitElement {
this.tabData.view = "pages"; this.tabData.view = "pages";
} }
if (this.tabData.url && this.tabData.query) { if (this.tabData.url && this.tabData.query && this.browsable) {
this.showSidebar = true; this.showSidebar = true;
} }
} }
@@ -705,7 +700,7 @@ class Item extends LitElement {
} }
.replay-bar { .replay-bar {
padding: 0.5em 0em 0.5em 0.5em; padding: 0.5em;
max-width: none; max-width: none;
border-bottom: solid 0.1rem #97989a; border-bottom: solid 0.1rem #97989a;
width: 100%; width: 100%;
@@ -1110,26 +1105,10 @@ class Item extends LitElement {
</nav>`; </nav>`;
} }
renderLocationBar() { protected renderToolbarLeft() {
if (this.embed === "replayonly" || this.embed == "replay-with-info") {
return "";
}
const dateStr = tsToDate(this.ts).toLocaleString();
const isReplay = !!this.tabData.url; const isReplay = !!this.tabData.url;
const showFavIcon = isReplay && this.favIconUrl; return html` ${this.browsable
return html` <a
class="skip-link"
href="#skip-replay-target"
@click="${this.skipMenu}"
>Skip replay navigation</a
>
<nav class="replay-bar" aria-label="replay">
<div class="field has-addons">
${this.browsable
? html` <a ? html` <a
href="#" href="#"
role="button" role="button"
@@ -1213,8 +1192,27 @@ class Item extends LitElement {
` `
: ""} : ""}
</span> </span>
</a> </a>`;
${this.renderExtraToolbar()} }
renderLocationBar() {
if (this.embed === "replayonly" || this.embed == "replay-with-info") {
return "";
}
const isReplay = !!this.tabData.url;
const showFavIcon = isReplay && this.favIconUrl;
return html` <a
class="skip-link"
href="#skip-replay-target"
@click="${this.skipMenu}"
>Skip replay navigation</a
>
<nav class="replay-bar" aria-label="replay">
<div class="field has-addons">
${this.renderToolbarLeft()}
<form @submit="${this.onSubmit}"> <form @submit="${this.onSubmit}">
<div <div
class="control is-expanded ${showFavIcon ? "has-icons-left" : ""}" class="control is-expanded ${showFavIcon ? "has-icons-left" : ""}"
@@ -1236,8 +1234,18 @@ class Item extends LitElement {
: html``} : html``}
</div> </div>
</form> </form>
${this.renderToolbarRight()}
</div>
</nav>
<p id="skip-replay-target" tabindex="-1" class="is-sr-only">Skipped</p>`;
}
<div protected renderToolbarRight() {
const isReplay = !!this.tabData.url;
const dateStr = tsToDate(this.ts).toLocaleString();
return html` <div
class="dropdown is-right ${this.menuActive ? "is-active" : ""}" class="dropdown is-right ${this.menuActive ? "is-active" : ""}"
@click="${() => (this.menuActive = false)}" @click="${() => (this.menuActive = false)}"
> >
@@ -1249,9 +1257,7 @@ class Item extends LitElement {
@click="${this.onFullscreenToggle}" @click="${this.onFullscreenToggle}"
@keyup="${clickOnSpacebarPress}" @keyup="${clickOnSpacebarPress}"
title="${this.isFullscreen ? "Exit Full Screen" : "Full Screen"}" title="${this.isFullscreen ? "Exit Full Screen" : "Full Screen"}"
aria-label="${this.isFullscreen aria-label="${this.isFullscreen ? "Exit Fullscreen" : "Fullscreen"}"
? "Exit Fullscreen"
: "Fullscreen"}"
> >
<span class="icon is-small"> <span class="icon is-small">
<fa-icon <fa-icon
@@ -1295,9 +1301,7 @@ class Item extends LitElement {
size="1.0em" size="1.0em"
class="has-text-grey" class="has-text-grey"
aria-hidden="true" aria-hidden="true"
.svg="${this.isFullscreen .svg="${this.isFullscreen ? fasUnfullscreen : fasFullscreen}"
? fasUnfullscreen
: fasFullscreen}"
></fa-icon> ></fa-icon>
</span> </span>
<span>Full Screen</span> <span>Full Screen</span>
@@ -1323,7 +1327,6 @@ class Item extends LitElement {
<span>Browse Contents</span> <span>Browse Contents</span>
</a>` </a>`
: ""} : ""}
${this.renderExtraToolbar()}
${this.clearable ${this.clearable
? html` <hr class="dropdown-divider is-hidden-desktop" /> ? html` <hr class="dropdown-divider is-hidden-desktop" />
<a <a
@@ -1370,7 +1373,8 @@ class Item extends LitElement {
<span class="menu-head">Capture Date</span>${dateStr} <span class="menu-head">Capture Date</span>${dateStr}
</div>` </div>`
: ""} : ""}
<a ${!this.editable
? html` <a
href="#" href="#"
role="button" role="button"
class="dropdown-item" class="dropdown-item"
@@ -1385,7 +1389,8 @@ class Item extends LitElement {
</span> </span>
<span>Archive Info</span> <span>Archive Info</span>
</a> </a>
<hr class="dropdown-divider" /> <hr class="dropdown-divider" />`
: ``}
<a <a
href="#" href="#"
role="button" role="button"
@@ -1403,10 +1408,7 @@ class Item extends LitElement {
</a> </a>
</div> </div>
</div> </div>
</div> </div>`;
</div>
</nav>
<p id="skip-replay-target" tabindex="-1" class="is-sr-only">Skipped</p>`;
} }
private renderTimestamp() { private renderTimestamp() {
@@ -1506,10 +1508,6 @@ class Item extends LitElement {
></wr-item-info>`; ></wr-item-info>`;
} }
protected renderExtraToolbar(/*isDropdown = false*/): "" | TemplateResult<1> {
return "";
}
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'isSidebar' implicitly has an 'any' type. // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'isSidebar' implicitly has an 'any' type.
renderItemTabs(isSidebar) { renderItemTabs(isSidebar) {
const isStory = this.hasStory && this.tabData.view === "story"; const isStory = this.hasStory && this.tabData.view === "story";
@@ -1650,6 +1648,9 @@ class Item extends LitElement {
this.showSidebar = false; this.showSidebar = false;
this.updateTabData({ url: "", ts: "" }); this.updateTabData({ url: "", ts: "" });
} }
if (!this.browsable) {
this.showSidebar = false;
}
} }
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type. // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type.
+12 -3
View File
@@ -55,12 +55,11 @@ class Replay extends LitElement {
// TODO: Fix this the next time the file is edited. // TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/promise-function-async // eslint-disable-next-line @typescript-eslint/promise-function-async
navigator.serviceWorker.addEventListener("message", (event) => navigator.serviceWorker.addEventListener("message", (event) =>
this.handleAuthMessage(event), this.handleSWMessage(event),
); );
} }
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type. async handleSWMessage(event: MessageEvent) {
async handleAuthMessage(event) {
if ( if (
event.data.type === "authneeded" && event.data.type === "authneeded" &&
this.collInfo && this.collInfo &&
@@ -90,6 +89,8 @@ class Replay extends LitElement {
} else { } else {
this.showAuth = true; this.showAuth = true;
} }
} else if (event.data.type) {
window.parent.postMessage(event.data);
} }
} }
@@ -211,6 +212,10 @@ class Replay extends LitElement {
} }
} else if (event.data.wb_type === "title") { } else if (event.data.wb_type === "title") {
this.title = event.data.title; this.title = event.data.title;
} else {
const passEvent = { type: event.data.wb_type, ...event.data };
delete passEvent.wb_type;
window.parent.postMessage(passEvent);
} }
} }
} }
@@ -272,9 +277,13 @@ class Replay extends LitElement {
} }
if (iframeWin) { if (iframeWin) {
try {
iframeWin.addEventListener("beforeunload", () => { iframeWin.addEventListener("beforeunload", () => {
this.setLoading(); this.setLoading();
}); });
} catch (e) {
// ignore
}
} }
} }
+14 -39
View File
@@ -4,76 +4,60 @@ import rwpLogo from "~assets/brand/replaywebpage-icon-color.svg";
// =========================================================================== // ===========================================================================
export class SWManager { export class SWManager {
name: string;
scope: string;
appName: string;
requireSubdomainIframe: boolean;
errorMsg: string | null = null;
constructor({ constructor({
name = "sw.js", name = "sw.js",
scope = "./", scope = "./",
appName = "ReplayWeb.page", appName = "ReplayWeb.page",
requireSubdomainIframe = false, requireSubdomainIframe = false,
} = {}) { } = {}) {
// @ts-expect-error - TS2339 - Property 'name' does not exist on type 'SWManager'.
this.name = name; this.name = name;
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
this.scope = scope; this.scope = scope;
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
this.appName = appName; this.appName = appName;
// @ts-expect-error - TS2339 - Property 'requireSubdomainIframe' does not exist on type 'SWManager'.
this.requireSubdomainIframe = requireSubdomainIframe; this.requireSubdomainIframe = requireSubdomainIframe;
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
this.errorMsg = null;
} }
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'newAppName' implicitly has an 'any' type. setAppName(newAppName: string) {
setAppName(newAppName) {
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
this.appName = newAppName; this.appName = newAppName;
} }
// TODO: Fix this the next time the file is edited. async register(): Promise<void> {
// eslint-disable-next-line @typescript-eslint/promise-function-async
register() {
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7034 - Variable 'resolve' implicitly has type 'any' in some locations where its type cannot be determined. | TS7034 - Variable 'reject' implicitly has type 'any' in some locations where its type cannot be determined. // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7034 - Variable 'resolve' implicitly has type 'any' in some locations where its type cannot be determined. | TS7034 - Variable 'reject' implicitly has type 'any' in some locations where its type cannot be determined.
let resolve, reject; let resolve, reject;
const p = new Promise((res, rej) => { const p = new Promise<void>((res, rej) => {
resolve = res; resolve = res;
reject = rej; reject = rej;
}); });
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
this.errorMsg = this.getSWErrorMsg(); this.errorMsg = this.getSWErrorMsg();
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
if (this.errorMsg) { if (this.errorMsg) {
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
console.error(this.errorMsg); console.error(this.errorMsg);
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'. reject!(this.errorMsg);
reject(this.errorMsg);
} }
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'error' implicitly has an 'any' type. // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'error' implicitly has an 'any' type.
const handleError = (error) => { const handleError = (error) => {
console.error("Error during service worker registration:", error); console.error("Error during service worker registration:", error);
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
this.errorMsg = this.getCrossOriginIframeMsg(); this.errorMsg = this.getCrossOriginIframeMsg();
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
if (!this.errorMsg) { if (!this.errorMsg) {
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
this.errorMsg = `${ this.errorMsg = `${
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
this.appName this.appName
} could not be loaded due to the following error:\n${error.toString()}`; } could not be loaded due to the following error:\n${error.toString()}`;
} }
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'. reject!(this.errorMsg);
reject(this.errorMsg);
}; };
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'. | TS2339 - Property 'name' does not exist on type 'SWManager'.
// TODO: Fix this the next time the file is edited. // TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
register(this.scope + this.name, { register(this.scope + this.name, {
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
registrationOptions: { scope: this.scope }, registrationOptions: { scope: this.scope },
registered() { registered() {
console.log("Service worker is registered"); console.log("Service worker is registered");
@@ -118,9 +102,7 @@ export class SWManager {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (navigator.serviceWorker) { if (navigator.serviceWorker) {
// must be loaded from a cross-origin (eg. subdomain) // must be loaded from a cross-origin (eg. subdomain)
// @ts-expect-error - TS2339 - Property 'requireSubdomainIframe' does not exist on type 'SWManager'.
if (this.requireSubdomainIframe && !this.isCrossOriginIframe()) { if (this.requireSubdomainIframe && !this.isCrossOriginIframe()) {
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
return `Sorry, due to security settings, this ${this.appName} embed only be viewed within a subdomain iframe.`; return `Sorry, due to security settings, this ${this.appName} embed only be viewed within a subdomain iframe.`;
} }
@@ -135,12 +117,7 @@ export class SWManager {
if (!window.isSecureContext) { if (!window.isSecureContext) {
return ` return `
Sorry, the ${ Sorry, the ${this.appName} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${window.location.host}.
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
this.appName
} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${
window.location.host
}.
Please try loading this page from an HTTPS URL`; Please try loading this page from an HTTPS URL`;
} }
@@ -149,13 +126,11 @@ export class SWManager {
return "Sorry, Service Workers are disabled in Firefox in Private Mode. Please try loading this page in regular mode instead."; return "Sorry, Service Workers are disabled in Firefox in Private Mode. Please try loading this page in regular mode instead.";
} }
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
return `Sorry, ${this.appName} won't work in this browser as Service Workers are not supported in this window. return `Sorry, ${this.appName} won't work in this browser as Service Workers are not supported in this window.
Please try a different browser.`; Please try a different browser.`;
} }
renderErrorReport(override?: string) { renderErrorReport(override = "") {
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
const msg = this.errorMsg || override; const msg = this.errorMsg || override;
if (!msg) { if (!msg) {
+1 -1
View File
@@ -16,7 +16,7 @@ export type URLResource = {
export type Page = URLResource; export type Page = URLResource;
export type ItemType = { export type ItemType = {
filename: string; filename?: string;
sourceUrl: string; sourceUrl: string;
replayPrefix: string; replayPrefix: string;
apiPrefix: string; apiPrefix: string;
+1 -1
View File
@@ -4,5 +4,5 @@
}, },
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"include": ["**/*.ts", "**/*.js", ".*.js"], "include": ["**/*.ts", "**/*.js", ".*.js"],
"exclude": ["__generated__", "__mocks__", "dist", "ruffle/*.js"] "exclude": ["dist", "scratch"]
} }
+91 -79
View File
@@ -94,6 +94,92 @@ const electronPreloadConfig = (/*env, argv*/) => {
return merge(tsConfig, config); return merge(tsConfig, config);
}; };
const libConfig = (env, argv) => {
/** @type {import('webpack').Configuration['entry']} */
const entry = {
index: "./src/index.ts",
};
const extraPlugins = [];
const patterns = [
{ from: "node_modules/@webrecorder/wabac/dist/sw.js", to: "sw.js" },
];
extraPlugins.push(new CopyPlugin({ patterns }));
/** @type {import('webpack').Configuration} */
const config = {
target: "web",
mode: "production",
cache: {
type: "filesystem",
},
resolve: {
fallback: { crypto: false },
},
entry,
optimization,
output: {
path: path.join(__dirname, "dist"),
filename: "[name].js",
globalObject: "self",
library: {
type: "module",
},
publicPath: "/",
},
experiments: {
outputModule: true,
},
devtool: argv.mode === "production" ? undefined : "source-map",
plugins: [
new webpack.NormalModuleReplacementPlugin(/^node:*/, (resource) => {
switch (resource.request) {
case "node:stream":
resource.request = "stream-browserify";
break;
}
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
new webpack.ProvidePlugin({
process: "process/browser",
}),
new MiniCssExtractPlugin(),
new webpack.DefinePlugin({
__SW_NAME__: JSON.stringify("sw.js"),
__HELPER_PROXY__: JSON.stringify(HELPER_PROXY),
__GDRIVE_CLIENT_ID__: JSON.stringify(GDRIVE_CLIENT_ID),
__VERSION__: JSON.stringify(package_json.version),
}),
new webpack.BannerPlugin(BANNER_TEXT),
...extraPlugins,
],
module: {
rules: [
{
test: /\.svg$/,
use: ["raw-loader"],
},
{
test: /main.scss$/,
use: ["css-loader", "sass-loader"],
},
{
test: /wombat.js|wombatWorkers.js|index.html$/i,
use: ["raw-loader"],
},
],
},
};
return merge(tsConfig, config);
};
const browserConfig = (/*env, argv*/) => { const browserConfig = (/*env, argv*/) => {
const isDevServer = process.env.WEBPACK_SERVE; const isDevServer = process.env.WEBPACK_SERVE;
@@ -104,14 +190,14 @@ const browserConfig = (/*env, argv*/) => {
const extraPlugins = []; const extraPlugins = [];
if (isDevServer) { //if (isDevServer) {
entry["sw"] = "@webrecorder/wabac/src/sw.js"; // entry["sw"] = "@webrecorder/wabac/src/sw.js";
} else { //} else {
const patterns = [ const patterns = [
{ from: "node_modules/@webrecorder/wabac/dist/sw.js", to: "sw.js" }, { from: "node_modules/@webrecorder/wabac/dist/sw.js", to: "sw.js" },
]; ];
extraPlugins.push(new CopyPlugin({ patterns })); extraPlugins.push(new CopyPlugin({ patterns }));
} //}
/** @type {import('webpack').Configuration} */ /** @type {import('webpack').Configuration} */
const config = { const config = {
@@ -125,7 +211,6 @@ const browserConfig = (/*env, argv*/) => {
}, },
entry, entry,
optimization, optimization,
output: { output: {
path: path.join(__dirname), path: path.join(__dirname),
filename: "[name].js", filename: "[name].js",
@@ -133,7 +218,6 @@ const browserConfig = (/*env, argv*/) => {
globalObject: "self", globalObject: "self",
publicPath: "/", publicPath: "/",
}, },
devServer: { devServer: {
compress: true, compress: true,
port: 9990, port: 9990,
@@ -188,81 +272,9 @@ const browserConfig = (/*env, argv*/) => {
return merge(tsConfig, config); return merge(tsConfig, config);
}; };
const miscConfig = (/*env, argv*/) => {
/** @type {import('webpack').Configuration['entry']} */
const entry = {
misc: "./src/misc.ts",
};
/** @type {import('webpack').Configuration} */
const config = {
target: "web",
mode: "production",
cache: {
type: "filesystem"
},
resolve: {
fallback: { crypto: false },
},
entry,
optimization,
output: {
path: path.join(__dirname, "dist"),
filename: "[name].js",
libraryTarget: "self",
globalObject: "self",
publicPath: "/",
},
plugins: [
new webpack.NormalModuleReplacementPlugin(/^node:*/, (resource) => {
switch (resource.request) {
case "node:stream":
resource.request = "stream-browserify";
break;
}
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
new webpack.ProvidePlugin({
process: "process/browser",
}),
new MiniCssExtractPlugin(),
new webpack.DefinePlugin({
__SW_NAME__: JSON.stringify("sw.js"),
__HELPER_PROXY__: JSON.stringify(HELPER_PROXY),
__GDRIVE_CLIENT_ID__: JSON.stringify(GDRIVE_CLIENT_ID),
__VERSION__: JSON.stringify(package_json.version),
}),
new webpack.BannerPlugin(BANNER_TEXT),
],
module: {
rules: [
{
test: /\.svg$/,
use: ["raw-loader"],
},
{
test: /main.scss$/,
use: ["css-loader", "sass-loader"],
},
{
test: /wombat.js|wombatWorkers.js|index.html$/i,
use: ["raw-loader"],
},
],
},
};
return merge(tsConfig, config);
};
module.exports = [ module.exports = [
libConfig,
browserConfig, browserConfig,
miscConfig,
electronMainConfig, electronMainConfig,
electronPreloadConfig, electronPreloadConfig,
]; ];
+12 -6
View File
@@ -613,6 +613,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/js-levenshtein@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.3.tgz#a6fd0bdc8255b274e5438e0bfb25f154492d1106"
integrity sha512-jd+Q+sD20Qfu9e2aEXogiO3vpOC1PYJOUdyN9gvs4Qrvkg4wF43L5OhqrPeokdv8TL0/mXoYfpkcoGZMNN2pkQ==
"@types/json-schema@*", "@types/json-schema@^7.0.8": "@types/json-schema@*", "@types/json-schema@^7.0.8":
version "7.0.9" version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@@ -1016,14 +1021,15 @@
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
"@webrecorder/wabac@^2.19.9": "@webrecorder/wabac@^2.20.0":
version "2.19.9" version "2.20.0"
resolved "https://registry.yarnpkg.com/@webrecorder/wabac/-/wabac-2.19.9.tgz#21d357077bc2a85419e7a6002c81a4bc4fec2514" resolved "https://registry.yarnpkg.com/@webrecorder/wabac/-/wabac-2.20.0.tgz#d9f87a909a0c09e460cf8b86082a71c176e0c9f8"
integrity sha512-lyvbKVrdUZMUGxwKg5ZFQnyjGUSqZSGOF3NFG9rXLA+Ni0YcQjZCMexGSmqCwY+BksyrVJISCMs3xQ2WQAekgw== integrity sha512-zeR+CmAfJO2MQSKwRwcccy7+TfeKTX0A1yeHlO98mtsT3VMtTqrdasIDEjIxe39aEbBl11k+m8DQyrz3CctJNQ==
dependencies: dependencies:
"@peculiar/asn1-ecc" "^2.3.4" "@peculiar/asn1-ecc" "^2.3.4"
"@peculiar/asn1-schema" "^2.3.3" "@peculiar/asn1-schema" "^2.3.3"
"@peculiar/x509" "^1.9.2" "@peculiar/x509" "^1.9.2"
"@types/js-levenshtein" "^1.1.3"
"@webrecorder/wombat" "^3.8.2" "@webrecorder/wombat" "^3.8.2"
acorn "^8.10.0" acorn "^8.10.0"
auto-js-ipfs "^2.1.1" auto-js-ipfs "^2.1.1"
@@ -1043,7 +1049,7 @@
path-parser "^6.1.0" path-parser "^6.1.0"
process "^0.11.10" process "^0.11.10"
stream-browserify "^3.0.0" stream-browserify "^3.0.0"
warcio "^2.3.0" warcio "^2.3.1"
"@webrecorder/wombat@^3.8.2": "@webrecorder/wombat@^3.8.2":
version "3.8.2" version "3.8.2"
@@ -5609,7 +5615,7 @@ vscode-uri@^2.1.2:
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
warcio@^2.3.0, warcio@^2.3.1: warcio@^2.3.1:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/warcio/-/warcio-2.3.1.tgz#8ac9de897de1a556161168f2a3938b60929908ca" resolved "https://registry.yarnpkg.com/warcio/-/warcio-2.3.1.tgz#8ac9de897de1a556161168f2a3938b60929908ca"
integrity sha512-PjcWqzXfs6HdWfHi1V/i8MoMmV5M0Csg3rOa2mqCJ1dmCJXswVfQ0VXbEVumwavNIW2oFFj6LJoCHHeL4Ls/zw== integrity sha512-PjcWqzXfs6HdWfHi1V/i8MoMmV5M0Csg3rOa2mqCJ1dmCJXswVfQ0VXbEVumwavNIW2oFFj6LJoCHHeL4Ls/zw==