Update NPM packaging, linting, and a bunch of types (#275)

Preparation for
https://github.com/webrecorder/archiveweb.page/issues/198 /
https://github.com/webrecorder/archiveweb.page/pull/199.

## Changes

- Organizes published files more cleanly, using `dist/types` folder as
the target for type declarations and sourcemaps
- Configures type field in `package.json`
- Updates ESLint & its config
  - Sets up type-informed linting rules mirroring browsertrix
- Adds a bunch of other useful eslint and eslint-typescript rules, and
applies auto-fixes to the codebase
- Cleans up a bunch of types throughout the codebase, particularly parts
of the code used by ArchiveWebPage
- Changes `ItemIndex#_deleting` from `private` to `protected` so that a
part of AWP that extends it can do so properly
- Makes a bunch of previously-implied [non-null
assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#non-null-assertion-operator-postfix-)
explicit
- Updates `URLResource` and `ItemType` types (and renames `Item` →
`ItemType` to disambiguate from the `Item` class)
- Removes `node-sass` and replaces it with `sass-embedded` for much
quicker installs and compilation
This commit is contained in:
Emma Segal-Grossman
2024-02-06 18:50:12 -08:00
committed by GitHub
parent a40471128f
commit a63390f10c
32 changed files with 898 additions and 1550 deletions
+34 -43
View File
@@ -1,4 +1,10 @@
import { LitElement, html, css, type PropertyValues } from "lit";
import {
LitElement,
html,
css,
type PropertyValues,
type TemplateResult,
} from "lit";
import { property } from "lit/decorators.js";
import { ref, createRef, type Ref } from "lit/directives/ref.js";
import type {
@@ -51,7 +57,7 @@ import fasCaretDown from "@fortawesome/fontawesome-free/svgs/solid/caret-down.sv
import { RWPEmbedReceipt } from "./embed-receipt";
import Split from "split.js";
import type { Item as ItemType } from "./types";
import type { ItemType, URLResource } from "./types";
import type { Replay } from "./replay";
import { ifDefined } from "lit/directives/if-defined.js";
@@ -76,6 +82,7 @@ export type LoadInfo = {
swError?: string;
newFullImport?: unknown;
name?: string;
importCollId?: string;
};
// ===========================================================================
@@ -175,14 +182,13 @@ class Item extends LitElement {
private observer?: IntersectionObserver;
private archiveInfoDialog: Ref<SlDialog> = createRef();
private readonly archiveInfoDialog: Ref<SlDialog> = createRef();
private readonly tabNames = ["pages", "story", "resources", "info"];
private readonly tabLabels = {
pages: "Pages",
story: "Story",
resources: "URLs",
info: "Archive Info",
};
constructor() {
@@ -214,9 +220,7 @@ class Item extends LitElement {
while (
this.editable &&
this.autoUpdateInterval &&
(!this.itemInfo ||
!this.itemInfo.pages ||
this.itemInfo.pages.length < 100)
(!this.itemInfo?.pages || this.itemInfo.pages.length < 100)
) {
await new Promise((resolve) =>
setTimeout(resolve, this.autoUpdateInterval * 1000),
@@ -283,7 +287,7 @@ class Item extends LitElement {
}
}
if (changedProperties.has("tabData")) {
if (!this.itemInfo || !this.itemInfo.coll) {
if (!this.itemInfo?.coll) {
return;
}
const newHash =
@@ -308,9 +312,8 @@ class Item extends LitElement {
} else {
window.location.hash = this._locationHash;
if (!this.showSidebar) {
const replay = this.renderRoot.querySelector(
"wr-coll-replay",
) as Replay;
const replay =
this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (replay) {
replay.focus();
}
@@ -338,10 +341,8 @@ class Item extends LitElement {
configureSplitter() {
if (this.tabData.url && this.showSidebar) {
const contents = this.renderRoot.querySelector(
"#contents",
) as HTMLElement;
const replay = this.renderRoot.querySelector("wr-coll-replay") as Replay;
const contents = this.renderRoot.querySelector<HTMLElement>("#contents");
const replay = this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (contents && replay && !this.splitter) {
const opts = {
@@ -378,11 +379,11 @@ class Item extends LitElement {
return;
}
let item = this.loadInfo && this.loadInfo.customColl; // @todo(2023-11-06) update customColl -> customItem
let item = this.loadInfo?.customColl; // @todo(2023-11-06) update customColl -> customItem
if (!item) {
const res = await sourceToId(this.sourceUrl);
item = res.coll;
const res = await sourceToId(this.sourceUrl!);
item = res.item;
}
this.item = item;
@@ -406,11 +407,7 @@ class Item extends LitElement {
...json,
};
if (
this.loadInfo &&
this.loadInfo.extraConfig &&
this.loadInfo.extraConfig.headers
) {
if (this.loadInfo?.extraConfig?.headers) {
const headers = this.loadInfo.extraConfig.headers;
await fetch(`${itemApiPrefix}/updateAuth`, {
method: "POST",
@@ -870,10 +867,9 @@ class Item extends LitElement {
const isReplay = !!this.tabData.url;
const isSidebar = isReplay && this.showSidebar;
if (!isReplay && this.tabData && this.tabData.view) {
if (!isReplay && this.tabData?.view) {
const detail = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
title: (this.tabLabels as any)[this.tabData.view],
title: this.tabLabels[this.tabData.view],
replayTitle: false,
};
this.dispatchEvent(
@@ -932,7 +928,7 @@ class Item extends LitElement {
ts="${this.tabData.ts || ""}"
@coll-tab-nav="${this.onItemTabNav}"
id="replay"
@replay-loading="${(e) =>
@replay-loading="${(e: CustomEvent<{ loading: boolean }>) =>
(this.isLoading = e.detail.loading)}"
@replay-favicons="${this.onFavIcons}"
>
@@ -1488,14 +1484,14 @@ class Item extends LitElement {
}
dragStart() {
const replay = this.renderRoot.querySelector("wr-coll-replay") as Replay;
const replay = this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (replay) {
replay.setDisablePointer(true);
}
}
dragEnd() {
const replay = this.renderRoot.querySelector("wr-coll-replay") as Replay;
const replay = this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (replay) {
replay.setDisablePointer(false);
}
@@ -1517,7 +1513,7 @@ class Item extends LitElement {
></wr-item-info>`;
}
renderExtraToolbar(/*isDropdown = false*/) {
protected renderExtraToolbar(/*isDropdown = false*/): "" | TemplateResult<1> {
return "";
}
@@ -1582,9 +1578,7 @@ class Item extends LitElement {
// This is a workaround, since this app's routing doesn't permit normal
// following of in-page anchors.
event.preventDefault();
(
this.renderRoot.querySelector("#skip-replay-target") as HTMLElement
).focus();
this.renderRoot.querySelector<HTMLElement>("#skip-replay-target")?.focus();
}
onKeyDown(event) {
@@ -1702,7 +1696,7 @@ class Item extends LitElement {
onSubmit(event) {
event.preventDefault();
const input = this.renderRoot.querySelector("input") as HTMLInputElement;
const input = this.renderRoot.querySelector<HTMLInputElement>("input")!;
if (input.value) {
this.navigateTo(input.value);
} else {
@@ -1719,12 +1713,12 @@ class Item extends LitElement {
onTimestampDropdownBtnBlur(event: MouseEvent) {
const btn = event.currentTarget as HTMLButtonElement;
const dropdown = btn.closest("sl-dropdown") as SlDropdown;
const dropdown = btn.closest<SlDropdown>("sl-dropdown");
const relatedTarget = event.relatedTarget as HTMLElement;
if (relatedTarget && dropdown.contains(relatedTarget)) {
if (relatedTarget && dropdown?.contains(relatedTarget)) {
return;
}
if (dropdown.open) {
if (dropdown?.open) {
dropdown.hide();
}
}
@@ -1741,9 +1735,7 @@ class Item extends LitElement {
data = { url: value };
if (value === this.tabData.url) {
const replay = this.renderRoot.querySelector(
"wr-coll-replay",
) as Replay;
const replay = this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (replay) {
replay.refresh();
}
@@ -1761,8 +1753,7 @@ class Item extends LitElement {
_stringToParams(value) {
const q = new URLSearchParams(value.slice(RWP_SCHEME.length));
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
const data: any = {};
const data: Partial<URLResource> = {};
data.url = "";
data.ts = "";
@@ -1807,7 +1798,7 @@ class Item extends LitElement {
this.menuActive = false;
if (this.tabData.url) {
const replay = this.renderRoot.querySelector("wr-coll-replay") as Replay;
const replay = this.renderRoot.querySelector<Replay>("wr-coll-replay");
if (replay) {
replay.refresh();
}