diff --git a/nuxt.config.ts b/nuxt.config.ts index 6923ed1d..8a925a66 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -77,10 +77,18 @@ export default defineNuxtConfig({ domain: 'roe.dev', }, + critters: { + config: { + inlineFonts: true, + pruneSource: true, + }, + }, + modules: [ '@nuxtjs/tailwindcss', '@nuxtjs/color-mode', '@nuxt/content', 'vue-plausible', + '~/modules/critters', ], }) diff --git a/package.json b/package.json index 52f7272c..b15790e1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "dependencies": { "@nuxt/content": "npm:@nuxt/content-edge@2.1.0-27620140.d41205a", "@nuxt/kit": "npm:@nuxt/kit-edge@3.0.0-rc.4-27620285.c95a48c", + "critters": "^0.0.16", "prism-themes": "1.9.0", "vue-plausible": "^1.3.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1a2acad..5e52ecef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,7 @@ importers: '@vitejs/plugin-vue': ^2.0.0 '@vue/test-utils': ^2.0.0 c8: ^7.11.3 + critters: ^0.0.16 eslint: 8.19.0 eslint-config-prettier: 8.5.0 eslint-plugin-nuxt: 3.2.0 @@ -42,6 +43,7 @@ importers: dependencies: '@nuxt/content': /@nuxt/content-edge/2.1.0-27620140.d41205a '@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27620285.c95a48c + critters: 0.0.16 prism-themes: 1.9.0 vue-plausible: 1.3.1_wlppdykgj6nuhdp7os4wmc3wre devDependencies: @@ -1868,7 +1870,6 @@ packages: engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true /ansi-styles/6.1.0: resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==} @@ -2072,7 +2073,6 @@ packages: /boolbase/1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -2253,7 +2253,6 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true /chalk/5.0.1: resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} @@ -2420,14 +2419,12 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - dev: true /color-name/1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} /color-name/1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true /color-support/1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} @@ -2622,6 +2619,17 @@ packages: /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /critters/0.0.16: + resolution: {integrity: sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==} + dependencies: + chalk: 4.1.2 + css-select: 4.3.0 + parse5: 6.0.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + postcss: 8.4.14 + pretty-bytes: 5.6.0 + dev: false + /cross-fetch/3.1.5: resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} dependencies: @@ -2678,7 +2686,6 @@ packages: domhandler: 4.3.1 domutils: 2.8.0 nth-check: 2.1.1 - dev: true /css-tree/1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} @@ -2691,7 +2698,6 @@ packages: /css-what/6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - dev: true /css.escape/1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} @@ -3019,7 +3025,6 @@ packages: domelementtype: 2.3.0 domhandler: 4.3.1 entities: 2.2.0 - dev: true /dom-serializer/2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -3031,14 +3036,12 @@ packages: /domelementtype/2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true /domhandler/4.3.1: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} dependencies: domelementtype: 2.3.0 - dev: true /domhandler/5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} @@ -3053,7 +3056,6 @@ packages: dom-serializer: 1.4.1 domelementtype: 2.3.0 domhandler: 4.3.1 - dev: true /domutils/3.0.1: resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} @@ -3141,7 +3143,6 @@ packages: /entities/2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - dev: true /entities/4.3.1: resolution: {integrity: sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==} @@ -4462,7 +4463,6 @@ packages: /has-flag/4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors/1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} @@ -6187,7 +6187,6 @@ packages: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /natural-compare/1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -6385,7 +6384,6 @@ packages: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: boolbase: 1.0.0 - dev: true /nuxi-edge/3.0.0-rc.4-27620285.c95a48c: resolution: {integrity: sha512-wo44rYKKSWg09ExVA7iqLLbNTBlgkvn72JojH6O4iKEcxjGnr/mnLYsfzABmyBIHbtwt8vOF2ekdITYAd80wRw==} @@ -6704,6 +6702,12 @@ packages: protocols: 1.4.8 dev: true + /parse5-htmlparser2-tree-adapter/6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: false + /parse5/6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: false @@ -7309,7 +7313,6 @@ packages: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /prelude-ls/1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -7329,6 +7332,11 @@ packages: hasBin: true dev: true + /pretty-bytes/5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: false + /pretty-bytes/6.0.0: resolution: {integrity: sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==} engines: {node: ^14.13.1 || >=16.0.0} @@ -8003,7 +8011,6 @@ packages: /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==} @@ -8338,7 +8345,6 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-color/8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} diff --git a/src/modules/critters.ts b/src/modules/critters.ts new file mode 100644 index 00000000..dc53ccac --- /dev/null +++ b/src/modules/critters.ts @@ -0,0 +1,35 @@ +import { defineNuxtModule } from '@nuxt/kit' +import Critters, { Options } from 'critters' + +export interface ModuleOptions { + config?: Options +} + +export default defineNuxtModule({ + meta: { + name: 'critters', + configKey: 'critters', + }, + defaults: { + // Options passed directly to `critters` + config: { + preload: 'media', + }, + }, + setup(options, nuxt) { + // Only enable for production + if (nuxt.options.dev) return + + nuxt.hook('nitro:init', nitro => { + const critters = new Critters({ + path: nitro.options.output.publicDir, + publicPath: nuxt.options.app.baseURL, + ...options.config, + }) + nitro.hooks.hook('prerender:generate', async route => { + if (!route.contents || !route.fileName.endsWith('.html')) return + route.contents = await critters.process(route.contents) + }) + }) + }, +})