diff --git a/.eslintrc b/.eslintrc
index a46c301..c0f912f 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -7,6 +7,7 @@
"plugin:jest/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:unicorn/all",
+ "@open-wc/eslint-config",
"prettier",
],
"settings": {
@@ -35,6 +36,8 @@
"no-eval": "error",
"no-console": "error",
"no-unused-vars": "error",
+ "import/extensions": "off",
+ "import/no-cycle": "off",
"unicorn/template-indent": "off",
"unicorn/prefer-string-replace-all": "off",
"@typescript-eslint/explicit-member-accessibility": "error",
diff --git a/components/filter.ts b/components/filter.ts
index e25d4f5..e8b03dd 100644
--- a/components/filter.ts
+++ b/components/filter.ts
@@ -76,6 +76,7 @@ export default function filter(
const start = (currentPage - 1) * pageSize;
const end = currentPage * pageSize;
if (index >= start && index < end) return true;
+ return false;
});
return [filteredData.length, paginated];
diff --git a/components/font-call.ts b/components/font-call.ts
index 45b3942..277334f 100644
--- a/components/font-call.ts
+++ b/components/font-call.ts
@@ -1,6 +1,38 @@
import { GeneratedData } from "./main-app";
import rtlSubsets from "../data/rtl.json";
+export function fontCallVariant(
+ variants: GeneratedData[number]["variants"],
+): string {
+ if (variants.length === 0) {
+ return "";
+ }
+
+ const [firstVariant] = variants;
+ if (/\d+/g.test(firstVariant)) {
+ return `:wght@${firstVariant}`;
+ }
+ if (firstVariant.includes("italic")) {
+ return `:ital@1`;
+ }
+ return "";
+}
+
+export function fontCallSelectedVariant(selectedVariant: string): string {
+ const variantNumber = selectedVariant.match(/\d+/g); // get number from selectedVariant
+
+ const variants = [];
+ if (selectedVariant.includes("italic")) {
+ variants.push(selectedVariant === "italic" ? "ital@1" : "ital");
+ }
+ if (variantNumber && variantNumber[0]) {
+ variants.push(
+ `wght@${variants.includes("ital") ? "1," : ""}${variantNumber[0]}`,
+ );
+ }
+ return `:${variants.join(",")}`;
+}
+
export default function fontCall({
variants,
slug,
@@ -27,31 +59,6 @@ export default function fontCall({
return `https://fonts.googleapis.com/css2?family=${fontCallString}`;
}
-function fontCallVariant(variants: GeneratedData[number]["variants"]): string {
- const [firstVariant] = variants;
- if (/\d+/g.test(firstVariant)) {
- return `:wght@${firstVariant}`;
- } else if (firstVariant.includes("italic")) {
- return `:ital@1`;
- }
-}
-
-function fontCallSelectedVariant(selectedVariant: string): string {
- const hasItalic = selectedVariant.includes("italic");
- const variantNumber = selectedVariant.match(/\d+/g); // get number from selectedVariant
-
- const variants = [];
- if (selectedVariant === "italic") {
- variants.push("ital@1");
- } else if (hasItalic) {
- variants.push("ital");
- }
- if (variantNumber && variantNumber[0]) {
- variants.push(`wght@${hasItalic ? "1," : ""}${variantNumber[0]}`);
- }
- return `:${variants.join(",")}`;
-}
-
export function familyStyle({
family,
selectedVariant,
@@ -63,17 +70,17 @@ export function familyStyle({
previewName: string;
subset: string;
}): string {
- let style = `font-family: '${family}';`;
+ const styleParts = [`font-family: '${family}'`];
if (rtlSubsets.includes(subset) && family !== previewName) {
- style += "direction: rtl;";
+ styleParts.push("direction: rtl");
}
if (selectedVariant.includes("italic")) {
- style += "font-style: italic;";
+ styleParts.push("font-style: italic");
}
// get variant number from selectedVariant
const variantNumber = selectedVariant.match(/\d+/g);
if (variantNumber && variantNumber[0]) {
- style += `font-weight: ${variantNumber[0]};`;
+ styleParts.push(`font-weight: ${variantNumber[0]}`);
}
- return style;
+ return `${styleParts.join(";")};`;
}
diff --git a/components/font-item.ts b/components/font-item.ts
index 2dd3b5f..05217de 100644
--- a/components/font-item.ts
+++ b/components/font-item.ts
@@ -35,7 +35,8 @@ class FontItem extends HTMLLIElement {
(!subsets.includes("latin") || family.startsWith("Noto")) &&
sampleSubsets[subsets[0] as keyof SampleSubsets]
) {
- this.subset = subsets[0];
+ const [subset] = subsets;
+ this.subset = subset;
return sampleSubsets[subsets[0] as keyof SampleSubsets];
}
return family;
diff --git a/components/font-list.ts b/components/font-list.ts
index 0b1333c..2c8e9b6 100644
--- a/components/font-list.ts
+++ b/components/font-list.ts
@@ -1,10 +1,6 @@
import { setAttributes } from "./set-attributes";
class FontList extends HTMLUListElement {
- public constructor() {
- super();
- }
-
public get selectedVariant(): string {
return this.getAttribute("selected-variant");
}
diff --git a/components/main-app.ts b/components/main-app.ts
index 2b59527..d71b189 100644
--- a/components/main-app.ts
+++ b/components/main-app.ts
@@ -1,6 +1,7 @@
import customEvent from "./custom-event";
import filter from "./filter";
import generatedData from "../data/data.json";
+
export type GeneratedData = typeof generatedData;
type SelectTypes =
@@ -13,19 +14,22 @@ type SelectTypes =
class MainApp extends HTMLElement {
private paginationButtons: HTMLElement =
this.querySelector("pagination-buttons");
+
private searchStatus: HTMLElement = this.querySelector("search-status");
+
private sortByElm: HTMLElement = this.querySelector("sort-by");
+
private fontList: HTMLUListElement = this.querySelector("ul[is=font-list]");
+
private content: HTMLElement = this.querySelector("#content");
+
private selectedSearchElm: HTMLInputElement =
this.querySelector("#selectedSearch");
- public get pageSize(): number {
- return 10;
- }
+ public pageSize = 10;
public get currentPage(): number {
- return Number.parseInt(this.getAttribute("current-page"));
+ return Number.parseInt(this.getAttribute("current-page"), 10);
}
private set currentPage(value: number) {
@@ -48,7 +52,7 @@ class MainApp extends HTMLElement {
}
private get resultsLength(): number {
- return Number.parseInt(this.getAttribute("results-length"));
+ return Number.parseInt(this.getAttribute("results-length"), 10);
}
public get selectedCategory(): string {
@@ -156,28 +160,28 @@ class MainApp extends HTMLElement {
else this.removeAllFilters();
}
- private removeSingleFilter(filter: string): void {
- switch (filter) {
+ private removeSingleFilter(currentFilter: string): void {
+ switch (currentFilter) {
case "selectedSearch": {
this.removeSearch();
break;
}
case "selectedVariable": {
- this.removeCheckbox();
+ MainApp.removeCheckbox();
break;
}
default: {
- this.removeSelect(filter);
+ MainApp.removeSelect(currentFilter);
}
}
}
private removeAllFilters(): void {
- if (this.selectedCategory) this.removeSelect("selectedCategory");
- if (this.selectedSubset) this.removeSelect("selectedSubset");
- if (this.selectedVariant) this.removeSelect("selectedVariant");
- if (this.selectedVariable) this.removeCheckbox();
- if (this.selectedTag) this.removeSelect("selectedTag");
+ if (this.selectedCategory) MainApp.removeSelect("selectedCategory");
+ if (this.selectedSubset) MainApp.removeSelect("selectedSubset");
+ if (this.selectedVariant) MainApp.removeSelect("selectedVariant");
+ if (this.selectedVariable) MainApp.removeCheckbox();
+ if (this.selectedTag) MainApp.removeSelect("selectedTag");
if (this.selectedSearch) this.removeSearch();
}
@@ -186,7 +190,7 @@ class MainApp extends HTMLElement {
(this.selectedSearchElm as HTMLInputElement).value = "";
}
- private removeSelect(value: string): void {
+ private static removeSelect(value: string): void {
window.dispatchEvent(
customEvent("remove-select", {
value,
@@ -194,7 +198,7 @@ class MainApp extends HTMLElement {
);
}
- private removeCheckbox(): void {
+ private static removeCheckbox(): void {
window.dispatchEvent(customEvent("remove-checkbox"));
}
diff --git a/components/pagination-buttons.ts b/components/pagination-buttons.ts
index fa68800..cb24d34 100644
--- a/components/pagination-buttons.ts
+++ b/components/pagination-buttons.ts
@@ -3,6 +3,8 @@ export type ButtonType = MouseEvent & { target: HTMLButtonElement };
class PaginationButtons extends HTMLElement {
private mainApp = document.querySelector("main-app");
+ private pageSize = 10;
+
public constructor() {
super();
this.handlePage = this.handlePage.bind(this);
@@ -10,7 +12,7 @@ class PaginationButtons extends HTMLElement {
}
public get currentPage(): number {
- return Number.parseInt(this.getAttribute("current-page"));
+ return Number.parseInt(this.getAttribute("current-page"), 10);
}
private set currentPage(value: number) {
@@ -22,11 +24,7 @@ class PaginationButtons extends HTMLElement {
}
private get resultsLength(): number {
- return Number.parseInt(this.getAttribute("results-length"));
- }
-
- private get pageSize(): number {
- return 10;
+ return Number.parseInt(this.getAttribute("results-length"), 10);
}
private get totalPages(): number {
@@ -75,12 +73,11 @@ class PaginationButtons extends HTMLElement {
event === "next-page" &&
this.currentPage * this.pageSize < this.resultsLength
) {
- this.currentPage++;
+ this.currentPage += 1;
return;
}
if (event === "previous-page" && this.currentPage > 1) {
- this.currentPage--;
- return;
+ this.currentPage -= 1;
}
}
@@ -122,7 +119,7 @@ class PaginationButtons extends HTMLElement {
const urlParameters = new URLSearchParams(window.location.search);
const initialValue = urlParameters.get("page");
if (initialValue) {
- const parsedValue = Number.parseInt(initialValue);
+ const parsedValue = Number.parseInt(initialValue, 10);
if (Number.isNaN(parsedValue)) {
this.currentPage = 1;
return;
diff --git a/components/search-status.ts b/components/search-status.ts
index 441aee2..8a78a00 100644
--- a/components/search-status.ts
+++ b/components/search-status.ts
@@ -1,10 +1,6 @@
import iconClose from "../svg/close.svg";
class SearchStatus extends HTMLElement {
- public constructor() {
- super();
- }
-
private get resultsLength(): string {
return this.getAttribute("results-length");
}
@@ -60,7 +56,7 @@ class SearchStatus extends HTMLElement {
if (hasSelectedFilters) {
elm.push(
this.selectedFilters
- .map((filter) => this.renderFilter(filter))
+ .map((filter): string => SearchStatus.renderFilter(filter))
.join(""),
``,
);
@@ -69,7 +65,7 @@ class SearchStatus extends HTMLElement {
this.innerHTML = `${elm.join("\n")}`;
}
- private renderFilter({
+ private static renderFilter({
label,
value,
id,
diff --git a/components/set-attributes.ts b/components/set-attributes.ts
index d42e946..74e0183 100644
--- a/components/set-attributes.ts
+++ b/components/set-attributes.ts
@@ -4,7 +4,7 @@ export function setAttributes(
[x: string]: string;
},
): void {
- for (const key in attributes) {
+ for (const key of Object.keys(attributes)) {
if (attributes[key] !== undefined && attributes[key] !== null) {
element.setAttribute(key, attributes[key]);
}
diff --git a/components/sort-by.ts b/components/sort-by.ts
index ee3fd09..491ba35 100644
--- a/components/sort-by.ts
+++ b/components/sort-by.ts
@@ -19,7 +19,7 @@ class SortBy extends HTMLElement {
}
private get resultsLength(): number {
- return Number.parseInt(this.getAttribute("results-length"));
+ return Number.parseInt(this.getAttribute("results-length"), 10);
}
public render(): void {
diff --git a/package-lock.json b/package-lock.json
index 3a8c520..7f8859b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,12 +11,13 @@
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@actions/core": "^1.10.1",
+ "@open-wc/eslint-config": "^12.0.3",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"esbuild": "^0.20.2",
- "eslint": "^8.44.0",
+ "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
@@ -291,6 +292,33 @@
"url": "https://opencollective.com/babel"
}
},
+ "node_modules/@babel/eslint-parser": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz",
+ "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==",
+ "dev": true,
+ "dependencies": {
+ "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
+ "eslint-visitor-keys": "^2.1.0",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || >=14.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0",
+ "eslint": "^7.5.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@babel/generator": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz",
@@ -594,6 +622,21 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz",
+ "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-import-meta": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
@@ -1801,6 +1844,37 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
+ "version": "5.1.1-v1",
+ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
+ "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-scope": "5.1.1"
+ }
+ },
+ "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1836,6 +1910,46 @@
"node": ">= 8"
}
},
+ "node_modules/@open-wc/eslint-config": {
+ "version": "12.0.3",
+ "resolved": "https://registry.npmjs.org/@open-wc/eslint-config/-/eslint-config-12.0.3.tgz",
+ "integrity": "sha512-170IUpOUW0bQsiOs+tBUaWQkU03fALzXuPIGK/PSSGyT2FkDpPkR7pK7UZUv0gI+3PT2qy7GuMkMZoHqsFlPoQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/eslint-parser": "^7.19.1",
+ "@babel/plugin-syntax-import-assertions": "^7.20.0",
+ "eslint-config-airbnb-base": "^15.0.0",
+ "eslint-plugin-html": "^7.1.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-import-exports-imports-resolver": "^1.0.1",
+ "eslint-plugin-lit": "^1.10.1",
+ "eslint-plugin-lit-a11y": "^4.1.1",
+ "eslint-plugin-no-only-tests": "^3.1.0",
+ "eslint-plugin-wc": "^1.2.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.6.0",
+ "eslint-plugin-html": "^7.1.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-lit": "^1.10.1",
+ "eslint-plugin-lit-a11y": "^4.1.1",
+ "eslint-plugin-no-only-tests": "^3.1.0",
+ "eslint-plugin-wc": "^1.2.0"
+ }
+ },
+ "node_modules/@open-wc/eslint-config/node_modules/eslint-plugin-wc": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-1.5.0.tgz",
+ "integrity": "sha512-KFSfiHDol/LeV7U6IX8GdgpGf/s3wG8FTG120Rml/hGNB/DkCuGYQhlf0VgdBdf7gweem8Nlsh5o64HNdj+qPA==",
+ "dev": true,
+ "dependencies": {
+ "is-valid-element-name": "^1.0.0",
+ "js-levenshtein-esm": "^1.2.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -2121,6 +2235,15 @@
"integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
"dev": true
},
+ "node_modules/@types/parse5": {
+ "version": "2.2.34",
+ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-2.2.34.tgz",
+ "integrity": "sha512-p3qOvaRsRpFyEmaS36RtLzpdxZZnmxGuT1GMgzkTtTJVFuEw7KFjGK83MFODpJExgX1bEzy9r0NYjMC3IMfi7w==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/semver": {
"version": "7.5.8",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
@@ -2813,7 +2936,6 @@
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
"integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
"dev": true,
- "peer": true,
"dependencies": {
"deep-equal": "^2.0.5"
}
@@ -3016,6 +3138,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axe-core": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.0.tgz",
+ "integrity": "sha512-H5orY+M2Fr56DWmMFpMrq5Ge93qjNdPVqzBv5gWK3aD1OvjBEJlEzxf09z93dGVQeI0LiW+aCMIx1QtShC/zUw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
+ "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
+ "dev": true
+ },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -3595,6 +3732,15 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -3665,6 +3811,12 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
+ "node_modules/confusing-browser-globals": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
+ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==",
+ "dev": true
+ },
"node_modules/constantinople": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz",
@@ -3912,7 +4064,6 @@
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz",
"integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==",
"dev": true,
- "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"es-get-iterator": "^1.1.2",
@@ -4093,6 +4244,23 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/dom5": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dom5/-/dom5-3.0.1.tgz",
+ "integrity": "sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==",
+ "dev": true,
+ "dependencies": {
+ "@types/parse5": "^2.2.34",
+ "clone": "^2.1.0",
+ "parse5": "^4.0.0"
+ }
+ },
+ "node_modules/dom5/node_modules/parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "dev": true
+ },
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
@@ -4341,7 +4509,6 @@
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
"dev": true,
- "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.3",
@@ -4602,6 +4769,25 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-airbnb-base": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz",
+ "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==",
+ "dev": true,
+ "dependencies": {
+ "confusing-browser-globals": "^1.0.10",
+ "object.assign": "^4.1.2",
+ "object.entries": "^1.1.5",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.25.2"
+ }
+ },
"node_modules/eslint-config-prettier": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
@@ -4685,6 +4871,89 @@
"ms": "^2.1.1"
}
},
+ "node_modules/eslint-plugin-html": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-7.1.0.tgz",
+ "integrity": "sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==",
+ "dev": true,
+ "dependencies": {
+ "htmlparser2": "^8.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-html/node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-html/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-html/node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-html/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-html/node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
"node_modules/eslint-plugin-import": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
@@ -4716,6 +4985,25 @@
"eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
}
},
+ "node_modules/eslint-plugin-import-exports-imports-resolver": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import-exports-imports-resolver/-/eslint-plugin-import-exports-imports-resolver-1.0.1.tgz",
+ "integrity": "sha512-4Gqp25iQSS3k8o0/zKxymWbnDW8KIqkubrOOy67IU9Qmhmkq4AiuMXbjx9O9AhYG7Vl94ZQFBcpfwLaQkINv2w==",
+ "dev": true,
+ "dependencies": {
+ "resolve.exports": "^1.1.0",
+ "resolve.imports": "^1.2.6"
+ }
+ },
+ "node_modules/eslint-plugin-import-exports-imports-resolver/node_modules/resolve.exports": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz",
+ "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/eslint-plugin-import/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
@@ -4762,6 +5050,78 @@
}
}
},
+ "node_modules/eslint-plugin-lit": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.11.0.tgz",
+ "integrity": "sha512-jVqy2juQTAtOzj1ILf+ZW5GpDobXlSw0kvpP2zu2r8ZbW7KISt7ikj1Gw9DhNeirEU1UlSJR0VIWpdr4lzjayw==",
+ "dev": true,
+ "dependencies": {
+ "parse5": "^6.0.1",
+ "parse5-htmlparser2-tree-adapter": "^6.0.1",
+ "requireindex": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "eslint": ">= 5"
+ }
+ },
+ "node_modules/eslint-plugin-lit-a11y": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-lit-a11y/-/eslint-plugin-lit-a11y-4.1.2.tgz",
+ "integrity": "sha512-otrF1Q0uv6RUz/AflVgnf1rVzbfQJfgUmnB+xBl71IR8EwtJGEOrqGs3Ky/4APMda+maF6bsZLctppcz16m7Hw==",
+ "dev": true,
+ "dependencies": {
+ "aria-query": "^5.1.3",
+ "axe-core": "^4.3.3",
+ "axobject-query": "^2.2.0",
+ "dom5": "^3.0.1",
+ "emoji-regex": "^10.2.1",
+ "eslint-plugin-lit": "^1.10.1",
+ "eslint-rule-extender": "0.0.1",
+ "language-tags": "^1.0.5",
+ "parse5": "^7.1.2",
+ "parse5-htmlparser2-tree-adapter": "^6.0.1",
+ "requireindex": "~1.2.0"
+ },
+ "peerDependencies": {
+ "eslint": ">= 5"
+ }
+ },
+ "node_modules/eslint-plugin-lit-a11y/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-lit-a11y/node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/eslint-plugin-no-only-tests": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz",
+ "integrity": "sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==",
+ "dev": true,
+ "engines": {
+ "node": ">=5.0.0"
+ }
+ },
"node_modules/eslint-plugin-unicorn": {
"version": "52.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz",
@@ -4868,6 +5228,19 @@
"eslint": ">=5"
}
},
+ "node_modules/eslint-rule-extender": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-rule-extender/-/eslint-rule-extender-0.0.1.tgz",
+ "integrity": "sha512-F0j1Twve3lamL3J0rRSVAynlp58sDPG39JFcQrM+u9Na7PmCgiPHNODh6YE9mduaGcsn3NBqbf6LZRj0cLr8Ng==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kaicataldo"
+ }
+ },
"node_modules/eslint-scope": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
@@ -6001,7 +6374,6 @@
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dev": true,
- "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -6238,7 +6610,6 @@
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
"integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
"dev": true,
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -6330,7 +6701,6 @@
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
"integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
"dev": true,
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -6421,7 +6791,6 @@
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
"integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
"dev": true,
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -6443,7 +6812,6 @@
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
"integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
"dev": true,
- "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@@ -7428,6 +7796,24 @@
"integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==",
"dev": true
},
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -8361,7 +8747,6 @@
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"dev": true,
- "peer": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -8400,6 +8785,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.entries": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/object.fromentries": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
@@ -8589,6 +8988,21 @@
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
"dev": true
},
+ "node_modules/parse5": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+ "dev": true
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
+ "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
+ "dev": true,
+ "dependencies": {
+ "parse5": "^6.0.1"
+ }
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -8646,6 +9060,12 @@
"node": ">=8"
}
},
+ "node_modules/pattern-key-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/pattern-key-compare/-/pattern-key-compare-1.0.0.tgz",
+ "integrity": "sha512-7wi8a7OFmdx4Hx31+KY9kcD7gO+MWWupXtlAx7ANqoE8Pypl501FsDAPX2tSYLOuafED82A0Mv3lzeNfn82Jlg==",
+ "dev": true
+ },
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -9342,6 +9762,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/requireindex": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
+ "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.5"
+ }
+ },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -9404,6 +9833,15 @@
"node": ">=10"
}
},
+ "node_modules/resolve.imports": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/resolve.imports/-/resolve.imports-1.2.7.tgz",
+ "integrity": "sha512-q+UNv8vIE8wiB3BYjN9cAEtx17TnV6PoQSBWLCWaI9DDumevUifHY5ocKL4S5qcETHm++Gia3EdNJO81IW3PaQ==",
+ "dev": true,
+ "dependencies": {
+ "pattern-key-compare": "^1.0.0"
+ }
+ },
"node_modules/restore-cursor": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
@@ -9793,7 +10231,6 @@
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
"integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
"dev": true,
- "peer": true,
"dependencies": {
"internal-slot": "^1.0.4"
},
@@ -10942,7 +11379,6 @@
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
"integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
"dev": true,
- "peer": true,
"dependencies": {
"is-map": "^2.0.1",
"is-set": "^2.0.1",
diff --git a/package.json b/package.json
index 3056304..4a95301 100644
--- a/package.json
+++ b/package.json
@@ -14,12 +14,13 @@
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@actions/core": "^1.10.1",
+ "@open-wc/eslint-config": "^12.0.3",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"esbuild": "^0.20.2",
- "eslint": "^8.44.0",
+ "eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
diff --git a/test/families.test.ts b/test/families.test.ts
index f289467..777e8d5 100644
--- a/test/families.test.ts
+++ b/test/families.test.ts
@@ -51,10 +51,10 @@ describe("families.json", () => {
// sort tags by number of families
// eslint-disable-next-line unicorn/no-array-reduce
const tags = Object.values(families).reduce(
- (accumulator, tags) => {
- for (const tag of tags) {
+ (accumulator, allTags) => {
+ for (const tag of allTags) {
if (accumulator[tag]) {
- accumulator[tag]++;
+ accumulator[tag] += 1;
} else {
accumulator[tag] = 1;
}
diff --git a/test/filter-checkbox.test.ts b/test/filter-checkbox.test.ts
index f653070..7ee68bd 100644
--- a/test/filter-checkbox.test.ts
+++ b/test/filter-checkbox.test.ts
@@ -13,7 +13,7 @@ describe("filter-checkbox", () => {
});
document.body.innerHTML = ``;
- const filterCheckbox: HTMLInputElement = document.querySelector(
+ let filterCheckbox: HTMLInputElement = document.querySelector(
"input[is=filter-checkbox]",
);
@@ -43,9 +43,7 @@ describe("filter-checkbox", () => {
});
document.body.innerHTML = ``;
- const filterCheckbox: HTMLInputElement = document.querySelector(
- "input[is=filter-checkbox]",
- );
+ filterCheckbox = document.querySelector("input[is=filter-checkbox]");
expect(filterCheckbox.checked).toBe(true);
// expect the event to fire after the main-app is loaded
const mockFunction = jest.fn();
diff --git a/test/font-call.test.ts b/test/font-call.test.ts
new file mode 100644
index 0000000..b1c6af9
--- /dev/null
+++ b/test/font-call.test.ts
@@ -0,0 +1,101 @@
+import {
+ fontCallVariant,
+ fontCallSelectedVariant,
+ familyStyle,
+} from "../components/font-call";
+import { GeneratedData } from "../components/main-app";
+
+describe("fontCallVariant", () => {
+ it("should return weight variant when first variant is a number", () => {
+ const variants: GeneratedData[number]["variants"] = ["400", "italic"];
+ const result = fontCallVariant(variants);
+ expect(result).toBe(":wght@400");
+ });
+
+ it('should return italic variant when first variant includes "italic"', () => {
+ const variants: GeneratedData[number]["variants"] = ["italic", "400"];
+ const result = fontCallVariant(variants);
+ expect(result).toBe(":ital@1");
+ });
+
+ it('should return empty string when first variant is neither a number nor "italic"', () => {
+ const variants: GeneratedData[number]["variants"] = ["regular", "bold"];
+ const result = fontCallVariant(variants);
+ expect(result).toBe("");
+ });
+ it("should return empty string when first variant is []", () => {
+ const variants: GeneratedData[number]["variants"] = [];
+ const result = fontCallVariant(variants);
+ expect(result).toBe("");
+ });
+});
+
+describe("fontCallSelectedVariant", () => {
+ it('should return ":ital@1" when selectedVariant is "italic"', () => {
+ const result = fontCallSelectedVariant("italic");
+ expect(result).toBe(":ital@1");
+ });
+
+ it('should return ":ital,wght@1,400" when selectedVariant is "italic400"', () => {
+ const result = fontCallSelectedVariant("italic400");
+ expect(result).toBe(":ital,wght@1,400");
+ });
+
+ it('should return ":wght@400" when selectedVariant is "400"', () => {
+ const result = fontCallSelectedVariant("400");
+ expect(result).toBe(":wght@400");
+ });
+
+ it('should return ":" when selectedVariant does not include "italic" or a number', () => {
+ const result = fontCallSelectedVariant("regular");
+ expect(result).toBe(":");
+ });
+});
+
+describe("familyStyle", () => {
+ it("should return the correct style for a non-italic, non-rtl font", () => {
+ const style = familyStyle({
+ family: "Roboto",
+ selectedVariant: "400",
+ previewName: "Roboto",
+ subset: "latin",
+ });
+ expect(style).toBe("font-family: 'Roboto';font-weight: 400;");
+ });
+
+ it("should return the correct style for an italic, non-rtl font", () => {
+ const style = familyStyle({
+ family: "Roboto",
+ selectedVariant: "italic400",
+ previewName: "Roboto",
+ subset: "latin",
+ });
+ expect(style).toBe(
+ "font-family: 'Roboto';font-style: italic;font-weight: 400;",
+ );
+ });
+
+ it("should return the correct style for a non-italic, rtl font", () => {
+ const style = familyStyle({
+ family: "Roboto",
+ selectedVariant: "400",
+ previewName: "Preview",
+ subset: "arabic",
+ });
+ expect(style).toBe(
+ "font-family: 'Roboto';direction: rtl;font-weight: 400;",
+ );
+ });
+
+ it("should return the correct style for an italic, rtl font", () => {
+ const style = familyStyle({
+ family: "Roboto",
+ selectedVariant: "italic400",
+ previewName: "Preview",
+ subset: "arabic",
+ });
+ expect(style).toBe(
+ "font-family: 'Roboto';direction: rtl;font-style: italic;font-weight: 400;",
+ );
+ });
+});
diff --git a/test/main-app.test.ts b/test/main-app.test.ts
index 00347eb..bc305aa 100644
--- a/test/main-app.test.ts
+++ b/test/main-app.test.ts
@@ -1,5 +1,5 @@
import "./components";
-import { default as userEvent } from "@testing-library/user-event";
+import { userEvent } from "@testing-library/user-event";
import { readFileSync } from "node:fs";
import customEvent from "../components/custom-event";
@@ -194,7 +194,7 @@ describe("MainApp", () => {
customEvent("tag-button-selected", {
value: "need tags",
id: "selectedTag",
- })
+ }),
);
const searchStatus = document.querySelector("search-status");
expect(searchStatus).toMatchInlineSnapshot(`
@@ -242,13 +242,13 @@ describe("MainApp", () => {
customEvent("tag-button-selected", {
value: "cute",
id: "selectedTag",
- })
+ }),
);
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedTag",
- })
+ }),
);
expect(document.querySelector("search-status")).toMatchInlineSnapshot(`
@@ -271,7 +271,8 @@ describe("MainApp", () => {
const searchStatus = document.querySelector("search-status");
const resultsLength = Number.parseInt(
- searchStatus.getAttribute("results-length")
+ searchStatus.getAttribute("results-length"),
+ 10,
);
expect(searchStatus).toMatchInlineSnapshot(`
@@ -314,7 +315,7 @@ describe("MainApp", () => {
// expect there two be resultsLength number of font-items
expect(document.querySelectorAll("li[is='font-item']").length).toEqual(
- resultsLength
+ resultsLength,
);
});
@@ -326,7 +327,7 @@ describe("MainApp", () => {
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedSearch",
- })
+ }),
);
const searchStatus = document.querySelector("search-status");
expect(searchStatus).toMatchInlineSnapshot(`
@@ -385,7 +386,7 @@ describe("MainApp", () => {
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedVariable",
- })
+ }),
);
expect(document.querySelector("search-status")).toMatchInlineSnapshot(`
@@ -403,13 +404,13 @@ describe("MainApp", () => {
test("removes category filter", async () => {
await user.selectOptions(
document.querySelector("#selectedCategory"),
- "display"
+ "display",
);
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedCategory",
- })
+ }),
);
const searchStatus = document.querySelector("search-status");
@@ -429,13 +430,13 @@ describe("MainApp", () => {
test("removes subset filter", async () => {
await user.selectOptions(
document.querySelector("#selectedSubset"),
- "hebrew"
+ "hebrew",
);
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedSubset",
- })
+ }),
);
const searchStatus = document.querySelector("search-status");
@@ -455,13 +456,13 @@ describe("MainApp", () => {
test("removes variant filter", async () => {
await user.selectOptions(
document.querySelector("#selectedVariant"),
- "100italic"
+ "100italic",
);
mainApp.dispatchEvent(
customEvent("clear-filter", {
value: "selectedVariant",
- })
+ }),
);
const searchStatus = document.querySelector("search-status");
@@ -483,7 +484,7 @@ describe("MainApp", () => {
customEvent("tag-button-selected", {
value: "modern",
id: "selectedTag",
- })
+ }),
);
const checkboxVariable: HTMLInputElement =
document.querySelector("#selectedVariable");
@@ -493,17 +494,17 @@ describe("MainApp", () => {
await user.selectOptions(
document.querySelector("#selectedCategory"),
- "display"
+ "display",
);
await user.selectOptions(
document.querySelector("#selectedSubset"),
- "hebrew"
+ "hebrew",
);
await user.selectOptions(
document.querySelector("#selectedVariant"),
- "100italic"
+ "100italic",
);
expect(document.querySelector("search-status")).toMatchInlineSnapshot(`
@@ -700,7 +701,7 @@ describe("MainApp", () => {
// expect tag to be selected
expect(
- (document.querySelector("#selectedTag") as HTMLSelectElement).value
+ (document.querySelector("#selectedTag") as HTMLSelectElement).value,
).toBe("cute");
});
@@ -877,7 +878,7 @@ describe("MainApp", () => {
`);
// expect variable to be checked
expect(
- (document.querySelector("#selectedVariable") as HTMLInputElement).checked
+ (document.querySelector("#selectedVariable") as HTMLInputElement).checked,
).toBe(true);
});
@@ -903,13 +904,13 @@ describe("MainApp", () => {
`);
expect(
- (document.querySelector("#selectedVariable") as HTMLInputElement).checked
+ (document.querySelector("#selectedVariable") as HTMLInputElement).checked,
).toBe(false);
});
test("sorts fonts when sort-by button is clicked", async () => {
const sortByButton: HTMLButtonElement = document.querySelector(
- "sort-by button[data-sort='date']"
+ "sort-by button[data-sort='date']",
);
sortByButton.click();
@@ -947,10 +948,10 @@ describe("MainApp", () => {
it("current page changes on click", () => {
document.body.innerHTML = body;
const nextButton: HTMLButtonElement = document.querySelector(
- "pagination-buttons #btn-next"
+ "pagination-buttons #btn-next",
);
nextButton.click();
- const mainApp = document.querySelector("main-app");
+ mainApp = document.querySelector("main-app");
expect(mainApp.getAttribute("current-page")).toBe("2");
const paginationButtons = document.querySelector("pagination-buttons");
expect(paginationButtons.getAttribute("current-page")).toBe("2");
@@ -959,16 +960,16 @@ describe("MainApp", () => {
it("current page changes on click, next then back", () => {
document.body.innerHTML = body;
const nextButton: HTMLButtonElement = document.querySelector(
- "pagination-buttons #btn-next"
+ "pagination-buttons #btn-next",
);
nextButton.click();
- const mainApp = document.querySelector("main-app");
+ mainApp = document.querySelector("main-app");
expect(mainApp.getAttribute("current-page")).toBe("2");
const paginationButtons = document.querySelector("pagination-buttons");
expect(paginationButtons.getAttribute("current-page")).toBe("2");
const backButton: HTMLButtonElement = document.querySelector(
- "pagination-buttons #btn-prev"
+ "pagination-buttons #btn-prev",
);
backButton.click();
expect(mainApp.getAttribute("current-page")).toBe("1");
@@ -978,10 +979,10 @@ describe("MainApp", () => {
it("current page changes when a different filter is changed", () => {
document.body.innerHTML = body;
const nextButton: HTMLButtonElement = document.querySelector(
- "pagination-buttons #btn-next"
+ "pagination-buttons #btn-next",
);
nextButton.click();
- const mainApp = document.querySelector("main-app");
+ mainApp = document.querySelector("main-app");
expect(mainApp.getAttribute("current-page")).toBe("2");
const paginationButtons = document.querySelector("pagination-buttons");
expect(paginationButtons.getAttribute("current-page")).toBe("2");