From 4515bc235976b1ea6736620107fa9063ec50d565 Mon Sep 17 00:00:00 2001 From: Nulo Date: Fri, 31 Mar 2023 20:38:34 -0300 Subject: [PATCH] generar report.html (fixes #7) --- package.json | 1 + pnpm-lock.yaml | 66 +++++++++++++++++++++++++++++++------------------- src/index.ts | 64 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 97 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 202b051..e051703 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "author": "", "license": "ISC", "dependencies": { + "@nulo/html.js": "^0.0.9", "domhandler": "^5.0.3", "htmlparser2": "^8.0.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 921a0a9..97d95f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,30 +1,42 @@ -lockfileVersion: 5.4 - -specifiers: - '@types/htmlparser2': ^3.10.3 - '@types/node': ^18.11.9 - domhandler: ^5.0.3 - htmlparser2: ^8.0.1 - typescript: ^4.9.3 +lockfileVersion: '6.0' dependencies: - domhandler: 5.0.3 - htmlparser2: 8.0.1 + '@nulo/html.js': + specifier: ^0.0.9 + version: 0.0.9 + domhandler: + specifier: ^5.0.3 + version: 5.0.3 + htmlparser2: + specifier: ^8.0.1 + version: 8.0.1 devDependencies: - '@types/htmlparser2': 3.10.3 - '@types/node': 18.11.9 - typescript: 4.9.3 + '@types/htmlparser2': + specifier: ^3.10.3 + version: 3.10.3 + '@types/node': + specifier: ^18.11.9 + version: 18.11.9 + typescript: + specifier: ^4.9.3 + version: 4.9.3 packages: - /@types/domutils/1.7.4: + /@nulo/html.js@0.0.9: + resolution: {integrity: sha512-/mdpdH3cjL52X/V0H3LLxydcx0vkjQneuk91L9SkBXIoEUwA1nK6sR23MpvoT7zwqMph/fx3fevz0llXvdzayQ==, tarball: https://gitea.nulo.in/api/packages/Nulo/npm/%40nulo%2Fhtml.js/-/0.0.9/html.js-0.0.9.tgz} + dependencies: + html-escaper: 3.0.3 + dev: false + + /@types/domutils@1.7.4: resolution: {integrity: sha512-w542nRQ0vpXQjLYP52LKqrugQtUq580dEDiDIyZ6IBmV8a3LXjGVNxfj/jUQxS0kDsbZAWsSxQOcTfVX3HRdwg==} dependencies: domhandler: 2.4.2 dev: true - /@types/htmlparser2/3.10.3: + /@types/htmlparser2@3.10.3: resolution: {integrity: sha512-XA74aD+acytofnZic9n83Rxy/IZ259299bYPx5SEyx7uymPi79lRyKDkhJlsuCaPHB7rEoTEhRN4Vm2G5WmHHg==} dependencies: '@types/domutils': 1.7.4 @@ -32,11 +44,11 @@ packages: domhandler: 2.4.2 dev: true - /@types/node/18.11.9: + /@types/node@18.11.9: resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} dev: true - /dom-serializer/2.0.0: + /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: domelementtype: 2.3.0 @@ -44,28 +56,28 @@ packages: entities: 4.4.0 dev: false - /domelementtype/1.3.1: + /domelementtype@1.3.1: resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} dev: true - /domelementtype/2.3.0: + /domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: false - /domhandler/2.4.2: + /domhandler@2.4.2: resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} dependencies: domelementtype: 1.3.1 dev: true - /domhandler/5.0.3: + /domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} dependencies: domelementtype: 2.3.0 dev: false - /domutils/3.0.1: + /domutils@3.0.1: resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} dependencies: dom-serializer: 2.0.0 @@ -73,12 +85,16 @@ packages: domhandler: 5.0.3 dev: false - /entities/4.4.0: + /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} dev: false - /htmlparser2/8.0.1: + /html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + dev: false + + /htmlparser2@8.0.1: resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==} dependencies: domelementtype: 2.3.0 @@ -87,7 +103,7 @@ packages: entities: 4.4.0 dev: false - /typescript/4.9.3: + /typescript@4.9.3: resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} engines: {node: '>=4.2.0'} hasBin: true diff --git a/src/index.ts b/src/index.ts index 4b64a89..aad90a9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,18 @@ import { Parser } from "htmlparser2"; import { DomHandler, Element } from "domhandler"; -import { readdir, readFile } from "fs/promises"; -import { join } from "path"; +import { readdir, readFile, writeFile } from "fs/promises"; +import { join, relative } from "path"; +import { + doctype, + metaUtf8, + render, + title, + ul, + li, + h2, + ol, + basicElement, +} from "@nulo/html.js"; const { argv } = process; const dirPath = argv[2] || "."; @@ -15,14 +26,14 @@ interface Thing { | "media-no-src"; description: string; } -interface Report { +type Report = { things: Thing[]; -} +}; -interface Page { +type Page = { report: Report; rawHtml: string; -} +}; function recurseElement(page: Page, el: Element) { const { report, rawHtml } = page; @@ -140,9 +151,9 @@ async function recurseDirectory(reports: Reports, path: string) { ); } await recurseDirectory(reports, dirPath); -const totalThings = Object.values(reports) - .map((r) => r.things) - .flat(); +const totalThings = [...reports.entries()].flatMap(([name, r]) => + r.things.map((t) => ({ ...t, fileName: name })) +); const kinds = new Set(totalThings.map((t) => t.type)); console.log( `Finished with ${Object.keys(reports).length} files read, ${ @@ -168,3 +179,38 @@ const linkHttp = totalThings.filter((t) => t.type === "link-http").length; console.log( `==> ${linkHttp} links to HTTP sites, which is not a real concern unless it's a key part of the site's navigation.` ); + +const code = basicElement("code"); + +const reportOutput = "report.html"; +console.info(`Writing report to ${reportOutput}`); +const html = render( + doctype(), + metaUtf8, + title("site-analyzer report"), + + ul( + li( + `${pathBasedCount} problems that affect users using legacy IPFS gateways` + ), + li( + `${mediaHttp} problems that make the website not self-contained, making it miss content if HTTP is unavailable` + ), + li( + `${linkHttp} links to HTTP sites, which is not a real concern unless it's a key part of the site's navigation.` + ) + ), + ...[...kinds] + .sort((a, b) => (b === "link-http" ? -1 : 0)) + .flatMap((kind) => [ + h2(kind), + ol( + ...totalThings + .filter((t) => t.type === kind) + .map((t) => + li(code(relative(dirPath, t.fileName)), ": ", code(t.description)) + ) + ), + ]) +); +await writeFile(reportOutput, html);