diff --git a/package.json b/package.json index 896c83d..ecea7e3 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-typescript": "^11.1.5", + "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-url": "^8.0.2", "@types/node": "^18.18.12", "ava": "^5.3.1", @@ -81,7 +82,11 @@ "rollup-plugin-postcss": "^4.0.2", "tslib": "^2.6.2", "tsx": "^4.4.0", - "typescript": "^5.3.2" + "typescript": "^5.3.2", + "puppeteer": "^21.5.2", + "mime": "^4.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "types": "./types/index.d.ts", "ava": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6238697..639f048 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,6 +31,9 @@ devDependencies: '@rollup/plugin-node-resolve': specifier: ^15.2.3 version: 15.2.3(rollup@3.29.4) + '@rollup/plugin-terser': + specifier: ^0.4.4 + version: 0.4.4(rollup@3.29.4) '@rollup/plugin-typescript': specifier: ^11.1.5 version: 11.1.5(rollup@3.29.4)(tslib@2.6.2)(typescript@5.3.2) @@ -55,12 +58,24 @@ devDependencies: lint-staged: specifier: ^13.3.0 version: 13.3.0 + mime: + specifier: ^4.0.0 + version: 4.0.0 nyc: specifier: ^15.1.0 version: 15.1.0 postcss: specifier: ^8.4.31 version: 8.4.31 + puppeteer: + specifier: ^21.5.2 + version: 21.5.2(typescript@5.3.2) + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) rollup: specifier: ^3.29.4 version: 3.29.4 @@ -649,6 +664,13 @@ packages: engines: {node: '>=6.0.0'} dev: true + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} @@ -680,6 +702,22 @@ packages: fastq: 1.15.0 dev: true + /@puppeteer/browsers@1.8.0: + resolution: {integrity: sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==} + engines: {node: '>=16.3.0'} + hasBin: true + dependencies: + debug: 4.3.4 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.3.1 + tar-fs: 3.0.4 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: true + /@rollup/plugin-babel@6.0.4(@babel/core@7.23.3)(rollup@3.29.4): resolution: {integrity: sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==} engines: {node: '>=14.0.0'} @@ -717,6 +755,21 @@ packages: rollup: 3.29.4 dev: true + /@rollup/plugin-terser@0.4.4(rollup@3.29.4): + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + rollup: 3.29.4 + serialize-javascript: 6.0.1 + smob: 1.4.1 + terser: 5.24.0 + dev: true + /@rollup/plugin-typescript@11.1.5(rollup@3.29.4)(tslib@2.6.2)(typescript@5.3.2): resolution: {integrity: sha512-rnMHrGBB0IUEv69Q8/JGRD/n4/n6b3nfpufUu26axhUcboUzv/twfZU8fIBbTOphRAe0v8EyxzeDpKXqGHfyDA==} engines: {node: '>=14.0.0'} @@ -766,6 +819,10 @@ packages: picomatch: 2.3.1 rollup: 3.29.4 + /@tootallnate/quickjs-emscripten@0.23.0: + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + dev: true + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -803,6 +860,14 @@ packages: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 18.18.12 + dev: true + optional: true + /acorn-walk@8.3.0: resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} engines: {node: '>=0.4.0'} @@ -814,6 +879,15 @@ packages: hasBin: true dev: true + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -891,6 +965,10 @@ packages: sprintf-js: 1.0.3 dev: true + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + /array-find-index@1.0.2: resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} engines: {node: '>=0.10.0'} @@ -916,6 +994,13 @@ packages: engines: {node: '>=12'} dev: true + /ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.2 + dev: true + /ava@5.3.1: resolution: {integrity: sha512-Scv9a4gMOXB6+ni4toLuhAm9KYWEjsgBglJl+kMGI5+IVDt120CCDZyB5HNU9DjmLI2t4I0GbnxGLmmRfGTJGg==} engines: {node: '>=14.19 <15 || >=16.15 <17 || >=18'} @@ -973,10 +1058,23 @@ packages: - supports-color dev: true + /b4a@1.6.4: + resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /basic-ftp@5.0.3: + resolution: {integrity: sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==} + engines: {node: '>=10.0.0'} + dev: true + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -1015,6 +1113,21 @@ packages: update-browserslist-db: 1.0.13(browserslist@4.22.1) dev: true + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -1030,6 +1143,11 @@ packages: write-file-atomic: 3.0.3 dev: true + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + /callsites@4.1.0: resolution: {integrity: sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==} engines: {node: '>=12.20'} @@ -1112,6 +1230,16 @@ packages: fsevents: 2.3.3 dev: true + /chromium-bidi@0.4.33(devtools-protocol@0.0.1203626): + resolution: {integrity: sha512-IxoFM5WGQOIAd95qrSXzJUv4eXIrh+RvU3rwwqIiwYuvfE7U/Llj4fejbsJnjJMUYCuGtVQsY2gv7oGl4aTNSQ==} + peerDependencies: + devtools-protocol: '*' + dependencies: + devtools-protocol: 0.0.1203626 + mitt: 3.0.1 + urlpattern-polyfill: 9.0.0 + dev: true + /chunkd@2.0.1: resolution: {integrity: sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==} dev: true @@ -1215,6 +1343,10 @@ packages: engines: {node: '>=16'} dev: true + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} @@ -1265,6 +1397,30 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /cosmiconfig@8.3.6(typescript@5.3.2): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.3.2 + dev: true + + /cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1385,6 +1541,11 @@ packages: array-find-index: 1.0.2 dev: true + /data-uri-to-buffer@6.0.1: + resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==} + engines: {node: '>= 14'} + dev: true + /date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} engines: {node: '>=6'} @@ -1434,6 +1595,15 @@ packages: strip-bom: 4.0.0 dev: true + /degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + dev: true + /del-cli@5.1.0: resolution: {integrity: sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==} engines: {node: '>=14.16'} @@ -1471,6 +1641,10 @@ packages: slash: 4.0.0 dev: true + /devtools-protocol@0.0.1203626: + resolution: {integrity: sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g==} + dev: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1526,6 +1700,12 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: true + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + /entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: true @@ -1595,12 +1775,29 @@ packages: engines: {node: '>=12'} dev: true + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true dev: true + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + /estree-walker@0.6.1: resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} dev: true @@ -1636,10 +1833,28 @@ packages: strip-final-newline: 3.0.0 dev: true + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: true + /fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} dev: true + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + dev: true + /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -1657,6 +1872,12 @@ packages: reusify: 1.0.4 dev: true + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: true + /figures@5.0.0: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} engines: {node: '>=14'} @@ -1717,6 +1938,15 @@ packages: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} dev: true + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -1753,6 +1983,13 @@ packages: engines: {node: '>=8.0.0'} dev: true + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1764,6 +2001,18 @@ packages: resolve-pkg-maps: 1.0.0 dev: true + /get-uri@6.0.2: + resolution: {integrity: sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==} + engines: {node: '>= 14'} + dependencies: + basic-ftp: 5.0.3 + data-uri-to-buffer: 6.0.1 + debug: 4.3.4 + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1870,6 +2119,26 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} @@ -1888,6 +2157,10 @@ packages: postcss: 8.4.31 dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + /ignore-by-default@2.1.0: resolution: {integrity: sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==} engines: {node: '>=10 <11 || >=12 <13 || >=14'} @@ -1905,6 +2178,14 @@ packages: import-from: 3.0.0 dev: true + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + /import-from@3.0.0: resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} engines: {node: '>=8'} @@ -1938,6 +2219,14 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /ip@1.1.8: + resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} + dev: true + + /ip@2.0.0: + resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: true + /irregular-plurals@3.5.0: resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==} engines: {node: '>=8'} @@ -2145,6 +2434,13 @@ packages: esprima: 4.0.1 dev: true + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -2161,6 +2457,12 @@ packages: hasBin: true dev: true + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -2292,6 +2594,13 @@ packages: wrap-ansi: 8.1.0 dev: true + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: true + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -2305,6 +2614,11 @@ packages: yallist: 4.0.0 dev: true + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: true + /magic-string@0.30.5: resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} engines: {node: '>=12'} @@ -2410,6 +2724,12 @@ packages: hasBin: true dev: true + /mime@4.0.0: + resolution: {integrity: sha512-pzhgdeqU5pJ9t5WK9m4RT4GgGWqYJylxUf62Yb9datXRwdcw5MjiD1BYI5evF8AgTXN9gtKX3CFLvCUL5fAhEA==} + engines: {node: '>=16'} + hasBin: true + dev: true + /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -2444,6 +2764,14 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: true + + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: true + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -2462,6 +2790,23 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true + /netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + /node-preload@0.2.1: resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} engines: {node: '>=8'} @@ -2669,6 +3014,31 @@ packages: engines: {node: '>=6'} dev: true + /pac-proxy-agent@7.0.1: + resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + engines: {node: '>= 14'} + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.0 + debug: 4.3.4 + get-uri: 6.0.2 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + pac-resolver: 7.0.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /pac-resolver@7.0.0: + resolution: {integrity: sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==} + engines: {node: '>= 14'} + dependencies: + degenerator: 5.0.1 + ip: 1.1.8 + netmask: 2.0.2 + dev: true + /package-hash@4.0.0: resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} engines: {node: '>=8'} @@ -2679,6 +3049,13 @@ packages: release-zalgo: 1.0.0 dev: true + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -2734,6 +3111,10 @@ packages: engines: {node: '>=8'} dev: true + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: true + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -3166,20 +3547,112 @@ packages: fromentries: 1.3.2 dev: true + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + /promise.series@0.2.0: resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} engines: {node: '>=0.12'} dev: true + /proxy-agent@6.3.1: + resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: true + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /puppeteer-core@21.5.2: + resolution: {integrity: sha512-v4T0cWnujSKs+iEfmb8ccd7u4/x8oblEyKqplqKnJ582Kw8PewYAWvkH4qUWhitN3O2q9RF7dzkvjyK5HbzjLA==} + engines: {node: '>=16.13.2'} + dependencies: + '@puppeteer/browsers': 1.8.0 + chromium-bidi: 0.4.33(devtools-protocol@0.0.1203626) + cross-fetch: 4.0.0 + debug: 4.3.4 + devtools-protocol: 0.0.1203626 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /puppeteer@21.5.2(typescript@5.3.2): + resolution: {integrity: sha512-BaAGJOq8Fl6/cck6obmwaNLksuY0Bg/lIahCLhJPGXBFUD2mCffypa4A592MaWnDcye7eaHmSK9yot0pxctY8A==} + engines: {node: '>=16.13.2'} + requiresBuild: true + dependencies: + '@puppeteer/browsers': 1.8.0 + cosmiconfig: 8.3.6(typescript@5.3.2) + puppeteer-core: 21.5.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + dev: true + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + dev: true + /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} dev: true + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: true + + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: true + /read-pkg-up@8.0.0: resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} engines: {node: '>=12'} @@ -3237,6 +3710,11 @@ packages: resolve-from: 5.0.0 dev: true + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + /resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -3339,10 +3817,20 @@ packages: queue-microtask: 1.2.3 dev: true + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + /safe-identifier@0.4.2: resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} dev: true + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: true + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3363,6 +3851,12 @@ packages: type-fest: 0.13.1 dev: true + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true @@ -3406,11 +3900,46 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: true + + /smob@1.4.1: + resolution: {integrity: sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==} + dev: true + + /socks-proxy-agent@8.0.2: + resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /socks@2.7.1: + resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 2.0.0 + smart-buffer: 4.2.0 + dev: true + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} dev: true + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -3466,6 +3995,13 @@ packages: escape-string-regexp: 2.0.0 dev: true + /streamx@2.15.5: + resolution: {integrity: sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==} + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + dev: true + /string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -3582,11 +4118,38 @@ packages: stable: 0.1.8 dev: true + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.6 + dev: true + + /tar-stream@3.1.6: + resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + dependencies: + b4a: 1.6.4 + fast-fifo: 1.3.2 + streamx: 2.15.5 + dev: true + /temp-dir@3.0.0: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} dev: true + /terser@5.24.0: + resolution: {integrity: sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + /test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} @@ -3596,6 +4159,10 @@ packages: minimatch: 3.1.2 dev: true + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + /time-zone@1.0.0: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} engines: {node: '>=4'} @@ -3613,6 +4180,10 @@ packages: is-number: 7.0.0 dev: true + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + /trim-newlines@4.1.1: resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} engines: {node: '>=12'} @@ -3668,10 +4239,22 @@ packages: dev: true optional: true + /unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + dependencies: + buffer: 5.7.1 + through: 2.3.8 + dev: true + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + /update-browserslist-db@1.0.13(browserslist@4.22.1): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -3683,6 +4266,10 @@ packages: picocolors: 1.0.0 dev: true + /urlpattern-polyfill@9.0.0: + resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} + dev: true + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -3699,11 +4286,22 @@ packages: spdx-expression-parse: 3.0.1 dev: true + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + /well-known-symbols@2.0.0: resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} engines: {node: '>=6'} dev: true + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} dev: true @@ -3781,6 +4379,19 @@ packages: optional: true dev: true + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} dev: true @@ -3856,6 +4467,13 @@ packages: yargs-parser: 21.1.1 dev: true + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/src/index.ts b/src/index.ts index e44802b..d4737c0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -82,7 +82,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { let addedEntries = new Map(); let entryNames = new Map(); - const pluginName = 'html2'; + const pluginName = 'html2'; // TODO: Need a better name /** * Short summary: * Intercepts the loading of the html files and parses it with parse5. @@ -103,7 +103,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { * - we might need to know which output is being used to properly extract the html back from the result? (in case of not being included in a JS file) */ return { - name: pluginName,// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one + name: pluginName, // Track html entrypoints buildStart(options){ diff --git a/test/basic/test.js b/test/basic/test.js index f73efbb..a3ba273 100644 --- a/test/basic/test.js +++ b/test/basic/test.js @@ -2,7 +2,7 @@ import {join, dirname} from "node:path"; import test from "ava"; import { rollup } from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; @@ -25,7 +25,7 @@ test.serial('simple', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('simple',code); t.snapshot(code); }); @@ -38,7 +38,7 @@ test.serial('inline-script', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('inline-script',code); t.snapshot(code); }); diff --git a/test/evaluated-web-bundle/fixtures/assets/assistant.ttf b/test/evaluated-web-bundle/fixtures/assets/assistant.ttf new file mode 100644 index 0000000..1c624f9 Binary files /dev/null and b/test/evaluated-web-bundle/fixtures/assets/assistant.ttf differ diff --git a/test/evaluated-web-bundle/fixtures/assets/logo-sq.svg b/test/evaluated-web-bundle/fixtures/assets/logo-sq.svg new file mode 100644 index 0000000..31f790b --- /dev/null +++ b/test/evaluated-web-bundle/fixtures/assets/logo-sq.svg @@ -0,0 +1,8 @@ + + HTML5 Logo + + + + + + diff --git a/test/evaluated-web-bundle/fixtures/batman.js b/test/evaluated-web-bundle/fixtures/batman.js new file mode 100644 index 0000000..c3685a8 --- /dev/null +++ b/test/evaluated-web-bundle/fixtures/batman.js @@ -0,0 +1 @@ +export const batman = 'bum badum badum baaaaa dum!'; diff --git a/test/evaluated-web-bundle/fixtures/index.hbs b/test/evaluated-web-bundle/fixtures/index.hbs new file mode 100644 index 0000000..9724a18 --- /dev/null +++ b/test/evaluated-web-bundle/fixtures/index.hbs @@ -0,0 +1,18 @@ + + + + + + Test bundle! + + + + + + {{{ head }}} + + +
Here the app should load!
+ + + diff --git a/test/evaluated-web-bundle/fixtures/index.js b/test/evaluated-web-bundle/fixtures/index.js new file mode 100644 index 0000000..4c1172f --- /dev/null +++ b/test/evaluated-web-bundle/fixtures/index.js @@ -0,0 +1,27 @@ +// Dynamically loads libraries and bootstraps the application +(async ()=>{ + // Add a loader here if any + const root = document.getElementById('root') + if(root) root.innerHTML= `
My app has loaded!!
`; + + try { + // Load app + const [ + appModule, + ] = await Promise.all([ + import("./batman.js"), + ]); + + console.log("Bootstrapped, ready to go!"); + + // Wait for DOM to be ready + if(document.readyState === 'loading') { + await new Promise((resolve)=>document.addEventListener('DOMContentLoaded', resolve)); + } + + // Start the app! + root.innerHTML = `
${appModule.batman}
`; + }catch(err){ + console.error(err); + } +})() diff --git a/test/evaluated-web-bundle/snapshots/test.js.md b/test/evaluated-web-bundle/snapshots/test.js.md new file mode 100644 index 0000000..6e02668 --- /dev/null +++ b/test/evaluated-web-bundle/snapshots/test.js.md @@ -0,0 +1,73 @@ +# Snapshot report for `test/evaluated-web-bundle/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## web-bundle + +> Snapshot 1 + + { + console: [ + '[log] Bootstrapped, ready to go!', + ], + errors: [], + html: `␊ + ␊ + ␊ + Test bundle!␊ + ␊ + ␊ + ␊ + ␊ + ␊ + I'm cool!␊ + ␊ + ␊ +
bum badum badum baaaaa dum!
␊ + ␊ + ␊ + ␊ + `, + requestsFailed: [], + responses: [ + '200 http://localhost/index.html', + '200 http://localhost/index.js', + '200 http://localhost/batman.js', + ], + } + +## copied-assets + +> Snapshot 1 + + { + console: [ + '[log] Bootstrapped, ready to go!', + ], + errors: [], + html: `␊ + ␊ + ␊ + Test bundle!␊ + ␊ + ␊ + ␊ + ␊ + ␊ + I'm cool!␊ + ␊ + ␊ +
bum badum badum baaaaa dum!
␊ + ␊ + ␊ + ␊ + `, + requestsFailed: [], + responses: [ + '200 http://localhost/index.html', + '200 http://localhost/index.js', + '200 http://localhost/batman.js', + ], + } diff --git a/test/evaluated-web-bundle/snapshots/test.js.snap b/test/evaluated-web-bundle/snapshots/test.js.snap new file mode 100644 index 0000000..5e6ee19 Binary files /dev/null and b/test/evaluated-web-bundle/snapshots/test.js.snap differ diff --git a/test/evaluated-web-bundle/test.js b/test/evaluated-web-bundle/test.js new file mode 100644 index 0000000..82219a3 --- /dev/null +++ b/test/evaluated-web-bundle/test.js @@ -0,0 +1,58 @@ +import {join, dirname} from "node:path"; + +import test from "ava"; +import { rollup } from "rollup"; +import urlPlugin from "@rollup/plugin-url"; + +import html from "../../src/index.ts"; +import serveTest from "../util/test-server.ts"; + +/** + * @type {OutputOptions} + */ +const output= { + dir: 'output', // Output all files + format: 'es', // iifi and cjs should be added to tests + sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output + chunkFileNames: '[name].js', + entryFileNames: '[name].[extname]', + assetFileNames: '[name].[extname]', +}; + +import {fileURLToPath} from "node:url"; +import handlebars from "handlebars"; +const __dirname = dirname(fileURLToPath(import.meta.url)); +process.chdir(join(__dirname, 'fixtures')); + + +const defaultAssetInclude = [ + '**/*.(png|jpg|jpeg|gif|ico|svg)',// images, svg + '**/*.(woff|woff2|eot|ttf|otf)',// fonts + '**/*.(webm|mp4)',// video +]; + +test.serial('web-bundle', async (t) => { + const bundle = await rollup({ + input: 'index.hbs', + treeshake: 'smallest', + plugins: [ + html({ + transform(src) { + return handlebars.compile(src)({ + head: `I'm cool!` + }); + } + }), + urlPlugin({ + include: defaultAssetInclude, + }), + + serveTest({ + path: 'index.html', + t, + }) + ], + }); + await bundle.generate(output); +}); + diff --git a/test/js-import/snapshots/test.js.md b/test/js-import/snapshots/test.js.md index 50c5968..f63ad4a 100644 --- a/test/js-import/snapshots/test.js.md +++ b/test/js-import/snapshots/test.js.md @@ -37,7 +37,7 @@ Generated by [AVA](https://avajs.dev). sources: [ '../icon.svg', '../index.html', - '../index.js', + '../index.ts', ], sourcesContent: [ 'export default "data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E"', @@ -66,6 +66,6 @@ Generated by [AVA](https://avajs.dev). code: undefined, fileName: 'index-f75fa1e5.js.map', map: undefined, - source: '{"version":3,"file":"index-f75fa1e5.js","sources":["../icon.svg","../index.html","../index.js"],"sourcesContent":["export default \\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E\\"","\\n \\n \\n\\n \\n \\n \\n \\n\\n","import html from \\"./index.html\\"\\n\\nexport function render(){\\n return html;\\n}\\n"],"names":[],"mappings":"AAAA,aAAe;;ACAf,MAAA,IAAA,GAAA,CAAA;AACA,+BAA+B,EAAwD,MAAA,CAAA;AACvF;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,CAAA;;ACNN,SAAS,MAAM,EAAE;AACxB,IAAI,OAAO,IAAI,CAAC;AAChB;;;;"}', + source: '{"version":3,"file":"index-f75fa1e5.js","sources":["../icon.svg","../index.html","../index.ts"],"sourcesContent":["export default \\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E\\"","\\n \\n \\n\\n \\n \\n \\n \\n\\n","import html from \\"./index.html\\"\\n\\nexport function render(){\\n return html;\\n}\\n"],"names":[],"mappings":"AAAA,aAAe;;ACAf,MAAA,IAAA,GAAA,CAAA;AACA,+BAA+B,EAAwD,MAAA,CAAA;AACvF;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,CAAA;;ACNN,SAAS,MAAM,EAAE;AACxB,IAAI,OAAO,IAAI,CAAC;AAChB;;;;"}', }, ] diff --git a/test/js-import/test.js b/test/js-import/test.js index 7d739db..f4a30dd 100644 --- a/test/js-import/test.js +++ b/test/js-import/test.js @@ -3,7 +3,7 @@ import {join, dirname} from "node:path"; import test from "ava"; import { rollup } from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; import handlebars from "handlebars"; @@ -38,7 +38,7 @@ test.serial('js-import', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('js-import',code); t.snapshot(code); }); diff --git a/test/live-reload/test.js b/test/live-reload/test.js index 4842cca..8fe7d29 100644 --- a/test/live-reload/test.js +++ b/test/live-reload/test.js @@ -3,7 +3,7 @@ import {join, dirname} from "node:path"; import test from "ava"; import {rollup} from "rollup"; import liveReload from "rollup-plugin-livereload"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; @@ -29,7 +29,7 @@ test.serial('live-reload', async (t) => { }) ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); await bundle.close();// Make sure live-reload closes itself debugPrintOutput('live-reload',code); t.snapshot(code); diff --git a/test/multi-entry/test.js b/test/multi-entry/test.js index a465f5d..b0397fa 100644 --- a/test/multi-entry/test.js +++ b/test/multi-entry/test.js @@ -2,7 +2,7 @@ import {resolve, join, dirname} from "node:path"; import test from "ava"; import { rollup } from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; @@ -28,7 +28,7 @@ test.serial('multi-entry', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('multi-entry',code); t.snapshot(code); }); diff --git a/test/rewrite-url/test.js b/test/rewrite-url/test.js index 1bea26f..236ecd3 100644 --- a/test/rewrite-url/test.js +++ b/test/rewrite-url/test.js @@ -2,7 +2,7 @@ import {resolve, join, dirname} from "node:path"; import * as path from "node:path"; import test from "ava"; import { rollup } from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; @@ -32,7 +32,7 @@ test.serial('rewrite-url', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('rewrite-url',code); t.snapshot(code); }); diff --git a/test/templating/test.js b/test/templating/test.js index 243b1b7..ebbfa5d 100644 --- a/test/templating/test.js +++ b/test/templating/test.js @@ -3,7 +3,7 @@ import {join, dirname} from "node:path"; import test from "ava"; import { rollup } from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; import handlebars from "handlebars"; @@ -30,7 +30,7 @@ test.serial('handlebars', async (t) => { }) ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('handlebars',code); t.snapshot(code); }); diff --git a/test/url-plugin/test.js b/test/url-plugin/test.js index dbdd35d..cab1edb 100644 --- a/test/url-plugin/test.js +++ b/test/url-plugin/test.js @@ -4,7 +4,7 @@ import test from "ava"; import { rollup } from "rollup"; import urlPlugin from "@rollup/plugin-url"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import html from "../../src/index.ts"; @@ -37,7 +37,7 @@ test.serial('copied-assets', async (t) => { }), ], }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('copied-assets',code); t.snapshot(code); }); @@ -55,7 +55,7 @@ test.serial('inlined-assets', async (t) => { }), ] }); - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('inlined-assets',code); t.snapshot(code); }); diff --git a/test/util/code-output.ts b/test/util/code-output.ts new file mode 100644 index 0000000..2a6b7c6 --- /dev/null +++ b/test/util/code-output.ts @@ -0,0 +1,26 @@ +import type {RollupBuild, OutputOptions, OutputAsset, OutputChunk, SourceMap} from "rollup"; + +export interface TestOutput{ + code: string, + fileName: string, + source: any, + map: any +} + +export const getCode = async (bundle: RollupBuild, outputOptions: OutputOptions): Promise => { + const { output } = await bundle.generate(outputOptions || { format: 'cjs', exports: 'auto' }); + + return output.sort((a,b)=> { + if(a.fileName === b.fileName && (a).source !== (b).source){ return (a).source<(b).source?-1:1} + return a.fileName < b.fileName ? -1 : (a.fileName > b.fileName? 1 : 0); + }).map(chunk=> { + const { code, map } = (chunk); + const { fileName, source } = (chunk); + return { + code, + fileName, + source, + map + }; + }); +}; diff --git a/test/util/index.ts b/test/util/index.ts new file mode 100644 index 0000000..8b95f2a --- /dev/null +++ b/test/util/index.ts @@ -0,0 +1,6 @@ +export * from "./code-output.ts"; +export * from "./print-code-output.ts"; +export * from "./test-server.ts"; + + +export * from './misc.js'; diff --git a/test/util/test.js b/test/util/misc.js similarity index 62% rename from test/util/test.js rename to test/util/misc.js index 1819db7..c721774 100644 --- a/test/util/test.js +++ b/test/util/misc.js @@ -1,59 +1,5 @@ import path from "node:path"; import process from "node:process"; -import chalk from "chalk"; - -/** - * @param {import('rollup').RollupBuild} bundle - * @param {import('rollup').OutputOptions} [outputOptions] - */ -export const getCode = async (bundle, outputOptions, allFiles = false) => { - const { output } = await bundle.generate(outputOptions || { format: 'cjs', exports: 'auto' }); - - if (allFiles) { - return output.sort((a,b)=> { - if(a.fileName === b.fileName && a.source !== b.source){ return a.source b.fileName? 1 : 0); - }).map(({ code, fileName, source, map }) => { - return { - code, - fileName, - source, - map - }; - }); - } - const [{ code }] = output; - return code; -}; - -export const debugPrintOutput = async (header, files) => { - const out = []; - - const headFn = chalk.bgCyan; - const headPadding = header.split('').map(x=>'#').join(''); - out.push(...[ - headFn(`##${headPadding}##`), - headFn(`# ${header} #`), - headFn(`##${headPadding}##`), - ]); - - const fileHeadFn = chalk.blue; - const fileContentFn = chalk.blackBright; - out.push(...(files.map(file=>{ - return [ - fileHeadFn(`${file.fileName}:`), - fileContentFn(`${file.code??file.source}`), - '', - ] - }).flat())); - - out.push(...[ - headFn(`##${headPadding}##`), - ]); - - process.env.DEBUG? console.log(out.join('\n')) : null; -}; - /** * @param {import('rollup').RollupBuild} bundle diff --git a/test/util/print-code-output.ts b/test/util/print-code-output.ts new file mode 100644 index 0000000..aa55319 --- /dev/null +++ b/test/util/print-code-output.ts @@ -0,0 +1,32 @@ +import process from "node:process"; +import chalk from "chalk"; + +import {TestOutput} from "./code-output.ts"; + +export const debugPrintOutput = async (header: string, files: TestOutput[]) => { + const out = []; + + const headFn = chalk.bgCyan; + const headPadding = header.split('').map(x=>'#').join(''); + out.push(...[ + headFn(`##${headPadding}##`), + headFn(`# ${header} #`), + headFn(`##${headPadding}##`), + ]); + + const fileHeadFn = chalk.blue; + const fileContentFn = chalk.blackBright; + out.push(...(files.map(file=>{ + return [ + fileHeadFn(`${file.fileName}:`), + fileContentFn(`${file.code??file.source}`), + '', + ] + }).flat())); + + out.push(...[ + headFn(`##${headPadding}##`), + ]); + + process.env.DEBUG? console.log(out.join('\n')) : null; +}; diff --git a/test/util/test-server.ts b/test/util/test-server.ts new file mode 100644 index 0000000..a620667 --- /dev/null +++ b/test/util/test-server.ts @@ -0,0 +1,384 @@ +/** + * Puppeteer + from-memory devServer rollup plugin to open the result in a webpage en output the result + * (after an optional series of commands to the puppeteer Page) + */ + + +import puppeteer, {Page} from "puppeteer"; +import http from 'http'; +import {resolve, posix} from "node:path"; +import {URL} from "node:url"; + + +import { readFile } from 'fs' +import { createServer as createHttpsServer } from 'https' +import { createServer} from 'http' +import { Mime } from 'mime/lite' +import standardTypes from 'mime/types/standard.js' +import otherTypes from 'mime/types/other.js' + + +import type {NormalizedOutputOptions, OutputAsset, OutputBundle, OutputChunk, Plugin} from 'rollup' + +import type { + IncomingHttpHeaders, OutgoingHttpHeaders, + IncomingMessage, ServerResponse, + Server +} from 'http' +import type { ServerOptions } from 'https' +type TypeMap = { + [key: string]: string[]; +}; + +type ErrorCodeException = Error & {code: string}; + +export interface RollupServeOptions { + /** + * Change the path to be opened when the test is started + * Remember to start with a slash, e.g. `'/different/page'` + */ + path?: string + + cb?: PageTestCallback + t?: any + + /** + * Set to `true` to return index.html (200) instead of error page (404) + * or path to fallback page + */ + historyApiFallback?: boolean | string + + /** + * Change the host of the server (default: `'localhost'`) + */ + host?: string + + /** + * Change the port that the server will listen on (default: `10001`) + */ + port?: number | string + + /** + * By default server will be served over HTTP (https: `false`). It can optionally be served over HTTPS. + */ + https?: ServerOptions | false + + /** + * Set custom response headers + */ + headers?: + | IncomingHttpHeaders + | OutgoingHttpHeaders + | { + // i.e. Parameters + [name: string]: number | string | ReadonlyArray + } + + /** + * Set custom mime types, usage https://github.com/broofa/mime#mimedefinetypemap-force--false + */ + mimeTypes?: TypeMap + + /** + * Execute function after server has begun listening + */ + onListening?: (server: Server) => void +} + +/** + * Serve your rolled up bundle like webpack-dev-server + * @param {import('..').RollupServeOptions} options + */ +export default function serveTest (options: RollupServeOptions ): Plugin { + const mime = new Mime(standardTypes, otherTypes) + const testOptions = { + port: 0, + headers: {}, + historyApiFallback: true, + onListening: function noop (){}, + ...options||{}, + https: options.https??false, + mimeTypes: options.mimeTypes? mime.define(options.mimeTypes, true): false + } + + let server : Server; + let bundle : OutputBundle = {}; + + const requestListener = (request: IncomingMessage, response: ServerResponse) => { + // Remove querystring + const unsafePath = decodeURI(request.url!.split('?')[0]) + + // Don't allow path traversal + const urlPath = posix.normalize(unsafePath) + + for(const [key, value] of Object.entries((testOptions.headers))){ + response.setHeader(key, value!); + } + + function urlToFilePath(url:string){ + return url[0]==='/'?url.slice(1):url; + } + let filePath = urlToFilePath(urlPath); // Todo check if we need to strip '/' + let file: OutputChunk|OutputAsset; + if(!bundle[filePath] && testOptions.historyApiFallback) { + const fallbackPath = typeof testOptions.historyApiFallback === 'string' + ? testOptions.historyApiFallback + : '/index.html'; + if(bundle[urlToFilePath(fallbackPath)]){ + filePath = urlToFilePath(fallbackPath); + } + } + file = bundle[filePath]; + if(!file){ + return notFound(response, filePath); + }else{ + const content = (file).code || (file).source; // Todo might need to read a source file; + return found(response, mime.getType(filePath!), content); + } + // + // if(bundle[urlPath]){ + // const fallbackPath = typeof testOptions.historyApiFallback === 'string' ? testOptions.historyApiFallback : '/index.html' + // } + // + // readFileFromContentBase(contentBase, urlPath, function (error, content, filePath) { + // if (!error) { + // return found(response, mime.getType(filePath!), content) + // } + // if ((error).code !== 'ENOENT') { + // response.writeHead(500) + // response.end('500 Internal Server Error' + + // '\n\n' + filePath + + // '\n\n' + Object.values(error).join('\n') + + // '\n\n(rollup-plugin-serve)', 'utf-8') + // return + // } + // if (testOptions.historyApiFallback) { + // const fallbackPath = typeof testOptions.historyApiFallback === 'string' ? testOptions.historyApiFallback : '/index.html' + // readFileFromContentBase(contentBase, fallbackPath, function (error, content, filePath) { + // if (error) { + // notFound(response, filePath) + // } else { + // found(response, mime.getType(filePath), content) + // } + // }) + // } else { + // notFound(response, filePath) + // } + // }) + } + + + function closeServerOnTermination () { + const terminationSignals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP'] + terminationSignals.forEach(signal => { + process.on(signal, () => { + if (server) { + server.close() + process.exit() + } + }) + }) + } + + + // release previous server instance if rollup is reloading configuration in watch mode + // @ts-ignore + if (server) { + server.close() + } else { + closeServerOnTermination() + } + + // If HTTPS options are available, create an HTTPS server + server = testOptions.https + ? createHttpsServer(testOptions.https, requestListener) + : createServer(requestListener) + server.listen( + typeof(testOptions.port)==='string'? Number.parseInt(testOptions.port):testOptions.port, + testOptions.host, + undefined, + () => testOptions.onListening?.(server) + ) + + testOptions.port = (server.address())?.port ?? testOptions.port; + + // Assemble url for error and info messages + const url = (testOptions.https ? 'https' : 'http') + '://' + (testOptions.host || 'localhost') + ':' + testOptions.port + + // Handle common server errors + server.on('error', e => { + if ((e).code === 'EADDRINUSE') { + console.error(url + ' is in use, either stop the other server or use a different port.') + process.exit() + } else { + throw e + } + }) + + let first = true + + return { + name: 'serve', + generateBundle: { + order: 'post', + async handler(options, output){ + bundle = output; + if (first) { + first = false + + const testOutput = await runTest({ + page: testOptions.path!, + cb: testOptions.cb, + }, url) + testOptions.t?.snapshot?.(testOutput); + } + } + }, + closeBundle (){ + // Done with the bundle + } + } +} + + +function notFound (response: ServerResponse, filePath: string) { + response.writeHead(404) + response.end( + '404 Not Found' + '\n\n' + filePath, + 'utf-8' + ) +} + +function found (response: ServerResponse, mimeType: string|null, content: any) { + response.writeHead(200, { 'Content-Type': mimeType || 'text/plain' }) + response.end(content, 'utf-8') +} + +function green (text: string) { + return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m' +} + + + +export type PageTestCallback = (page: Page)=>Promise; +export interface TestFilterOptions{ + html?: boolean + console?: ('log'|'error'|'warn')[] | true + errors?: boolean, // again don't know possible values + responses?: boolean, // interesting to see what other values were requested + requestsFailed?: boolean, // will probably also be replicated into console errors, but helpful to have if imports werent found +} +export interface TestOptions { + page: string + cb: PageTestCallback + filterOutput: TestFilterOptions + replaceHost: boolean + replaceHostWith?: string +} +const defaultOptions: Partial = { + page: 'index.html', + cb: async (page: Page)=>{ + await page.waitForNetworkIdle({}); + }, + replaceHost: true, + replaceHostWith: `http://localhost`, + filterOutput:{ + html: true, + console: ['log','error','warn'],// TODO: or warning? need to check what possible values are + errors: true, // again don't know possible values + responses: true, // interesting to see what other values were requested + requestsFailed: true, // will probably also be replicated into console errors, but helpful to have if imports werent found + } +} +export interface TestOutput{ + html?: string, + console?: string[], + errors?: string[], + responses?: string[], + requestsFailed?: string[], +} +export async function runTest(opts: Partial, hostUrl: string){ + const options : TestOptions = ({ + ...defaultOptions, + ...opts, + filterOutput: { + ...defaultOptions.filterOutput, + ...(opts?.filterOutput), + }, + }); + const { + page: path, + cb, + replaceHost, + replaceHostWith, + filterOutput + } = options; + + const browser = await puppeteer.launch({ + headless: 'new', + }); + const page = await browser.newPage(); + + let output : TestOutput = { + console: [], + errors: [], + responses: [], + requestsFailed: [] + }; + + try{ + // Track requests, errors and console + page.on('console', message => { + let [type, text] = [message.type(), message.text()]; + if(replaceHost){ + text = text.replaceAll(hostUrl, replaceHostWith!); + } + if((filterOutput.console)?.includes?.(type) ?? (filterOutput.console === true)){// TODO: add callback option + output.console?.push(`[${type}] ${text}`); + } + }).on('pageerror', ({ message }) => { + let text = message; + if(replaceHost){ + text = text.replaceAll(hostUrl, replaceHostWith!); + } + if(filterOutput.errors === true) {// TODO add callback option + output.errors?.push(text) + } + }).on('response', response => { + let [status, url] = [response.status(), response.url()] + if(replaceHost){ + url = url.replaceAll(hostUrl, replaceHostWith!); + } + if(filterOutput.responses === true) {// TODO add callback option + output.responses?.push(`${status} ${url}`) + } + }).on('requestfailed', request => { + let [failure, url] = [request.failure()?.errorText, request.url()]; + if(replaceHost){ + failure = failure?.replaceAll(hostUrl, replaceHostWith!); + url = url.replaceAll(hostUrl, replaceHostWith!); + } + if(filterOutput.requestsFailed === true) {// TODO add callback option + output.requestsFailed?.push(`${failure} ${url}`) + } + }); + + const url = new URL(`${hostUrl}/${path??''}`); + await page.goto(url.href); + + if(!cb) { + await page.waitForNetworkIdle({}); + }else{ + await cb(page); + } + const htmlHandle = await page.$('html'); + const html = await page.evaluate(html => html?.outerHTML??html?.innerHTML, htmlHandle); + + // Add the final html + output.html = html; + }finally{ + await page.close(); + await browser.close(); + } + return output; +} diff --git a/test/util/test.d.ts b/test/util/test.d.ts deleted file mode 100644 index e2ac0bc..0000000 --- a/test/util/test.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import type { RollupBuild, OutputOptions, OutputChunk, OutputAsset } from 'rollup'; -import type { Assertions } from 'ava'; - -interface GetCode { - (bundle: RollupBuild, outputOptions?: OutputOptions | null, allFiles?: false): Promise; - (bundle: RollupBuild, outputOptions: OutputOptions | null | undefined, allFiles: true): Promise< - Array<{ - code: OutputChunk['code'] | undefined; - fileName: OutputChunk['fileName'] | OutputAsset['fileName']; - source: OutputAsset['source'] | undefined; - }> - >; -} - -export const getCode: GetCode; - -export function getFiles( - bundle: RollupBuild, - outputOptions?: OutputOptions -): Promise< - { - fileName: string; - content: any; - }[] ->; - -export function evaluateBundle(bundle: RollupBuild): Promise>; - -export function getImports(bundle: RollupBuild): Promise; - -export function getResolvedModules(bundle: RollupBuild): Promise>; - -export function onwarn(warning: string | any): void; - -export function testBundle( - t: Assertions, - bundle: RollupBuild, - options: { inject: Record; options: Record } -): Promise<{ - code: string; - error?: any; - result?: any; - module: Pick; -}>; diff --git a/test/watch/test.js b/test/watch/test.js index 224d3e4..a1f81e2 100644 --- a/test/watch/test.js +++ b/test/watch/test.js @@ -2,7 +2,7 @@ import {join, dirname} from "node:path"; import test from "ava"; import * as rollup from "rollup"; -import {debugPrintOutput, getCode} from "../util/test.js"; +import {debugPrintOutput, getCode} from "../util/index.ts"; import {resolve} from "node:path"; import {writeFile} from "node:fs/promises"; @@ -49,7 +49,7 @@ test.serial('watch', async (t) => { // Just wait on the watch mode to pick up on the changes }, async (bundle)=>{ - const code = await getCode(bundle, output, true); + const code = await getCode(bundle, output); debugPrintOutput('watch',code); // Reset the source file diff --git a/tsconfig.json b/tsconfig.json index db4fb87..8af2d8b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,8 @@ "target": "ESNext", "module": "ESNext", "moduleResolution": "NodeNext", - "allowJs": true + "allowJs": true, + "allowImportingTsExtensions": true }, "exclude": ["dist", "node_modules", "test/types"], "include": ["src/**/*", "types/**/*"],