From 5c3edb953c6741e37ceaf271f2c513b4a0bcf009 Mon Sep 17 00:00:00 2001 From: Alexander Sullivan Date: Sun, 18 Oct 2026 21:16:41 -0400 Subject: [PATCH 1/2] more unit tests --- src/scripts/index.js | 10 +++- src/scripts/index.test.js | 97 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/scripts/index.js b/src/scripts/index.js index af89161..776b766 100644 --- a/src/scripts/index.js +++ b/src/scripts/index.js @@ -65,8 +65,14 @@ class ArticleFiller { static retrieveArticleData() { const articleDataUrl = "/src/articleArchive/articleData.json"; - fetch(articleDataUrl) - .then((response) => response.json()) + return fetch(articleDataUrl) + .then((response) => { + if (!response.ok) { + throw new Error(`Failed to fetch article data: ${response.status} ${response.statusText}`); + } + + return response.json(); + }) .then((articleData) => { ArticleFiller.articleData = articleData; ArticleFiller.callArticle(); diff --git a/src/scripts/index.test.js b/src/scripts/index.test.js index 66682b5..0e78e5c 100644 --- a/src/scripts/index.test.js +++ b/src/scripts/index.test.js @@ -4,6 +4,8 @@ const { ArticleFiller } = require("./index.js"); const { registerServiceWorker } = require("./index.js"); +window.onload = null; + describe("ArticleFiller: displayError", () => { beforeEach(() => { document.body.innerHTML = ` @@ -118,6 +120,7 @@ describe("ArticleFiller: grabArticle", () => { afterEach(() => { jest.restoreAllMocks(); + delete global.fetch; }); test("loads markdown and updates DOM", async () => { @@ -170,6 +173,100 @@ describe("ArticleFiller: grabArticle", () => { }); }); +describe("ArticleFiller: retrieveArticleData", () => { + beforeEach(() => { + ArticleFiller.articleData = undefined; + }); + + afterEach(() => { + jest.restoreAllMocks(); + delete global.fetch; + delete document.URL; + }); + + test("fetches and processes article data", async () => { + const articleData = { + TestArticle: { + title: "Test Article", + summary: "A summary.", + thumbnail: "thumb.png", + author: "Jane Doe", + date: "2024-06-01", + }, + }; + document.body.innerHTML = ` +
+ + + + + + + + + `; + Object.defineProperty(document, "URL", { + value: "http://localhost/index.html?TestArticle", + configurable: true, + }); + const markdown = "# Test Article"; + const fetchSpy = (global.fetch = jest.fn((url) => { + if (url === "/src/articleArchive/articleData.json") { + return Promise.resolve({ ok: true, json: () => Promise.resolve(articleData) }); + } + + return Promise.resolve({ ok: true, text: () => Promise.resolve(markdown) }); + })); + + await ArticleFiller.retrieveArticleData(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(fetchSpy).toHaveBeenCalledWith("/src/articleArchive/articleData.json"); + expect(fetchSpy).toHaveBeenCalledWith( + "/src/articleArchive/authorJaneDoe/2024-06-01_TestArticle/TestArticle.md", + ); + expect(ArticleFiller.articleData).toEqual(articleData); + expect(document.getElementById("articleBody").innerHTML).toContain("Test Article"); + }); + + test("logs network failures without processing article data", async () => { + const error = new Error("Network unavailable"); + global.fetch = jest.fn().mockRejectedValue(error); + const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); + + await ArticleFiller.retrieveArticleData(); + + expect(consoleErrorSpy).toHaveBeenCalledWith("Error retrieving article data:", error); + expect(ArticleFiller.articleData).toBeUndefined(); + }); + + test("logs non-OK responses without parsing or processing article data", async () => { + const response = { ok: false, status: 500, statusText: "Internal Server Error", json: jest.fn() }; + global.fetch = jest.fn().mockResolvedValue(response); + const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); + + await ArticleFiller.retrieveArticleData(); + + expect(response.json).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith( + "Error retrieving article data:", + expect.objectContaining({ message: "Failed to fetch article data: 500 Internal Server Error" }), + ); + expect(ArticleFiller.articleData).toBeUndefined(); + }); + + test("logs JSON parsing failures without processing article data", async () => { + const error = new SyntaxError("Unexpected token"); + global.fetch = jest.fn().mockResolvedValue({ ok: true, json: () => Promise.reject(error) }); + const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); + + await ArticleFiller.retrieveArticleData(); + + expect(consoleErrorSpy).toHaveBeenCalledWith("Error retrieving article data:", error); + expect(ArticleFiller.articleData).toBeUndefined(); + }); +}); + describe("ServiceWorker registration", () => { afterEach(() => { jest.restoreAllMocks(); From 1ced52d512d8fc6d609b293ad13c106ae8343254 Mon Sep 17 00:00:00 2001 From: Alexander Sullivan Date: Sun, 18 Oct 2026 22:38:51 -0400 Subject: [PATCH 2/2] minify --- package-lock.json | 485 +++++++++++++++++++++++++++++++++++++++ package.json | 4 +- src/scripts/index.min.js | 116 +++++++++- src/style.min.css | 2 +- 4 files changed, 604 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index daa6bfd..7408ff9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "GPL-3.0", "devDependencies": { "cypress": "^16.1.1", + "esbuild": "^0.28.2", "eslint": "^10.12.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-cypress": "^7.0.2", @@ -2040,6 +2041,448 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", @@ -6697,6 +7140,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", diff --git a/package.json b/package.json index 0cc5972..201585c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "main": "index.html", "devDependencies": { "cypress": "^16.1.1", + "esbuild": "^0.28.2", "eslint": "^10.12.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-cypress": "^7.0.2", @@ -40,13 +41,14 @@ "eslint:check": "eslint ./", "lint:markdown": "markdownlint-cli2 --fix", "lint:markdown:check": "markdownlint-cli2", + "minify": "esbuild src/scripts/index.js --minify --outfile=src/scripts/index.min.js && esbuild src/style.css --minify --outfile=src/style.min.css", "prettier": "prettier --write ./", "prettier:check": "prettier --check ./", "regen-package-lock": "rm -rf node_modules package-lock.json && npm run audit:fix", "start": "http-server . -p 3000 -c-1", "test": "jest", "test:verbose": "jest --verbose --silent=false", - "validate": "npm run prettier && npm run eslint && npm run test && npm run e2e:headless && npm run lint:markdown", + "validate": "npm run prettier && npm run eslint && npm run minify && npm run test && npm run e2e:headless && npm run lint:markdown", "workbox": "workbox generateSW" }, "bugs": { diff --git a/src/scripts/index.min.js b/src/scripts/index.min.js index beb2a80..b04e855 100644 --- a/src/scripts/index.min.js +++ b/src/scripts/index.min.js @@ -1 +1,115 @@ -const converter=new showdown.Converter;class ArticleFiller{constructor(){this.articleData,this.articleMd,this.article,this.pageData,this.pageURL,this.callPageDisplay=!0,this.whatPageDisplay="index"}static displayError(t){ArticleFiller.errMsg=t?.trim(),ArticleFiller.errMsg?.length<1&&(ArticleFiller.errMsg="Unknown error"),console.error(ArticleFiller.errMsg),ArticleFiller.article=`\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\tError\n\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t\t\t${ArticleFiller.errMsg}\n\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t`,document?.getElementById("articleBody")&&(document.getElementById("articleBody").innerHTML=ArticleFiller.article)}static retrieveArticleData(){fetch("/src/articleArchive/articleData.json").then((t=>t.json())).then((t=>{ArticleFiller.articleData=t,ArticleFiller.callArticle()})).catch((t=>{console.error("Error retrieving article data:",t)}))}static callArticle(){const t=document.URL,[,e]=t.split("?");if(!e)return void ArticleFiller.callDisplay();const[l]=e.split("&");if(1===e.split("&").length){ArticleFiller.grabArticle(l);const t=document.getElementById("featuredArticles"),e=document.getElementById("displayArticles"),r=document.getElementById("articleBody");t&&t.setAttribute("hidden",!0),e&&e.setAttribute("hidden",!0),r&&r.removeAttribute("hidden")}else ArticleFiller.callDisplay()}static grabArticle(t){const e=t.split(" ");t="";for(const l of e){t+=l[0].toUpperCase()+l.slice(1)}if(ArticleFiller.articleData&&t){const e=ArticleFiller.articleData[t];if(e){this.updateMetaData(e,t);const l=`author${e.author.replace(/\s/g,"")}`,r=`${e.date}_${t}`;fetch(`/src/articleArchive/${l}/${r}/${t}.md`).then((t=>{if(!t.ok)throw new Error(`Failed to fetch article: ${t.status} ${t.statusText}`);return t.text()})).then((t=>{ArticleFiller.articleMd=t,ArticleFiller.addToPage()})).catch((t=>{ArticleFiller.displayError(`Could not retrieve article. Please check the article name or try again later. (${t.message})`)}))}else ArticleFiller.displayError("Error retrieving article.")}}static updateMetaData(t,e){if(Object.keys(t)?.length>0){let l=document?.querySelector("script[type='application/ld+json']")?.textContent;if(l=l?JSON.parse(l):void 0,t?.title){const e=`${t.title} | Small Dev Talk`;document.title=e,document.querySelector("meta[property='og:title']").setAttribute("content",e),document.querySelector("meta[property='twitter:title']").setAttribute("content",e),l?.name&&(l.name=e)}if(t?.summary){const e=`${t.summary} | Small Dev Talk`;document.querySelector("meta[name='description']").setAttribute("content",e),document.querySelector("meta[property='og:description']").setAttribute("content",e),document.querySelector("meta[property='twitter:description']").setAttribute("content",e),l?.description&&(l.description=e)}if(t?.thumbnail&&t?.author&&t?.date&&e){const r=`https://smalldevtalk.net/src/articleArchive/author${t.author.split(" ").join("")}/${t.date}_${e}/${t.thumbnail}`;document.querySelector("meta[property='og:image']").setAttribute("content",r),document.querySelector("meta[property='twitter:image']").setAttribute("content",r),l?.image&&(l.image=r)}l&&(document.querySelector("script[type='application/ld+json']").textContent=JSON.stringify(l))}}static addToPage(){ArticleFiller.article=converter.makeHtml(ArticleFiller.articleMd),ArticleFiller?.article?.trim()?.length<1&&ArticleFiller?.articleMd?.trim()?.length>0?ArticleFiller.displayError("Article content could not be converted to HTML."):document?.getElementById("articleBody")&&(document.getElementById("articleBody").innerHTML=ArticleFiller.article)}static retrievePageData(){const t=new XMLHttpRequest;t.responseType="json",t.onreadystatechange=()=>{t.readyState===XMLHttpRequest.DONE&&200===t.status&&(ArticleFiller.pageData=t.response,ArticleFiller.callArticle())},t.open("GET","/src/legacyPages/legacyPagesDisplay.json"),t.send()}static callDisplay(){let t=[];const e=document.URL.split("?");e.length>1?(t=e[1].split("&"),ArticleFiller.whatPageDisplay=t[1]):(t=[],ArticleFiller.whatPageDisplay="index"),ArticleFiller.pageURL=t,1===ArticleFiller.pageURL.length?ArticleFiller.callPageDisplay=!1:(ArticleFiller.callPageDisplay=!0,"archive"===ArticleFiller.whatPageDisplay?ArticleFiller.displayArchive():ArticleFiller.changeCarousel())}static displayArchive(){document.getElementById("featuredArticles")&&document.getElementById("featuredArticles").setAttribute("hidden",!0),document.getElementById("articleBody")&&document.getElementById("articleBody").removeAttribute("hidden");let t="";const{articleData:e}=ArticleFiller;if(e)for(const[l,r]of Object.entries(e))if(r&&r.title&&r.author&&r.date&&r.thumbnail){t.trim().length<1&&(t+='\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t');const e=`src/articleArchive/author${r.author.split(" ").join("")}/${r.date}_${l}/${r.thumbnail}`;t+=`\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

${r.title}

\n\t\t\t\t\t\t\t${r.title}'s thumbnail\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t`}t.trim().length>0&&(t+="
",document.getElementById("displayArticles").innerHTML+=t)}static changeCarousel(){const t=ArticleFiller.whatPageDisplay[0].toUpperCase()+ArticleFiller.whatPageDisplay.substring(1,ArticleFiller.whatPageDisplay.length);if(document.getElementById("pageTitle")&&(document.getElementById("pageTitle").innerText=`Small Dev Talk: ${t}`),ArticleFiller&&ArticleFiller.pageData&&ArticleFiller.articleData&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay]&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay].carousel&&document.getElementById("carouselInner")){const t=ArticleFiller.pageData[ArticleFiller.whatPageDisplay].carousel;document.getElementById("carouselIndicator")&&(document.getElementById("carouselIndicator").innerHTML=""),document.getElementById("carouselInner").innerHTML="";for(let e=0;e\n\t\t\t\t`;document.getElementById("carouselIndicator")&&(document.getElementById("carouselIndicator").innerHTML+=o),o=`\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t`,document.getElementById("carouselInner").innerHTML+=o}}ArticleFiller.ArticleFiller()}static ArticleFiller(){if(ArticleFiller&&ArticleFiller.pageData&&ArticleFiller.articleData&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay]&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay].displayArticles){const t=ArticleFiller.pageData[ArticleFiller.whatPageDisplay].displayArticles;if(document.getElementById("displayArticles").innerHTML="",t&&t.length>0)for(const e in t)if(ArticleFiller.articleData[t[e]]){const l=`author${ArticleFiller.articleData[t[e]].author.split(" ").join("")}`,r=`${ArticleFiller.articleData[t[e]].date}_${t[e]}`,i=ArticleFiller.articleData[t[e]].thumbnail,a=ArticleFiller.articleData[t[e]].title,n=ArticleFiller.articleData[t[e]].summary,c=ArticleFiller.articleData[t[e]].date,o=`/src/articleArchive/${l}/${r}/${i}`,s=`\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t${a}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t\t\t${n}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tRead More\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t${c}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t`;document.getElementById("displayArticles").innerHTML+=s}}}}function init(){ArticleFiller.retrievePageData(),ArticleFiller.retrieveArticleData()}async function registerServiceWorker(){if("undefined"!=typeof navigator&&"serviceWorker"in navigator)try{return await navigator.serviceWorker.register("./src/serviceWorker/sw.js")}catch(t){return console.error("ServiceWorker registration failed:",t&&t.message?t.message:t),null}return null}function changeCarouselSlide(t){const e="active",l=document.getElementsByClassName("carousel-item");if(!l||!l.length)return;const r=Array.from(l).find((t=>t.classList.contains(e)));if(!r)return void l[0].classList.add(e);const i="next"===t?(Array.from(l).indexOf(r)+1)%l.length:(Array.from(l).indexOf(r)-1+l.length)%l.length;r.classList.remove(e),l[i].classList.add(e)}"undefined"!=typeof module&&module.exports&&(module.exports={ArticleFiller:ArticleFiller}),window.onload=async function(){await registerServiceWorker(),init()},"undefined"!=typeof module&&module.exports&&(module.exports={ArticleFiller:ArticleFiller,registerServiceWorker:registerServiceWorker}); \ No newline at end of file +const converter=new showdown.Converter;class ArticleFiller{constructor(){this.articleData,this.articleMd,this.article,this.pageData,this.pageURL,this.callPageDisplay=!0,this.whatPageDisplay="index"}static displayError(t){ArticleFiller.errMsg=t?.trim(),ArticleFiller.errMsg?.length<1&&(ArticleFiller.errMsg="Unknown error"),console.error(ArticleFiller.errMsg),ArticleFiller.article=` +
+
+
+ Error +
+ +
+ ${ArticleFiller.errMsg} +
+ +
+ + + +
+
+
+ `,document?.getElementById("articleBody")&&(document.getElementById("articleBody").innerHTML=ArticleFiller.article)}static retrieveArticleData(){return fetch("/src/articleArchive/articleData.json").then(e=>{if(!e.ok)throw new Error(`Failed to fetch article data: ${e.status} ${e.statusText}`);return e.json()}).then(e=>{ArticleFiller.articleData=e,ArticleFiller.callArticle()}).catch(e=>{console.error("Error retrieving article data:",e)})}static callArticle(){const t=document.URL,[,e]=t.split("?");if(!e){ArticleFiller.callDisplay();return}const[a]=e.split("&");if(e.split("&").length===1){ArticleFiller.grabArticle(a);const i=document.getElementById("featuredArticles"),o=document.getElementById("displayArticles"),s=document.getElementById("articleBody");i&&i.setAttribute("hidden",!0),o&&o.setAttribute("hidden",!0),s&&s.removeAttribute("hidden")}else ArticleFiller.callDisplay()}static grabArticle(t){const e=t.split(" ");t="";for(const a of e){const n=a[0].toUpperCase()+a.slice(1);t+=n}if(ArticleFiller.articleData&&t){const a=ArticleFiller.articleData[t];if(a){this.updateMetaData(a,t);const n=`author${a.author.replace(/\s/g,"")}`,i=`${a.date}_${t}`,o=`/src/articleArchive/${n}/${i}/${t}.md`;fetch(o).then(s=>{if(!s.ok)throw new Error(`Failed to fetch article: ${s.status} ${s.statusText}`);return s.text()}).then(s=>{ArticleFiller.articleMd=s,ArticleFiller.addToPage()}).catch(s=>{ArticleFiller.displayError(`Could not retrieve article. Please check the article name or try again later. (${s.message})`)})}else ArticleFiller.displayError("Error retrieving article.")}}static updateMetaData(t,e){if(Object.keys(t)?.length>0){let a=document?.querySelector("script[type='application/ld+json']")?.textContent;if(a?a=JSON.parse(a):a=void 0,t?.title){const n=`${t.title} | Small Dev Talk`;document.title=n,document.querySelector("meta[property='og:title']").setAttribute("content",n),document.querySelector("meta[property='twitter:title']").setAttribute("content",n),a?.name&&(a.name=n)}if(t?.summary){const n=`${t.summary} | Small Dev Talk`;document.querySelector("meta[name='description']").setAttribute("content",n),document.querySelector("meta[property='og:description']").setAttribute("content",n),document.querySelector("meta[property='twitter:description']").setAttribute("content",n),a?.description&&(a.description=n)}if(t?.thumbnail&&t?.author&&t?.date&&e){const n=`https://smalldevtalk.net/src/articleArchive/author${t.author.split(" ").join("")}/${t.date}_${e}/${t.thumbnail}`;document.querySelector("meta[property='og:image']").setAttribute("content",n),document.querySelector("meta[property='twitter:image']").setAttribute("content",n),a?.image&&(a.image=n)}a&&(document.querySelector("script[type='application/ld+json']").textContent=JSON.stringify(a))}}static addToPage(){if(ArticleFiller.article=converter.makeHtml(ArticleFiller.articleMd),ArticleFiller?.article?.trim()?.length<1&&ArticleFiller?.articleMd?.trim()?.length>0){ArticleFiller.displayError("Article content could not be converted to HTML.");return}document?.getElementById("articleBody")&&(document.getElementById("articleBody").innerHTML=ArticleFiller.article)}static retrievePageData(){const t=new XMLHttpRequest,e="/src/legacyPages/legacyPagesDisplay.json";t.responseType="json",t.onreadystatechange=()=>{t.readyState===XMLHttpRequest.DONE&&t.status===200&&(ArticleFiller.pageData=t.response,ArticleFiller.callArticle())},t.open("GET",e),t.send()}static callDisplay(){let t=[];const a=document.URL.split("?");a.length>1?(t=a[1].split("&"),ArticleFiller.whatPageDisplay=t[1]):(t=[],ArticleFiller.whatPageDisplay="index"),ArticleFiller.pageURL=t,ArticleFiller.pageURL.length===1?ArticleFiller.callPageDisplay=!1:(ArticleFiller.callPageDisplay=!0,ArticleFiller.whatPageDisplay==="archive"?ArticleFiller.displayArchive():ArticleFiller.changeCarousel())}static displayArchive(){document.getElementById("featuredArticles")&&document.getElementById("featuredArticles").setAttribute("hidden",!0),document.getElementById("articleBody")&&document.getElementById("articleBody").removeAttribute("hidden");let t="";const{articleData:e}=ArticleFiller;if(e){for(const[a,n]of Object.entries(e))if(n&&n.title&&n.author&&n.date&&n.thumbnail){t.trim().length<1&&(t+=` +
+
+ `);const i=`src/articleArchive/author${n.author.split(" ").join("")}/${n.date}_${a}/${n.thumbnail}`;t+=` + + `}}t.trim().length>0&&(t+="
",document.getElementById("displayArticles").innerHTML+=t)}static changeCarousel(){const t=ArticleFiller.whatPageDisplay[0].toUpperCase()+ArticleFiller.whatPageDisplay.substring(1,ArticleFiller.whatPageDisplay.length);if(document.getElementById("pageTitle")&&(document.getElementById("pageTitle").innerText=`Small Dev Talk: ${t}`),ArticleFiller&&ArticleFiller.pageData&&ArticleFiller.articleData&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay]&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay].carousel&&document.getElementById("carouselInner")){const e=ArticleFiller.pageData[ArticleFiller.whatPageDisplay].carousel;document.getElementById("carouselIndicator")&&(document.getElementById("carouselIndicator").innerHTML=""),document.getElementById("carouselInner").innerHTML="";for(let a=0;a + `;document.getElementById("carouselIndicator")&&(document.getElementById("carouselIndicator").innerHTML+=c),c=` + + `,document.getElementById("carouselInner").innerHTML+=c}}ArticleFiller.ArticleFiller()}static ArticleFiller(){if(ArticleFiller&&ArticleFiller.pageData&&ArticleFiller.articleData&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay]&&ArticleFiller.pageData[ArticleFiller.whatPageDisplay].displayArticles){const t=ArticleFiller.pageData[ArticleFiller.whatPageDisplay].displayArticles;if(document.getElementById("displayArticles").innerHTML="",t&&t.length>0){for(const e in t)if(ArticleFiller.articleData[t[e]]){const a=`author${ArticleFiller.articleData[t[e]].author.split(" ").join("")}`,n=`${ArticleFiller.articleData[t[e]].date}_${t[e]}`,i=ArticleFiller.articleData[t[e]].thumbnail,o=ArticleFiller.articleData[t[e]].title,s=ArticleFiller.articleData[t[e]].summary,d=ArticleFiller.articleData[t[e]].date,l=`/src/articleArchive/${a}/${n}/${i}`,c=` +
+
+ + Thumbnail for ${o} + +
+
+

+ + ${o} + +

+
+
+

+ ${s} + + Read More + +

+
+
+

+ + ${d} + +

+
+
+ + `;document.getElementById("displayArticles").innerHTML+=c}}}}}typeof module<"u"&&module.exports&&(module.exports={ArticleFiller});function init(){ArticleFiller.retrievePageData(),ArticleFiller.retrieveArticleData()}async function registerServiceWorker(){if(typeof navigator<"u"&&"serviceWorker"in navigator)try{return await navigator.serviceWorker.register("./src/serviceWorker/sw.js")}catch(r){return console.error("ServiceWorker registration failed:",r&&r.message?r.message:r),null}return null}window.onload=async function(){await registerServiceWorker(),init()},typeof module<"u"&&module.exports&&(module.exports={ArticleFiller,registerServiceWorker});function changeCarouselSlide(r){const t="active",e=document.getElementsByClassName("carousel-item");if(!e||!e.length)return;const a=Array.from(e).find(i=>i.classList.contains(t));if(!a){e[0].classList.add(t);return}const n=r==="next"?(Array.from(e).indexOf(a)+1)%e.length:(Array.from(e).indexOf(a)-1+e.length)%e.length;a.classList.remove(t),e[n].classList.add(t)} diff --git a/src/style.min.css b/src/style.min.css index cc2ba9e..d2aeb0e 100644 --- a/src/style.min.css +++ b/src/style.min.css @@ -1 +1 @@ -#header h1,#header nav ul li,#header ul li{float:left}#content .featured .photo,#content .featured .text,#content .postnav ul,#header ul,#sidebar ul{list-style-type:none}#content .atitle,#content .featured .text .readmore,#content .featured h2.title{font-size:.9em;text-transform:uppercase}#sidebar .ads,.archive-title,body{text-align:center}#footer p,#wrapper{margin:auto;text-align:left}body{color:#000;font:12px Verdana;margin:0;padding:0}img{border:0}.break{clear:both;font-size:0;height:0;width:0}#wrapper{max-width:100%}#header{height:200px}#header ul{clear:both}#header .pages{display:flex;float:left;margin-bottom:0;width:100%}#header .pages li{font-size:.7em;font-weight:700;text-transform:uppercase}#header .pages li a{color:#fff;display:block;padding:8px 10px;text-decoration:none}#content .details a:hover,#footer a:hover,#header .pages li a:hover{text-decoration:underline}#header nav{width:100%;background-color:#000;overflow-x:auto;white-space:nowrap}#header nav ul li:hover>ul{display:block}#header nav ul{background:-moz-linear-gradient;background:-webkit-linear-gradient;box-shadow:0 0 9px rgba (0,0,0,.15);display:inline-table;list-style:none;padding:0 2%;position:relative}#header nav ul li:hover{background:-moz-linear-gradient(top,#4f5964 0,#5f6975 40%);background:-webkit-linear-gradient(top,#4f5964 0,#5f6975 40%);background:linear-gradient(top,#4f5964 0,#5f6975 40%)}#header nav ul li a{color:#000;display:block;padding:25px 40px;text-decoration:none}#header nav ul ul{display:none;background:#5f6975;border-radius:0;padding:0;position:absolute;top:100%}#content .featured .thumb,#content .post img,.articleBody img{background-color:#f2f2f1;border:1px solid #e9e9e9;padding:5px}#header nav ul ul li{border-bottom:1px solid #575f6a;border-top:1px solid #6b727c;float:none;position:relative}#header nav ul ul li a{color:#fff;padding:15px 40px}#header nav ul ul ul{left:100%;position:absolute;top:0}#header h1{clear:both;padding:min(1%,10px) 2%}#header .ad{float:right;padding-top:30px}#body{padding:10px 8px;display:flex;justify-content:center;gap:min(20px,10%)}.articleBody{margin-left:3%;margin-right:3%}.articleBody img{vertical-align:middle;width:100%}#content{border:1px solid #afafaf;box-shadow:0 0 10px rgba(0,0,0,.5);clear:both;float:left;font-family:Arial;max-width:676px;width:100%}#content .foot{padding:25px 8px}#content .atitle,#content .featured h2.title,#sidebar h2{font-weight:400;padding:5px 8px}#content .atitle{float:left;margin:10px 30px}#content .featured{padding:5px 30px 10px}#content .featured h2.title{background-color:#212121;color:#fff;float:left;margin-bottom:10px}#content .featured .thumb{clear:both;height:315px;width:590px}#content .featured .b{height:315px;overflow:hidden;position:relative;width:589px}#content .photo li{left:0;position:absolute;top:0;z-index:0}#content .photo li.first{z-index:2}#content .photo li img{width:589px}#content .featured .text li{background:url(images/shade.png);color:#fff;font-family:Verdana;height:285px;padding:15px;position:absolute;right:-270px;top:0;width:230px;z-index:4}#content .featured .text li.first{right:0}#content .featured .text h2{font-size:1.6em;margin-bottom:15px}#content .featured .text p,#content .post p{line-height:1.6em;margin-bottom:15px}#content .featured .text a,#footer a{color:#fff;text-decoration:none}#content .featured .text .readmore{font-weight:700}#content .post{border-top:1px solid #e9e9e9;clear:both;margin:0 30px}#content .first{border-top:0}#content .post .l{float:left;padding:15px 0}#content .post .r{padding:15px 0;width:100%}#content .post h2{font-size:1.8em;font-weight:400;margin-bottom:15px}#content .post h2 a,#sidebar ul li a{color:#191919;text-decoration:none}#content .details{float:left;font-size:.85em;margin-bottom:0!important;text-transform:uppercase}#content .details a{color:#191919;margin:0 5px;text-decoration:none}#content .comments a{background-color:#212121;color:#fff;display:block;font-family:Verdana;font-size:.9em;padding:2px 6px;text-decoration:none}#content .single li,#sidebar ul li{line-height:1.5em;padding:2px 0}#content .postnav{clear:both;float:right;padding:0 2%}#content .postnav ul li{float:left;font-family:Arial;padding:0 4px}#content .postnav ul li a{border:1px solid #e1e1e1;color:#4f4f4f;display:block;padding:4px 8px;text-decoration:none}#content .postnav ul li a:hover{border-color:#fff}#content .single{padding:10px 30px}#content .single h2{font-size:1.4em;margin-bottom:10px;text-transform:none}#content .single p{line-height:1.5em;margin-bottom:10px}#content .single ol,#content .single ul{list-style-position:inside;margin-bottom:10px}#content .single blockquote{background-color:#eee;border-color:#e0e0e0;border-style:solid;border-width:1px 0;margin-bottom:10px;padding:10px 10px 5px}#footer,#sidebar .search button,#sidebar h2{background-color:#212121;color:#fff}#content .single h3,#content .single h4,#content .single h5,#content .single h6{font-size:1.2em;margin-bottom:5px}.archive-title{color:#000;text-decoration:none}.archive-link{text-decoration:none}.archive-display{border:1px solid rgba(0,0,0,.342);margin:auto auto 2%;max-width:30%!important;min-width:200px}.archive-display img{margin:auto;width:100%}#sidebar{float:right;width:330px}@media screen and (max-width:900px){#body{display:block}#sidebar{margin-top:1%;width:100%}#content{max-width:100%}}#sidebar .box{border:2px solid #e1e1e1;margin-bottom:15px;padding:10px}#sidebar h2{font-size:.9em;margin-bottom:10px;text-transform:uppercase;width:130px}#sidebar ul li{border-bottom:1px solid #e9e9e9}#sidebar .ads{margin-bottom:10px}#sidebar .ads img{margin:4px}#sidebar .search{border:2px solid #e1e1e1;height:29px;margin-bottom:10px}#sidebar .search input{border:0;float:left;margin:6px 4px;width:220px}#sidebar .search button{border:0;float:right;font-size:.8em;font-weight:700;height:29px;text-transform:uppercase;width:38px}#footer{clear:both}#footer p{font-size:.9em;padding:15px 0;width:940px}input:user-valid,select:user-valid,textarea:user-valid{border:1px solid #28a745}input:user-invalid,select:user-invalid,textarea:user-invalid{border:1px solid #dc3545} \ No newline at end of file +body{color:#000;font:12px Verdana;text-align:center;margin:0;padding:0}img{border:0}.break{clear:both;font-size:0;height:0;width:0}#wrapper{margin:auto;text-align:left;max-width:100%}#header{height:200px}#header ul{clear:both;list-style-type:none}#header ul li{float:left}#header .pages{display:flex;float:left;margin-bottom:0;width:100%}#header .pages li{font-size:.7em;font-weight:700;text-transform:uppercase}#header .pages li a{color:#fff;display:block;padding:8px 10px;text-decoration:none}#header .pages li a:hover{text-decoration:underline}#header nav{width:100%;background-color:#000;overflow-x:auto;white-space:nowrap}#header nav ul li:hover>ul{display:block}#header nav ul{background:linear-gradient (top,#efefef 0%,#bbbbbb 100%);background:-moz-linear-gradient (top,#efefef 0%,#bbbbbb 100%);background:-webkit-linear-gradient (top,#efefef 0%,#bbbbbb 100%);box-shadow:0 0 9px rgba (0,0,0,.15);display:inline-table;list-style:none;padding:0 2%;position:relative}#header nav ul li{float:left}#header nav ul li:hover{background:-moz-linear-gradient(top,#4f5964 0%,#5f6975 40%);background:-webkit-linear-gradient(top,#4f5964 0%,#5f6975 40%);background:linear-gradient(top,#4f5964,#5f6975 40%)}#header nav ul li a{color:#000;display:block;padding:25px 40px;text-decoration:none}#header nav ul ul{display:none;background:#5f6975;border-radius:0;padding:0;position:absolute;top:100%}#header nav ul ul li{border-bottom:1px solid #575f6a;border-top:1px solid #6b727c;float:none;position:relative}#header nav ul ul li a{color:#fff;padding:15px 40px}#header nav ul ul ul{left:100%;position:absolute;top:0}#header h1{clear:both;float:left;padding:min(1%,10px) 2%}#header .ad{float:right;padding-top:30px}#body{padding:10px 8px;display:flex;justify-content:center;gap:min(20px,10%)}.articleBody{margin-left:3%;margin-right:3%}.articleBody img{background-color:#f2f2f1;border:1px solid #e9e9e9;padding:5px;vertical-align:middle;width:100%}#content{border:1px solid rgb(175,175,175) (128,128,128,.568);box-shadow:0 0 10px #00000080;clear:both;float:left;font-family:Arial;max-width:676px;width:100%}#content .foot{padding:25px 8px}#content .atitle{float:left;font-size:.9em;font-weight:400;margin:10px 30px;padding:5px 8px;text-transform:uppercase}#content .featured{padding:5px 30px 10px}#content .featured h2.title{background-color:#212121;color:#fff;float:left;font-size:.9em;font-weight:400;margin-bottom:10px;padding:5px 8px;text-transform:uppercase}#content .featured .thumb{background-color:#f2f2f1;border:1px solid #e9e9e9;clear:both;height:315px;padding:5px;width:590px}#content .featured .b{height:315px;overflow:hidden;position:relative;width:589px}#content .featured .photo{list-style-type:none}#content .photo li{left:0;position:absolute;top:0;z-index:0}#content .photo li.first{z-index:2}#content .photo li img{width:589px}#content .featured .text{list-style-type:none}#content .featured .text li{background:url(images/shade.png) repeat 0 0;color:#fff;font-family:Verdana;height:285px;padding:15px;position:absolute;right:-270px;top:0;width:230px;z-index:4}#content .featured .text li.first{right:0}#content .featured .text h2{font-size:1.6em;margin-bottom:15px}#content .featured .text p{line-height:1.6em;margin-bottom:15px}#content .featured .text a{color:#fff;text-decoration:none}#content .featured .text .readmore{font-size:.9em;font-weight:700;text-transform:uppercase}#content .post{border-top:1px solid #e9e9e9;clear:both;margin:0 30px}#content .first{border-top:0}#content .post .l{float:left;padding:15px 0}#content .post img{background-color:#f2f2f1;border:1px solid #e9e9e9;padding:5px}#content .post .r{padding:15px 0;width:100%}#content .post h2{font-size:1.8em;font-weight:400;margin-bottom:15px}#content .post h2 a{color:#191919;text-decoration:none}#content .post p{line-height:1.6em;margin-bottom:15px}#content .details{float:left;font-size:.85em;margin-bottom:0!important;text-transform:uppercase}#content .details a{color:#191919;margin:0 5px;text-decoration:none}#content .details a:hover{text-decoration:underline}#content .comments a{background-color:#212121;color:#fff;display:block;font-family:Verdana;font-size:.9em;padding:2px 6px;text-decoration:none}#content .postnav{clear:both;float:right;padding:0 2%}#content .postnav ul{list-style-type:none}#content .postnav ul li{float:left;font-family:Arial;padding:0 4px}#content .postnav ul li a{border:1px solid #e1e1e1;color:#4f4f4f;display:block;padding:4px 8px;text-decoration:none}#content .postnav ul li a:hover{border-color:#fff}#content .single{padding:10px 30px}#content .single h2{font-size:1.4em;margin-bottom:10px;text-transform:none}#content .single p{line-height:1.5em;margin-bottom:10px}#content .single ul,#content .single ol{list-style-position:inside;margin-bottom:10px}#content .single li{line-height:1.5em;padding:2px 0}#content .single blockquote{background-color:#eee;border-color:#e0e0e0;border-style:solid;border-width:1px 0;margin-bottom:10px;padding:10px 10px 5px}#content .single h3,#content .single h4,#content .single h5,#content .single h6{font-size:1.2em;margin-bottom:5px}.archive-title{color:#000;text-align:center;text-decoration:none}.archive-link{text-decoration:none}.archive-display{border:1px solid rgba(0,0,0,.342);margin:auto auto 2%;max-width:30%!important;min-width:200px}.archive-display img{margin:auto;width:100%}#sidebar{float:right;width:330px}@media screen and (max-width:900px){#body{display:block}#sidebar{margin-top:1%;width:100%}#content{max-width:100%}}#sidebar .box{border:2px solid #e1e1e1;margin-bottom:15px;padding:10px}#sidebar h2{background-color:#212121;color:#fff;font-size:.9em;font-weight:400;margin-bottom:10px;padding:5px 8px;text-transform:uppercase;width:130px}#sidebar ul{list-style-type:none}#sidebar ul li{border-bottom:1px solid #e9e9e9;line-height:1.5em;padding:2px 0}#sidebar ul li a{color:#191919;text-decoration:none}#sidebar .ads{margin-bottom:10px;text-align:center}#sidebar .ads img{margin:4px}#sidebar .search{border:2px solid #e1e1e1;height:29px;margin-bottom:10px}#sidebar .search input{border:0;float:left;margin:6px 4px;width:220px}#sidebar .search button{background-color:#212121;border:0;color:#fff;float:right;font-size:.8em;font-weight:700;height:29px;text-transform:uppercase;width:38px}#footer{background-color:#212121;clear:both;color:#fff}#footer p{font-size:.9em;margin:auto;padding:15px 0;text-align:left;width:940px}#footer a{color:#fff;text-decoration:none}#footer a:hover{text-decoration:underline}input:user-valid,textarea:user-valid,select:user-valid{border:1px solid #28a745}input:user-invalid,textarea:user-invalid,select:user-invalid{border:1px solid #dc3545}