diff --git a/greenwood.config.js b/greenwood.config.js index 39e8acdc..e1a4eea3 100644 --- a/greenwood.config.js +++ b/greenwood.config.js @@ -1,9 +1,10 @@ import { greenwoodPluginImportRaw } from "@greenwood/plugin-import-raw"; import { greenwoodPluginCssModules } from "./plugin-css-modules.js"; +// import { greenwoodPluginPostCss } from "@greenwood/plugin-postcss"; export default { prerender: true, - plugins: [greenwoodPluginImportRaw(), greenwoodPluginCssModules()], + plugins: [greenwoodPluginCssModules(), greenwoodPluginImportRaw()], markdown: { plugins: ["@mapbox/rehype-prism"], }, diff --git a/package-lock.json b/package-lock.json index 5ce6f15e..df47b1b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@esm-bundle/chai": "^4.3.4-fix.0", "@greenwood/cli": "^0.30.0-alpha.4", "@greenwood/plugin-import-raw": "^0.30.0-alpha.4", + "@greenwood/plugin-postcss": "^0.30.0-alpha.4", "@ls-lint/ls-lint": "^1.10.0", "@mapbox/rehype-prism": "^0.9.0", "@storybook/addon-essentials": "^8.0.6", @@ -38,6 +39,7 @@ "lint-staged": "^15.2.2", "lit": "^3.1.2", "patch-package": "^8.0.0", + "postcss-import": "^16.1.0", "prettier": "^3.2.5", "rimraf": "^5.0.5", "storybook": "^8.0.6", @@ -2015,6 +2017,302 @@ "@csstools/css-tokenizer": "^2.2.4" } }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-cascade-layers/node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, "node_modules/@csstools/selector-specificity": { "version": "3.0.3", "dev": true, @@ -2225,6 +2523,37 @@ "@greenwood/cli": "^0.4.0" } }, + "node_modules/@greenwood/plugin-postcss": { + "version": "0.30.0-alpha.4", + "resolved": "https://registry.npmjs.org/@greenwood/plugin-postcss/-/plugin-postcss-0.30.0-alpha.4.tgz", + "integrity": "sha512-zXxSx2I1IOYT/PqtT5Si5actidRCgI4gfEWMYwzLHsMwziq4MqMtROvuVptuirC4TyvpqAQtg80Vi/k4oAb5Dw==", + "dev": true, + "dependencies": { + "postcss": "^8.3.11", + "postcss-import": "^13.0.0", + "postcss-preset-env": "^7.0.1" + }, + "peerDependencies": { + "@greenwood/cli": "^0.4.0" + } + }, + "node_modules/@greenwood/plugin-postcss/node_modules/postcss-import": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-13.0.0.tgz", + "integrity": "sha512-LPUbm3ytpYopwQQjqgUH4S3EM/Gb9QsaSPP/5vnoi+oKVy3/mIk2sc0Paqw7RL57GpScm9MdIMUypw2znWiBpg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "dev": true, @@ -2909,9 +3238,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", - "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], @@ -5628,6 +5957,43 @@ "gulp-header": "^1.7.1" } }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "dev": true, @@ -6995,6 +7361,24 @@ "node": ">=8" } }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/css-functions-list": { "version": "3.2.2", "dev": true, @@ -7003,25 +7387,74 @@ "node": ">=12 || >=16" } }, - "node_modules/css-tree": { - "version": "2.3.1", + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", "dev": true, - "license": "MIT", "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/css.escape": { - "version": "1.5.1", + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", "dev": true, - "license": "MIT" - }, - "node_modules/cssesc": { - "version": "3.0.0", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cssdb": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", + "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] + }, + "node_modules/cssesc": { + "version": "3.0.0", "dev": true, "license": "MIT", "bin": { @@ -8493,6 +8926,19 @@ "node": ">= 0.6" } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fresh": { "version": "0.5.2", "dev": true, @@ -11778,6 +12224,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "dev": true, @@ -12709,6 +13164,552 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", + "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "dev": true, + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "dev": true, + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.3" + } + }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.1", "dev": true, @@ -12739,6 +13740,25 @@ "postcss": "^8.4.31" } }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.16", "dev": true, @@ -13182,6 +14202,24 @@ "dev": true, "license": "MIT" }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "dev": true, diff --git a/package.json b/package.json index 84fa25e4..0917b3b0 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@esm-bundle/chai": "^4.3.4-fix.0", "@greenwood/cli": "^0.30.0-alpha.4", "@greenwood/plugin-import-raw": "^0.30.0-alpha.4", + "@greenwood/plugin-postcss": "^0.30.0-alpha.4", "@ls-lint/ls-lint": "^1.10.0", "@mapbox/rehype-prism": "^0.9.0", "@storybook/addon-essentials": "^8.0.6", @@ -62,6 +63,7 @@ "lint-staged": "^15.2.2", "lit": "^3.1.2", "patch-package": "^8.0.0", + "postcss-import": "^16.1.0", "prettier": "^3.2.5", "rimraf": "^5.0.5", "storybook": "^8.0.6", diff --git a/patches/@greenwood+cli+0.30.0-alpha.4.patch b/patches/@greenwood+cli+0.30.0-alpha.4.patch new file mode 100644 index 00000000..ff330157 --- /dev/null +++ b/patches/@greenwood+cli+0.30.0-alpha.4.patch @@ -0,0 +1,358 @@ +diff --git a/node_modules/@greenwood/cli/src/config/rollup.config.js b/node_modules/@greenwood/cli/src/config/rollup.config.js +index 7771d11..5d48e0c 100644 +--- a/node_modules/@greenwood/cli/src/config/rollup.config.js ++++ b/node_modules/@greenwood/cli/src/config/rollup.config.js +@@ -12,7 +12,9 @@ function cleanRollupId(id) { + return id.replace('\x00', '').replace('?commonjs-proxy', ''); + } + +-function greenwoodResourceLoader (compilation) { ++function greenwoodResourceLoader (compilation, browser = false) { ++ // ConstructableStylesheets, JSON Modules ++ const externalizedResources = ['css', 'json']; + const resourcePlugins = compilation.config.plugins.filter((plugin) => { + return plugin.type === 'resource'; + }).map((plugin) => { +@@ -21,16 +23,29 @@ function greenwoodResourceLoader (compilation) { + + return { + name: 'greenwood-resource-loader', +- async resolveId(id) { +- const normalizedId = cleanRollupId(id); // idUrl.pathname; +- const { projectDirectory, userWorkspace } = compilation.context; +- +- if (normalizedId.startsWith('.') && !normalizedId.startsWith(projectDirectory.pathname)) { ++ async resolveId(id, importer) { ++ const normalizedId = cleanRollupId(id); ++ const { userWorkspace } = compilation.context; ++ ++ // check for non bare paths and resolve them to the user's workspace ++ // or Greenwood's scratch dir, like when bundling inline `) ++ ...customImports.filter(resource => resource.split(' ')[0].split('.').pop() === 'js') ++ .map((resource) => { ++ const [src, ...attributes] = resource.split(' '); ++ const attrs = attributes?.length > 0 ++ ? attributes.join(' ') ++ : ''; ++ ++ return ``; ++ }) + ].join('\n'); + + const finalBody = pageLayoutContents +diff --git a/node_modules/@greenwood/cli/src/lifecycles/bundle.js b/node_modules/@greenwood/cli/src/lifecycles/bundle.js +index 21636a9..f3b814b 100644 +--- a/node_modules/@greenwood/cli/src/lifecycles/bundle.js ++++ b/node_modules/@greenwood/cli/src/lifecycles/bundle.js +@@ -353,10 +353,12 @@ const bundleCompilation = async (compilation) => { + + console.info('bundling static assets...'); + ++ // need styles bundled first for usage with import attributes syncing in Rollup ++ await bundleStyleResources(compilation, optimizeResourcePlugins); ++ + await Promise.all([ + await bundleApiRoutes(compilation), +- await bundleScriptResources(compilation), +- await bundleStyleResources(compilation, optimizeResourcePlugins) ++ await bundleScriptResources(compilation) + ]); + + // bundleSsrPages depends on bundleScriptResources having run first +diff --git a/node_modules/@greenwood/cli/src/loader.js b/node_modules/@greenwood/cli/src/loader.js +index 657ab4e..792f43c 100644 +--- a/node_modules/@greenwood/cli/src/loader.js ++++ b/node_modules/@greenwood/cli/src/loader.js +@@ -7,6 +7,7 @@ const resourcePlugins = config.plugins + .filter(plugin => plugin.name !== 'plugin-node-modules:resource' && plugin.name !== 'plugin-user-workspace') + .map(plugin => plugin.provider({ + context: { ++ outputDir: new URL(`file://${process.cwd()}/public`), + projectDirectory: new URL(`file://${process.cwd()}/`), + scratchDir: new URL(`file://${process.cwd()}/.greenwood/`) + }, +diff --git a/node_modules/@greenwood/cli/src/plugins/resource/plugin-standard-css.js b/node_modules/@greenwood/cli/src/plugins/resource/plugin-standard-css.js +index b0cdbcb..d8409ea 100644 +--- a/node_modules/@greenwood/cli/src/plugins/resource/plugin-standard-css.js ++++ b/node_modules/@greenwood/cli/src/plugins/resource/plugin-standard-css.js +@@ -49,23 +49,26 @@ function bundleCss(body, url, compilation) { + barePath = barePath.replace('/', ''); + } + +- const locationUrl = barePath.startsWith('node_modules') ++ const locationUrl = barePath.indexOf('node_modules/') >= 0 + ? new URL(`./${barePath}`, projectDirectory) + : new URL(`./${barePath}`, userWorkspace); + + if (fs.existsSync(locationUrl)) { ++ const isDev = process.env.__GWD_COMMAND__ === 'develop'; // eslint-disable-line no-underscore-dangle + const hash = hashString(fs.readFileSync(locationUrl, 'utf-8')); + const ext = barePath.split('.').pop(); +- const hashedRoot = barePath.replace(`.${ext}`, `.${hash}.${ext}`); ++ const hashedRoot = isDev ? barePath : barePath.replace(`.${ext}`, `.${hash}.${ext}`); + +- fs.mkdirSync(new URL(`./${path.dirname(barePath)}/`, outputDir), { +- recursive: true +- }); ++ if (!isDev) { ++ fs.mkdirSync(new URL(`./${path.dirname(hashedRoot)}/`, outputDir), { ++ recursive: true ++ }); + +- fs.promises.copyFile( +- locationUrl, +- new URL(`./${hashedRoot}`, outputDir) +- ); ++ fs.promises.copyFile( ++ locationUrl, ++ new URL(`./${hashedRoot}`, outputDir) ++ ); ++ } + + optimizedCss += `url('${basePath}${hashedRoot}')`; + } else { +@@ -303,39 +306,25 @@ class StandardCssResource extends ResourceInterface { + }); + } + +- async shouldIntercept(url, request) { +- const { pathname, searchParams } = url; ++ async shouldIntercept(url) { ++ const { pathname } = url; + const ext = pathname.split('.').pop(); + +- return url.protocol === 'file:' && ext === this.extensions[0] && request.headers.get('Accept')?.indexOf('text/javascript') >= 0 && !searchParams.has('type'); ++ return url.protocol === 'file:' && ext === this.extensions[0]; + } + + async intercept(url, request, response) { +- const contents = (await response.text()).replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\'); +- const body = `const sheet = new CSSStyleSheet();sheet.replaceSync(\`${contents}\`);export default sheet;`; +- +- return new Response(body, { +- headers: { +- 'Content-Type': 'text/javascript' +- } +- }); +- } ++ let body = bundleCss(await response.text(), url, this.compilation); ++ let headers = {}; + +- async shouldOptimize(url, response) { +- const { protocol, pathname, searchParams } = url; +- const isValidCss = pathname.split('.').pop() === this.extensions[0] +- && protocol === 'file:' +- && response.headers.get('Content-Type').indexOf(this.contentType) >= 0 +- && searchParams.get('type') !== 'css'; ++ if (request.headers.get('Accept')?.indexOf('text/javascript') >= 0 && !url.searchParams.has('type')) { ++ const contents = body.replace(/\r?\n|\r/g, ' ').replace(/\\/g, '\\\\'); + +- return this.compilation.config.optimization !== 'none' && isValidCss; +- } +- +- async optimize(url, response) { +- const body = await response.text(); +- const optimizedBody = bundleCss(body, url, this.compilation); ++ body = `const sheet = new CSSStyleSheet();sheet.replaceSync(\`${contents}\`);export default sheet;`; ++ headers['Content-Type'] = 'text/javascript'; ++ } + +- return new Response(optimizedBody); ++ return new Response(body, { headers }); + } + } + diff --git a/patches/wc-compiler+0.14.0.patch b/patches/wc-compiler+0.14.0.patch index c3e43a7c..b8ff5220 100644 --- a/patches/wc-compiler+0.14.0.patch +++ b/patches/wc-compiler+0.14.0.patch @@ -1,8 +1,18 @@ diff --git a/node_modules/wc-compiler/src/dom-shim.js b/node_modules/wc-compiler/src/dom-shim.js -index be289a3..dd4692a 100644 +index be289a3..2c97d0e 100644 --- a/node_modules/wc-compiler/src/dom-shim.js +++ b/node_modules/wc-compiler/src/dom-shim.js -@@ -102,6 +102,9 @@ class ShadowRoot extends DocumentFragment { +@@ -83,6 +83,9 @@ class Document extends Node { + createDocumentFragment(html) { + return new DocumentFragment(html); + } ++ ++ querySelector() { } ++ querySelectorAll() { } + } + + // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement +@@ -102,6 +105,9 @@ class ShadowRoot extends DocumentFragment { super(); this.mode = options.mode || 'closed'; this.adoptedStyleSheets = []; diff --git a/plugin-css-modules.js b/plugin-css-modules.js index 46080983..4d89785d 100644 --- a/plugin-css-modules.js +++ b/plugin-css-modules.js @@ -159,78 +159,104 @@ class CssModulesResource extends ResourceInterface { return new Request(matchedUrl); } - async shouldServe(url) { + // async shouldIntercept(url) { + // console.log('css modules intercept', { url }); + // const { pathname, protocol } = url; + // const mapKey = `${protocol}//${pathname}`; + // // // console.log(this.compilation.context.scratchDir) + // // // console.log(new URL('./__css-modules-map.json', this.compilation.context.scratchDir)); + // const cssModulesMap = getCssModulesMap(this.compilation); + // // console.log("shouldServer", { cssModulesMap, url }); + // return protocol === "file:" && pathname.endsWith(this.extensions[0]) && cssModulesMap[mapKey]; + // } + + // async intercept(url) { + // console.log('css modules intercept', { url }); + // const { pathname, protocol } = url; + // const mapKey = `${protocol}//${pathname}`; + // const cssModulesMap = getCssModulesMap(this.compilation); + // // console.log("@@@@@@", { url, cssModulesMap }); + // const cssModule = `export default ${JSON.stringify(cssModulesMap[mapKey].module)}`; + + // // console.log("@@@@@@", { cssModule }); + // return new Response(cssModule, { + // headers: { + // "Content-Type": this.contentType, + // }, + // }); + // } + + // this happens "first" as the HTML is returned, to find viable references to CSS Modules + // better way than just checking for /? + async shouldIntercept(url) { const { pathname, protocol } = url; const mapKey = `${protocol}//${pathname}`; - // // console.log(this.compilation.context.scratchDir) - // // console.log(new URL('./__css-modules-map.json', this.compilation.context.scratchDir)); const cssModulesMap = getCssModulesMap(this.compilation); - // console.log("shouldServer", { cssModulesMap, url }); - return protocol === "file:" && pathname.endsWith(this.extensions[0]) && cssModulesMap[mapKey]; + + return ( + url.pathname.endsWith("/") || + (protocol === "file:" && pathname.endsWith(this.extensions[0]) && cssModulesMap[mapKey]) + ); } - async serve(url) { + async intercept(url, request, response) { const { pathname, protocol } = url; const mapKey = `${protocol}//${pathname}`; const cssModulesMap = getCssModulesMap(this.compilation); - // console.log("@@@@@@", { url, cssModulesMap }); - const cssModule = `export default ${JSON.stringify(cssModulesMap[mapKey].module)}`; - - // console.log("@@@@@@", { cssModule }); - return new Response(cssModule, { - headers: { - "Content-Type": this.contentType, - }, - }); - } - - // this happens "first" as the HTML is returned, to find viable references to CSS Modules - // better way than just checking for /? - async shouldIntercept(url) { - return url.pathname.endsWith("/"); - } - async intercept(url, request, response) { - const body = await response.text(); - const dom = htmlparser.parse(body, { script: true }); - const scripts = dom.querySelectorAll("head script"); - const sheets = []; // TODO use a map here? - - for (const script of scripts) { - const type = script.getAttribute("type"); - const src = script.getAttribute("src"); - if (src && ["module", "module-shim"].includes(type)) { - // console.log("check this file for CSS Modules", src); - // await resolveForRelativeUrl(new URL(src, import.meta.url this.compilation.context.userWorkspace) - const scriptUrl = new URL( - `./${src.replace(/\.\.\//g, "").replace(/\.\//g, "")}`, - this.compilation.context.userWorkspace, - ); - walkAllImportsForCssModules(scriptUrl, sheets, this.compilation); + if (url.pathname.endsWith("/")) { + const body = await response.text(); + const dom = htmlparser.parse(body, { script: true }); + const scripts = dom.querySelectorAll("head script"); + const sheets = []; // TODO use a map here? + + for (const script of scripts) { + const type = script.getAttribute("type"); + const src = script.getAttribute("src"); + if (src && ["module", "module-shim"].includes(type)) { + // console.log("check this file for CSS Modules", src); + // await resolveForRelativeUrl(new URL(src, import.meta.url this.compilation.context.userWorkspace) + const scriptUrl = new URL( + `./${src.replace(/\.\.\//g, "").replace(/\.\//g, "")}`, + this.compilation.context.userWorkspace, + ); + walkAllImportsForCssModules(scriptUrl, sheets, this.compilation); + } } - } - const cssModulesMap = getCssModulesMap(this.compilation); - // console.log({ cssModulesMap }); - - // for(const cssModule of cssModulesMap) { - // // console.log({ cssModule }); - // } - Object.keys(cssModulesMap).forEach((key) => { - sheets.push(cssModulesMap[key].contents); - }); - - const newBody = body.replace( - "", - ` - - - `, - ); + const cssModulesMap = getCssModulesMap(this.compilation); + // console.log({ cssModulesMap }); + + // for(const cssModule of cssModulesMap) { + // // console.log({ cssModule }); + // } + Object.keys(cssModulesMap).forEach((key) => { + sheets.push(cssModulesMap[key].contents); + }); + + const newBody = body.replace( + "", + ` + + + `, + ); - return new Response(newBody); + return new Response(newBody); + } else if ( + url.pathname.endsWith("/") || + (protocol === "file:" && pathname.endsWith(this.extensions[0]) && cssModulesMap[mapKey]) + ) { + const cssModule = `export default ${JSON.stringify(cssModulesMap[mapKey].module)}`; + + return new Response(cssModule, { + headers: { + "Content-Type": this.contentType, + }, + }); + } } async shouldOptimize(url, response) { diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 00000000..0df4fd4a --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + plugins: [require("postcss-import")], +}; diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 00000000..38ef7be9 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,5 @@ +// would like to get rid of this need, ideally +// https://github.com/ProjectEvergreen/greenwood/discussions/1238 +export default { + plugins: [(await import("postcss-import")).default], +}; diff --git a/src/assets/github.svg b/src/assets/github.svg index a69fbfcb..dc42fbd5 100644 --- a/src/assets/github.svg +++ b/src/assets/github.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/htmx.svg b/src/assets/htmx.svg new file mode 100644 index 00000000..4f5f653b --- /dev/null +++ b/src/assets/htmx.svg @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/modern-web.svg b/src/assets/modern-web.svg new file mode 100644 index 00000000..64e0b6a9 --- /dev/null +++ b/src/assets/modern-web.svg @@ -0,0 +1,104 @@ + + Tilted sphere with longitudinal stripes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/build-with-friends/build-with-friends.js b/src/components/build-with-friends/build-with-friends.js new file mode 100644 index 00000000..dd21aaf0 --- /dev/null +++ b/src/components/build-with-friends/build-with-friends.js @@ -0,0 +1,47 @@ +import styles from "./build-with-friends.module.css"; +import htmxIcon from "../../assets/htmx.svg?type=raw"; +import litIcon from "../../assets/lit.svg?type=raw"; +import storybookIcon from "../../assets/storybook.svg?type=raw"; +import tailwindIcon from "../../assets/tailwind-logo.svg?type=raw"; +import typescriptIcon from "../../assets/typescript.svg?type=raw"; +import wccIcon from "../../assets/wcc.svg?type=raw"; +import wtrIcon from "../../assets/modern-web.svg?type=raw"; + +export default class BuildWithFriends extends HTMLElement { + connectedCallback() { + this.innerHTML = ` +
+

Build With Friends

+ +

Greenwood and Web Components work great with all of your favorite tools in the web ecosystem.

+ + + + ${litIcon} + + + ${storybookIcon} + + + ${tailwindIcon} + + + ${typescriptIcon} + + + ${htmxIcon} + + + ${wtrIcon} + Web Test Runner + + + ${wccIcon} + +
+ + `; + } +} + +customElements.define("app-build-with-friends", BuildWithFriends); diff --git a/src/components/build-with-friends/build-with-friends.module.css b/src/components/build-with-friends/build-with-friends.module.css new file mode 100644 index 00000000..9e2bac57 --- /dev/null +++ b/src/components/build-with-friends/build-with-friends.module.css @@ -0,0 +1,52 @@ +.container { + background-color: var(--color-gray); + border: var(--border-size-1) solid var(--color-black); + border-radius: var(--radius-5); + padding: var(--size-px-5) var(--size-px-5); + margin: 20px auto; +} + +.heading { + font-size: var(--font-size-5); + font-weight: var(--font-weight-9); +} + +.icons { + display: block; +} + +.icon { + display: block; + text-align: center; + background-color: var(--color-white); + border-radius: var(--radius-5); + padding: var(--size-fluid-1) var(--size-fluid-2); + margin: var(--size-fluid-1) var(--size-fluid-1) var(--size-fluid-1) 0; + line-height: 100%; +} + +.icon svg { + height: 50px; +} + +.icon span { + vertical-align: middle; + font-weight: var(--font-weight-9); +} + +@media (min-width: 600px) { + .icon { + display: inline-block; + vertical-align: middle; + } +} + +@media (min-width: 1440px) { + .icons { + max-width: 80%; + } + + .container { + padding: var(--size-px-10) var(--size-px-11); + } +} diff --git a/src/components/build-with-friends/build-with-friends.stories.js b/src/components/build-with-friends/build-with-friends.stories.js new file mode 100644 index 00000000..741390ee --- /dev/null +++ b/src/components/build-with-friends/build-with-friends.stories.js @@ -0,0 +1,9 @@ +import "./build-with-friends.js"; + +export default { + title: "Components/Build With Friends", +}; + +const Template = () => ""; + +export const Primary = Template.bind({}); diff --git a/src/components/footer/footer.js b/src/components/footer/footer.js index 5f39bc30..7f808f5e 100644 --- a/src/components/footer/footer.js +++ b/src/components/footer/footer.js @@ -1,7 +1,7 @@ import discordIcon from "../../assets/discord.svg?type=raw"; import githubIcon from "../../assets/github.svg?type=raw"; import twitterIcon from "../../assets/twitter-logo.svg?type=raw"; -import styles from "./footer.module.css"; +import styles from "./footer.module.css" with { type: "css" }; import greenwoodLogo from "../../assets/greenwood-logo-full.svg?type=raw"; export default class Footer extends HTMLElement { diff --git a/src/components/get-started/get-started.js b/src/components/get-started/get-started.js new file mode 100644 index 00000000..e6a19ac9 --- /dev/null +++ b/src/components/get-started/get-started.js @@ -0,0 +1,28 @@ +import styles from "./get-started.module.css"; + +export default class GetStarted extends HTMLElement { + connectedCallback() { + this.innerHTML = ` +
+

Get started in seconds 🚀

+ +
+
$ npx @greenwood/init@latest
+
+ +
+ + + +
+ +
+ `; + } +} + +customElements.define("app-get-started", GetStarted); diff --git a/src/components/get-started/get-started.module.css b/src/components/get-started/get-started.module.css new file mode 100644 index 00000000..74d72bb5 --- /dev/null +++ b/src/components/get-started/get-started.module.css @@ -0,0 +1,68 @@ +.container { + padding: 20px 0 160px; + border-radius: var(--radius-5); + color: var(--color-white); + background-color: var(--color-tertiary); + text-align: center; +} + +.heading { + font-size: var(--font-size-5); + font-weight: var(--font-weight-9); +} + +.snippet { + display: inline-block; + border-radius: var(--radius-4); + padding: 0 var(--size-4); + box-shadow: var(--shadow-4); + letter-spacing: var(--font-letterspacing-3); + background-color: var(--color-white); + color: var(--color-black); + margin: 10px 0; +} + +.snippet pre { + font-size: 16px; + text-align: center; + display: inline-block; +} + +.buttonBlitz { + display: inline-block; + cursor: pointer; + border-radius: var(--radius-3); + border: var(--border-size-1) solid var(--color-white); + background-color: transparent; + padding: var(--size-fluid-1) var(--size-fluid-2); + min-width: var(--size-px-13); + color: var(--color-black); + box-shadow: var(--shadow-2); +} + +.buttonStarted { + display: inline-block; + cursor: pointer; + border-radius: var(--radius-3); + padding: var(--size-fluid-1) var(--size-fluid-2); + background-color: var(--color-primary); + min-width: var(--size-px-13); + color: var(--color-white); + box-shadow: var(--shadow-4); + margin-top: var(--size-fluid-1); +} + +.linkStarted { + color: var(--color-white); + text-decoration: none; +} + +@media (min-width: 1024px) { + .container { + padding: var(--size-px-10) 0 var(--size-px-13) 0; + } + + .snippet { + max-width: 50%; + } +} diff --git a/src/components/get-started/get-started.stories.js b/src/components/get-started/get-started.stories.js new file mode 100644 index 00000000..76d2a82c --- /dev/null +++ b/src/components/get-started/get-started.stories.js @@ -0,0 +1,9 @@ +import "./get-started.js"; + +export default { + title: "Components/Get Started", +}; + +const Template = () => ""; + +export const Primary = Template.bind({}); diff --git a/src/components/header/header.js b/src/components/header/header.js index 6077b97f..07a6743a 100644 --- a/src/components/header/header.js +++ b/src/components/header/header.js @@ -4,6 +4,7 @@ import githubIcon from "../../assets/github.svg?type=raw"; import twitterIcon from "../../assets/twitter-logo.svg?type=raw"; import mobileMenuIcon from "../../assets/tile.svg?type=raw"; import greenwoodLogo from "../../assets/greenwood-logo-full.svg?type=raw"; +import data from "./header.json" with { type: "json" }; export default class Header extends HTMLElement { constructor() { @@ -73,6 +74,7 @@ export default class Header extends HTMLElement { +

!!! ${data.message} !!!

diff --git a/src/components/header/header.json b/src/components/header/header.json new file mode 100644 index 00000000..fc04a68a --- /dev/null +++ b/src/components/header/header.json @@ -0,0 +1,3 @@ +{ + "message": "Message from JSON import attributes" +} diff --git a/src/components/hero-banner/hero-banner.js b/src/components/hero-banner/hero-banner.js new file mode 100644 index 00000000..2192650d --- /dev/null +++ b/src/components/hero-banner/hero-banner.js @@ -0,0 +1,27 @@ +import styles from "./hero-banner.module.css"; + +export default class HeroBanner extends HTMLElement { + connectedCallback() { + this.innerHTML = ` +
+

The fullstack web is here

+ +

Greenwood is your workbench for the web, embracing web standards from the ground up to empower your stack from front to back.

+ + + + + +
+
$ npx @greenwood/init@latest
+
+
+ `; + } +} + +customElements.define("app-hero-banner", HeroBanner); diff --git a/src/components/hero-banner/hero-banner.module.css b/src/components/hero-banner/hero-banner.module.css new file mode 100644 index 00000000..f3abf1ab --- /dev/null +++ b/src/components/hero-banner/hero-banner.module.css @@ -0,0 +1,75 @@ +.container { + text-align: left; + margin: 0; + padding: var(--size-px-2); +} + +.heading, +.headingEmphasis { + font-size: var(--font-size-8); + font-weight: var(--font-weight-9); + margin-block-start: 0; + margin-block-end: 0; +} + +.headingEmphasis { + text-decoration: underline; +} + +.headingSub { + font-size: var(--font-size-3); + letter-spacing: var(--font-letterspacing-2); +} + +.buttonBlitz { + display: inline-block; + cursor: pointer; + border-radius: var(--radius-3); + background-color: transparent; + padding: var(--size-fluid-1); + min-width: var(--size-px-13); + color: var(--color-black); + box-shadow: var(--shadow-2); +} + +.buttonStarted { + display: inline-block; + cursor: pointer; + border-radius: var(--radius-3); + padding: var(--size-fluid-1); + background-color: var(--color-primary); + min-width: var(--size-px-13); + color: var(--color-white); + box-shadow: var(--shadow-4); + margin-top: var(--size-fluid-1); +} + +.linkStarted { + color: var(--color-white); + text-decoration: none; +} + +.snippet { + display: block; + width: fit-content; + border-radius: var(--radius-4); + padding: 0 2px; + border: var(--radius-1) solid var(--color-primary); + box-shadow: var(--shadow-4); + margin: 5px 0; +} + +@media (min-width: 768px) { + .snippet { + display: inline-block; + letter-spacing: var(--font-letterspacing-3); + padding: 0 var(--size-4); + margin: 10px 0; + } +} + +@media (min-width: 1440px) { + .container { + max-width: 80%; + } +} diff --git a/src/components/hero-banner/hero-banner.stories.js b/src/components/hero-banner/hero-banner.stories.js new file mode 100644 index 00000000..ec7c7167 --- /dev/null +++ b/src/components/hero-banner/hero-banner.stories.js @@ -0,0 +1,9 @@ +import "./hero-banner.js"; + +export default { + title: "Components/Hero Banner", +}; + +const Template = () => ""; + +export const Primary = Template.bind({}); diff --git a/src/components/latest-post/latest-post.js b/src/components/latest-post/latest-post.js new file mode 100644 index 00000000..d0c50102 --- /dev/null +++ b/src/components/latest-post/latest-post.js @@ -0,0 +1,17 @@ +import styles from "./latest-post.module.css"; + +export default class LatestPost extends HTMLElement { + connectedCallback() { + const link = this.getAttribute("link"); + const title = this.getAttribute("title"); + + this.innerHTML = ` +
+ 🎉 New + ${title} → +
+ `; + } +} + +customElements.define("app-latest-post", LatestPost); diff --git a/src/components/latest-post/latest-post.module.css b/src/components/latest-post/latest-post.module.css new file mode 100644 index 00000000..17df04e3 --- /dev/null +++ b/src/components/latest-post/latest-post.module.css @@ -0,0 +1,19 @@ +.pill { + display: inline-block; + border-radius: var(--radius-4); + padding: var(--size-fluid-1); + border: var(--radius-1) solid var(--color-gray-background); + box-shadow: var(--shadow-2); + text-align: left; +} + +.new { + background-color: #c3ddba; + border-radius: var(--radius-4); + padding: var(--size-2); + margin-right: var(--size-fluid-1); +} + +.link { + line-height: 50px; +} diff --git a/src/components/latest-post/latest-post.spec.js b/src/components/latest-post/latest-post.spec.js new file mode 100644 index 00000000..1ef843ae --- /dev/null +++ b/src/components/latest-post/latest-post.spec.js @@ -0,0 +1,51 @@ +import { expect } from "@esm-bundle/chai"; +import "./latest-post.js"; + +describe("Components/Latest Post", () => { + const LINK = "/test/"; + const TITLE = "test title"; + let latestPost; + + before(async () => { + latestPost = document.createElement("app-latest-post"); + + latestPost.setAttribute("link", LINK); + latestPost.setAttribute("title", TITLE); + + document.body.appendChild(latestPost); + + await latestPost.updateComplete; + }); + + describe("Default Behavior", () => { + it("should not be null", () => { + expect(latestPost).not.equal(undefined); + expect(latestPost.querySelectorAll("div").length).equal(1); + }); + + describe("Link tag", () => { + let link; + + before(async () => { + link = document.querySelector("a"); + }); + + it("should have the expected href value", () => { + expect(link.getAttribute("href")).to.equal(LINK); + }); + + it("should have the expected title attribute", () => { + expect(link.getAttribute("title")).to.equal("Read our latest post"); + }); + + it("should have the expected title text", () => { + expect(link.textContent).to.equal(`${TITLE} →`); + }); + }); + }); + + after(() => { + latestPost.remove(); + latestPost = null; + }); +}); diff --git a/src/components/latest-post/latest-post.stories.js b/src/components/latest-post/latest-post.stories.js new file mode 100644 index 00000000..9ee43bbc --- /dev/null +++ b/src/components/latest-post/latest-post.stories.js @@ -0,0 +1,14 @@ +import "./latest-post.js"; + +export default { + title: "Components/Latest Post", +}; + +const Template = () => ` + +`; + +export const Primary = Template.bind({}); diff --git a/src/components/run-anywhere/platforms.json b/src/components/run-anywhere/platforms.json new file mode 100644 index 00000000..fe3bbf5d --- /dev/null +++ b/src/components/run-anywhere/platforms.json @@ -0,0 +1,22 @@ +[ + { + "name": "Vercel", + "icon": "/assets/vercel.svg", + "link": "#" + }, + { + "name": "Netlify", + "icon": "/assets/netlify.png", + "link": "#" + }, + { + "name": "NodeJS", + "icon": "/assets/node.png", + "link": "#" + }, + { + "name": "GitHub", + "icon": "/assets/github.svg", + "link": "#" + } +] diff --git a/src/components/run-anywhere/run-anywhere.js b/src/components/run-anywhere/run-anywhere.js new file mode 100644 index 00000000..0c38bc9c --- /dev/null +++ b/src/components/run-anywhere/run-anywhere.js @@ -0,0 +1,36 @@ +import platforms from "./platforms.json" with { type: "json" }; +import styles from "./run-anywhere.module.css"; + +export default class RunAnywhere extends HTMLElement { + connectedCallback() { + this.innerHTML = ` +
+

Run anywhere the web can run

+ +

Greenwood helps you take your application further by embracing platforms that embrace web standards.

+ +
+
+ ${platforms + .map((platform) => { + const { name, icon, link } = platform; + + return ` +
+
+ ${name} logo +
+ + ${name} +
+ `; + }) + .join("")} +
+
+
+ `; + } +} + +customElements.define("app-run-anywhere", RunAnywhere); diff --git a/src/components/run-anywhere/run-anywhere.module.css b/src/components/run-anywhere/run-anywhere.module.css new file mode 100644 index 00000000..6173254f --- /dev/null +++ b/src/components/run-anywhere/run-anywhere.module.css @@ -0,0 +1,67 @@ +.container { + border-left: 2px solid var(--color-gray); + border-right: 2px solid var(--color-gray); + margin: 0 auto; + text-align: center; +} + +.iconContainer { + margin: 0 auto; +} + +.heading { + font-size: var(--font-size-5); + font-weight: var(--font-weight-9); +} + +.subHeading { + text-align: center; + margin: 0px auto 30px; + padding: 20px; +} + +.iconBox { + border-radius: var(--radius-3); + box-shadow: var(--shadow-2); + background-color: var(--color-white); + width: 150px; + line-height: 150px; + margin: 0 auto; + display: inline-block; +} + +.icon { + width: 100px; + display: inline-block; + vertical-align: middle; + line-height: 100%; +} + +.iconLink { + display: inline-block; + margin: var(--size-px-2) 0 var(--size-px-4); + border-radius: var(--radius-3); + border: 1px solid #bababa; + background-color: var(--gray-background); + color: var(--color-black); + padding: 10px 20px; + text-decoration: none; + line-height: 100%; +} + +@media (min-width: 768px) { + .platformBox { + display: inline-block; + } + + .iconLink { + display: block; + margin: 0 var(--size-px-6); + } +} + +@media (min-width: 1024px) { + .subHeading { + max-width: 70%; + } +} diff --git a/src/components/run-anywhere/run-anywhere.stories.js b/src/components/run-anywhere/run-anywhere.stories.js new file mode 100644 index 00000000..87cf7e72 --- /dev/null +++ b/src/components/run-anywhere/run-anywhere.stories.js @@ -0,0 +1,9 @@ +import "./run-anywhere.js"; + +export default { + title: "Components/Run Anywhere", +}; + +const Template = () => ""; + +export const Primary = Template.bind({}); diff --git a/src/components/walkthrough/walkthrough.css b/src/components/walkthrough/walkthrough.css new file mode 100644 index 00000000..2f56290e --- /dev/null +++ b/src/components/walkthrough/walkthrough.css @@ -0,0 +1,127 @@ +:host .walkthrough { + padding: 50px; + border-radius: var(--radius-5); + color: var(--color-white); + background-color: var(--color-secondary); +} + +.walkthrough em, +.walkthrough strong { + font-size: var(--font-size-1); +} + +.cards { + overflow-x: auto; +} + +.card { + display: inline-block; + border-radius: var(--radius-5); + cursor: pointer; + margin: var(--font-size-1) 0; + padding: 10px 20px; +} + +.card:hover { + border: 2px dotted var(--color-accent); +} + +.card:hover strong, +.active strong { + color: var(--color-white); + font-weight: bold; +} + +.active { + background-color: var(--color-accent); + color: var(--color-black); +} + +.snippet pre { + border-radius: var(--radius-3); +} + +h2 { + font-size: var(--font-size-fluid-3); + font-weight: bold; + margin: 0; +} + +h3 { + color: var(--color-gray); +} + +h4 { + font-size: var(--font-size-fluid-1); + font-weight: bold; + margin: 5px 0; + display: inline-block; +} + +nav { + overflow: auto; + white-space: nowrap; + border-bottom: 1px solid var(--color-accent); + padding: 0px; + margin-bottom: 5px; +} + +ul { + list-style-type: none; + display: inline-block; + width: fit-content; + padding: 0; + margin: 0; +} + +p { + margin: 0; + padding: 10px; + text-align: left; + font-size: var(--font-size-1); + min-height: 100px; + border-radius: var(--radius-2); +} + +img { + display: inline-block; + vertical-align: middle; +} + +@media (max-width: 760px) { + code[class*="language-"], + pre[class*="language-"], + .token { + font-size: 12px; + } +} + +@media (min-width: 760px) { + :host .walkthrough { + padding: 50px 100px; + } + + .snippet pre { + border-radius: var(--radius-1); + } + + .card { + padding: 20px; + margin-right: 20px; + } + + .card:hover { + padding: 18px; + } + + nav { + padding-bottom: 10px; + margin-bottom: 10px; + } +} + +@media (min-width: 1400px) { + p { + width: 60%; + } +} diff --git a/src/components/walkthrough/walkthrough.js b/src/components/walkthrough/walkthrough.js new file mode 100644 index 00000000..6aeb4026 --- /dev/null +++ b/src/components/walkthrough/walkthrough.js @@ -0,0 +1,110 @@ +import sheet from "./walkthrough.css" with { type: "css" }; +import theme from "../../styles/theme.css" with { type: "css" }; + +const template = document.createElement("template"); + +export default class Walkthrough extends HTMLElement { + constructor() { + super(); + this.index = 0; + this.cards = []; + } + + connectedCallback() { + this.cards = globalThis.document?.querySelectorAll(".walkthrough-card") || []; + + if (this.cards.length > 0) { + template.innerHTML = ` +
+

Go from zero to fullstack with web standards

+

Lorum Ipsum...

+ + + +

${this.cards[this.index].querySelector("p").innerHTML}

+
${this.cards[this.index].querySelector("pre").outerHTML}
+
+ `; + + // TODO if going with the above option, rename cards related classes + // if (this.cards.length > 0) { + // template.innerHTML = ` + //
+ //

Go from Zero to Fullstack with web standards

+ //

Lorum Ipsum...

+ + //
+ //
+ // ${Array.from(this.cards) + // .map((card, idx) => { + // const title = card.querySelector("span").innerHTML; + // const text = card.querySelector("p").innerHTML; + // const icon = card.querySelector("i").textContent; + // const isActiveClass = idx === this.index ? " active" : ""; + + // return ` + //
+ //

+ // ${text} icon + // ${title} + //

+ //

${text}

+ //
+ // `; + // }) + // .join("")} + //
+ + //
${this.cards[this.index].querySelector("pre").outerHTML}
+ //
+ //
+ // `; + + this.attachShadow({ mode: "open" }); + this.shadowRoot.appendChild(template.content.cloneNode(true)); + this.shadowRoot.adoptedStyleSheets = [theme, sheet]; + this.shadowRoot + .querySelectorAll(".card") + .forEach((item) => item.addEventListener("click", this.selectItem.bind(this))); + } else { + console.debug("no walkthrough content cards detected"); + } + } + + selectItem(event) { + const cards = this.shadowRoot.querySelectorAll(".card"); + const index = (this.index = event.currentTarget.dataset.idx); + + this.shadowRoot.querySelector(".snippet").innerHTML = + this.cards[this.index].querySelector("pre").outerHTML; + + this.shadowRoot.querySelector("p").innerHTML = + this.cards[this.index].querySelector("p").innerHTML; + + cards.forEach((card) => { + card.dataset.idx === index ? card.classList.add("active") : card.classList.remove("active"); + }); + } +} + +customElements.define("app-walkthrough", Walkthrough); diff --git a/src/components/why-greenwood/why-greenwood.js b/src/components/why-greenwood/why-greenwood.js new file mode 100644 index 00000000..caecddab --- /dev/null +++ b/src/components/why-greenwood/why-greenwood.js @@ -0,0 +1,35 @@ +import styles from "./why-greenwood.module.css"; +import placeholderIcon from "../../assets/api-routes.svg?type=raw"; + +export default class WhyGreenwood extends HTMLElement { + connectedCallback() { + this.innerHTML = ` +
+

Why Greenwood?

+

Greenwood lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+ +
+
+

${placeholderIcon} Something 1

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+ Link +
+ +
+

${placeholderIcon} Something 2

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+ Link +
+ +
+

${placeholderIcon} Something 3

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+ Link +
+
+
+ `; + } +} + +customElements.define("app-why-greenwood", WhyGreenwood); diff --git a/src/components/why-greenwood/why-greenwood.module.css b/src/components/why-greenwood/why-greenwood.module.css new file mode 100644 index 00000000..b795fe54 --- /dev/null +++ b/src/components/why-greenwood/why-greenwood.module.css @@ -0,0 +1,64 @@ +.container { + background-color: var(--color-gray); + border: var(--border-size-1) solid var(--color-black); + border-radius: var(--radius-5); + text-align: center; + margin: 0 auto; + padding: 20px 20px; +} + +.heading { + font-size: var(--font-size-5); + font-weight: var(--font-weight-9); +} + +.subHeading { + margin: 10px auto 30px; +} + +.cardContainer { + background-color: var(--color-white); + border-radius: var(--radius-5); +} + +.card { + display: inline-block; + text-align: left; + margin: 10px 10px 10px; + padding: 20px; + border-radius: var(--radius-5); + background-color: var(--color-gray); +} + +.card h3 { + padding: 20px; + border-radius: var(--radius-5); + background-color: var(--color-gray-background); + line-height: 50px; +} + +.card svg { + vertical-align: middle; +} + +.card a { + display: inline-block; + margin-left: 40px; + width: 100px; + padding: 10px 0; + text-align: center; + border-radius: var(--radius-5); + border: var(--border-size-1) solid var(--color-black); +} + +@media (min-width: 1024px) { + .card { + display: inline-block; + margin: 20px 10px 20px 20px; + width: 29%; + } + + .subHeading { + width: 60%; + } +} diff --git a/src/components/why-greenwood/why-greenwood.stories.js b/src/components/why-greenwood/why-greenwood.stories.js new file mode 100644 index 00000000..6662928f --- /dev/null +++ b/src/components/why-greenwood/why-greenwood.stories.js @@ -0,0 +1,9 @@ +import "./why-greenwood.js"; + +export default { + title: "Components/Why Greenwood", +}; + +const Template = () => ""; + +export const Primary = Template.bind({}); diff --git a/src/pages/index.md b/src/pages/index.md index 57cf31da..f1188986 100644 --- a/src/pages/index.md +++ b/src/pages/index.md @@ -1,14 +1,170 @@ --- imports: + - ../components/latest-post/latest-post.js data-gwd-opt="static" type="module" + - ../components/hero-banner/hero-banner.js data-gwd-opt="static" type="module" + - ../components/walkthrough/walkthrough.js type="module" + - ../components/why-greenwood/why-greenwood.js data-gwd-opt="static" type="module" + - ../components/run-anywhere/run-anywhere.js data-gwd-opt="static" type="module" + - ../components/build-with-friends/build-with-friends.js data-gwd-opt="static" type="module" + - ../components/get-started/get-started.js data-gwd-opt="static" type="module" - ../styles/home.css --- -# Welcome to Greenwood! + + + + + + +
+ HTML First + html.svg +

Greenwood is HTML first by design. Start from just an index.html file or leverage hybrid, file-system based routing to easily achieve static and dynamic pages side-by-side.

+ +```html + + + + My Site + + + +

Welcome to our site!

+

+ Feel free to browse around or + contact us + if you have any questions. +

+ + +``` + +
+ +
+ Server Rendering + build-ssg.svg +

Yay SSR! Lorum...

```js -return new Response("

Hello World

", { - headers: { - "Content-Type": "text/html", - }, -}); +// pages/products.js +import "../components/card.js"; +import { getProducts } from "../services/products.js"; + +export default class ProductsPage extends HTMLElement { + async connectedCallback() { + const products = await getProducts(); + const html = products + .map((product) => { + const { title, thumbnail } = product; + + return ` + + + `; + }) + .join(""); + + this.innerHTML = ` +

Product Catalog

+
${html}
+ `; + } +} ``` + +
+ +
+ Web Components + web-components.svg +

Yay Web Components! Lorum...

+ +```js +// components/card.js +import sheet from "./card.js" with { type: "css" }; + +export default class Card extends HTMLElement { + connectedCallback() { + if (!this.shadowRoot) { + const thumbnail = this.getAttribute("thumbnail"); + const title = this.getAttribute("title"); + const template = document.createElement("template"); + + template.innerHTML = ` +
+

${title}

+ ${title} +
+ `; + this.attachShadow({ mode: "open" }); + this.shadowRoot.appendChild(template.content.cloneNode(true)); + } + + this.shadowRoot.adoptedStyleSheets = [sheet]; + } +} + +customElements.define("app-card", Card); +``` + +
+ +
+ API Routes + api-routes.svg +

Yay API Routes! Lorum...

+ +```js +// api/search.js +import { renderFromHTML } from "wc-compiler"; +import { getProducts } from "../services/products.js"; + +export async function handler(request) { + const formData = await request.formData(); + const searchTerm = formData.has("term") ? formData.get("term") : ""; + const products = await getProducts(searchTerm); + let body = "No results found."; + + if (products.length > 0) { + const { html } = await renderFromHTML( + ` + ${products + .map((item, idx) => { + const { title, thumbnail } = item; + + return ` + + `; + }) + .join("")} + `, + [new URL("../components/card.js", import.meta.url)], + ); + + body = html; + } + + return new Response(body, { + headers: new Headers({ + "Content-Type": "text/html", + }), + }); +} +``` + +
+ + + + + + + + diff --git a/src/styles/home.css b/src/styles/home.css index 2b330484..a857f5f1 100644 --- a/src/styles/home.css +++ b/src/styles/home.css @@ -1,9 +1,32 @@ -h1 { - text-align: center; +app-latest-post, +app-hero-banner, +app-walkthrough { + display: block; + margin: var(--size-fluid-1) auto; } -pre { - margin: 0 auto !important; - width: 30%; - overflow: scroll; +.walkthrough-card { + display: none; +} + +app-get-started { + display: block; + padding-bottom: 160px; +} + +app-get-started { + display: block; + margin-bottom: -300px; +} + +@media (min-width: 768px) { + app-hero-banner, + app-latest-post { + width: 70%; + } + + app-run-anywhere { + display: block; + margin: 0 auto; + } } diff --git a/src/styles/theme.css b/src/styles/theme.css index 2dd48507..2a9de343 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -15,7 +15,8 @@ format("truetype"); } -:root { +:root, +:host { --color-primary: #016341; --color-secondary: #0e0f0c; --color-tertiary: #151818; @@ -33,7 +34,7 @@ * { font-family: var(--font-primary); - font-size: var(--size-px-3); + font-size: var(--font-size-3); box-sizing: border-box; }