Add support for React components. (#18)

* Add support for React components.

This adds support for react components via a new `extensions` config in astro.config.mjs. In the future we can extend this to do things like look at the import statements, as Snowpack does.

* Fix the tests
This commit is contained in:
Matthew Phillips 2021-03-23 13:47:54 -04:00 committed by GitHub
parent 3f16550765
commit 854d0feb34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 388 additions and 52 deletions

View file

@ -2,5 +2,8 @@
export default {
projectRoot: '.',
hmxRoot: './astro',
dist: './_site'
dist: './_site',
extensions: {
'.jsx': 'preact'
}
}

View file

@ -72,6 +72,7 @@
.grid-body {
padding: 20px 0 0 0;
}
}
.header-snowpack {
font-size: 3.5rem;

View file

@ -1269,6 +1269,8 @@
"requires": {
"@types/estree": "0.0.46",
"@types/node": "^14.14.31",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@vue/server-renderer": "^3.0.7",
"acorn": "^7.4.0",
"acorn-jsx": "^5.3.1",
@ -1292,6 +1294,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"sass": "^1.32.8",
"snowpack": "^3.1.0-pre.14",
"svelte": "^3.35.0",
"vue": "^3.0.7",
"yargs-parser": "^20.2.7"
@ -1463,6 +1466,40 @@
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA=="
},
"@types/prop-types": {
"version": "15.7.3",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
"dev": true
},
"@types/react": {
"version": "17.0.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz",
"integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==",
"dev": true,
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
},
"dependencies": {
"csstype": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.7.tgz",
"integrity": "sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g==",
"dev": true
}
}
},
"@types/react-dom": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.2.tgz",
"integrity": "sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg==",
"dev": true,
"requires": {
"@types/react": "*"
}
},
"@types/sass": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.16.0.tgz",
@ -1471,6 +1508,12 @@
"@types/node": "*"
}
},
"@types/scheduler": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==",
"dev": true
},
"@types/yargs-parser": {
"version": "20.2.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz",
@ -1785,6 +1828,12 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"big-integer": {
"version": "1.6.48",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
"dev": true
},
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@ -1816,6 +1865,15 @@
"widest-line": "^3.1.0"
}
},
"bplist-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz",
"integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=",
"dev": true,
"requires": {
"big-integer": "^1.6.7"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -1984,6 +2042,12 @@
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
"integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw=="
},
"cli-spinners": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==",
"dev": true
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@ -2214,6 +2278,28 @@
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"default-browser-id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-2.0.0.tgz",
"integrity": "sha1-AezONxpx6F8VoXF354YwR+c9vn0=",
"dev": true,
"requires": {
"bplist-parser": "^0.1.0",
"pify": "^2.3.0",
"untildify": "^2.0.0"
},
"dependencies": {
"untildify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz",
"integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=",
"dev": true,
"requires": {
"os-homedir": "^1.0.0"
}
}
}
},
"defer-to-connect": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
@ -2350,6 +2436,12 @@
"integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==",
"dev": true
},
"esbuild": {
"version": "0.9.6",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.9.6.tgz",
"integrity": "sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA==",
"dev": true
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -2631,6 +2723,12 @@
"reusify": "^1.0.4"
}
},
"fdir": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-5.0.0.tgz",
"integrity": "sha512-cteqwWMA43lEmgwOg5HSdvhVFD39vHjQDhZkRMlKmeoNPtSSgUw1nUypydiY2upMdGiBFBZvNBDbnoBh0yCzaQ==",
"dev": true
},
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -3007,6 +3105,12 @@
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
"dev": true
},
"is-docker": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
"dev": true
},
"is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
@ -3071,6 +3175,15 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
"requires": {
"is-docker": "^2.0.0"
}
},
"is-yarn-global": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
@ -3479,6 +3592,16 @@
"wrappy": "1"
}
},
"open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"dev": true,
"requires": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
}
},
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@ -3492,6 +3615,12 @@
"word-wrap": "^1.2.3"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
},
"p-cancelable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
@ -3586,6 +3715,12 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
},
"postcss": {
"version": "8.2.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.8.tgz",
@ -3884,6 +4019,15 @@
"glob": "^7.1.3"
}
},
"rollup": {
"version": "2.42.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.42.3.tgz",
"integrity": "sha512-JjaT9WaUS5vmjy6xUrnPOskjkQg2cN4WSACNCwbOvBz8VDmbiKVdmTFUoMPRqTud0tsex8Xy9/boLbDW9HKD1w==",
"dev": true,
"requires": {
"fsevents": "~2.3.1"
}
},
"run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@ -3990,6 +4134,23 @@
"is-fullwidth-code-point": "^3.0.0"
}
},
"snowpack": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/snowpack/-/snowpack-3.1.2.tgz",
"integrity": "sha512-LsYlBNjB/t/p5QP434Pa1TqjyuX8VtXiYQaAWZkOn1d1TVKEt7nigMBr8Z+EDXYn6YlLXYKHXDvv/NhUS7Ri9A==",
"dev": true,
"requires": {
"cli-spinners": "^2.5.0",
"default-browser-id": "^2.0.0",
"esbuild": "^0.9.3",
"fdir": "^5.0.0",
"fsevents": "^2.2.0",
"open": "^7.0.4",
"picomatch": "^2.2.2",
"resolve": "^1.20.0",
"rollup": "^2.34.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View file

@ -44,6 +44,7 @@
"postcss-preset-env": "^6.7.0",
"prettier": "^2.0.5",
"snowpack": "^3.1.0-pre.14",
"sass": "^1.32.8",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-rational-order": "^0.1.2",

73
package-lock.json generated
View file

@ -190,6 +190,36 @@
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
"dev": true
},
"@types/prop-types": {
"version": "15.7.3",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
},
"@types/react": {
"version": "17.0.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz",
"integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==",
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
},
"dependencies": {
"csstype": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.7.tgz",
"integrity": "sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g=="
}
}
},
"@types/react-dom": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.2.tgz",
"integrity": "sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg==",
"requires": {
"@types/react": "*"
}
},
"@types/sass": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.16.0.tgz",
@ -199,6 +229,11 @@
"@types/node": "*"
}
},
"@types/scheduler": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
},
"@types/yargs-parser": {
"version": "20.2.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz",
@ -527,8 +562,7 @@
"big-integer": {
"version": "1.6.48",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
"dev": true
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
"big.js": {
"version": "5.2.2",
@ -566,7 +600,6 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz",
"integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=",
"dev": true,
"requires": {
"big-integer": "^1.6.7"
}
@ -750,8 +783,7 @@
"cli-spinners": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==",
"dev": true
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q=="
},
"cliui": {
"version": "7.0.4",
@ -1005,7 +1037,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-2.0.0.tgz",
"integrity": "sha1-AezONxpx6F8VoXF354YwR+c9vn0=",
"dev": true,
"requires": {
"bplist-parser": "^0.1.0",
"pify": "^2.3.0",
@ -1016,7 +1047,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz",
"integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=",
"dev": true,
"requires": {
"os-homedir": "^1.0.0"
}
@ -1174,8 +1204,7 @@
"esbuild": {
"version": "0.9.6",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.9.6.tgz",
"integrity": "sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA==",
"dev": true
"integrity": "sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA=="
},
"escalade": {
"version": "3.1.1",
@ -1493,8 +1522,7 @@
"fdir": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-5.0.0.tgz",
"integrity": "sha512-cteqwWMA43lEmgwOg5HSdvhVFD39vHjQDhZkRMlKmeoNPtSSgUw1nUypydiY2upMdGiBFBZvNBDbnoBh0yCzaQ==",
"dev": true
"integrity": "sha512-cteqwWMA43lEmgwOg5HSdvhVFD39vHjQDhZkRMlKmeoNPtSSgUw1nUypydiY2upMdGiBFBZvNBDbnoBh0yCzaQ=="
},
"file-entry-cache": {
"version": "6.0.1",
@ -1549,8 +1577,7 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"functional-red-black-tree": {
"version": "1.0.1",
@ -1698,7 +1725,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
@ -1882,7 +1908,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
"requires": {
"has": "^1.0.3"
}
@ -1895,8 +1920,7 @@
"is-docker": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
"dev": true
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw=="
},
"is-extendable": {
"version": "0.1.1",
@ -1970,7 +1994,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
"requires": {
"is-docker": "^2.0.0"
}
@ -2230,7 +2253,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
"dev": true,
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
@ -2397,7 +2419,6 @@
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"dev": true,
"requires": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
@ -2420,8 +2441,7 @@
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"p-cancelable": {
"version": "1.1.0",
@ -2513,8 +2533,7 @@
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"path-type": {
"version": "4.0.0",
@ -2530,8 +2549,7 @@
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
},
"postcss": {
"version": "8.2.8",
@ -2813,7 +2831,6 @@
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"dev": true,
"requires": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
@ -2853,7 +2870,6 @@
"version": "2.42.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.42.3.tgz",
"integrity": "sha512-JjaT9WaUS5vmjy6xUrnPOskjkQg2cN4WSACNCwbOvBz8VDmbiKVdmTFUoMPRqTud0tsex8Xy9/boLbDW9HKD1w==",
"dev": true,
"requires": {
"fsevents": "~2.3.1"
}
@ -2976,7 +2992,6 @@
"version": "3.1.0-pre.14",
"resolved": "https://registry.npmjs.org/snowpack/-/snowpack-3.1.0-pre.14.tgz",
"integrity": "sha512-NJm+XOMHryrDPWkqpqqBjQLZcSrs8WzW84H0vs3m10kFD1vvOBqPrD5ECH3fRVre314wA3arOgZbWGhY27A29w==",
"dev": true,
"requires": {
"cli-spinners": "^2.5.0",
"default-browser-id": "^2.0.0",

View file

@ -27,6 +27,8 @@
"dependencies": {
"@types/estree": "0.0.46",
"@types/node": "^14.14.31",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@vue/server-renderer": "^3.0.7",
"acorn": "^7.4.0",
"acorn-jsx": "^5.3.1",
@ -50,6 +52,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"sass": "^1.32.8",
"snowpack": "^3.1.0-pre.14",
"svelte": "^3.35.0",
"vue": "^3.0.7",
"yargs-parser": "^20.2.7"
@ -72,7 +75,6 @@
"preact": "^10.5.12",
"preact-render-to-string": "^5.1.14",
"prettier": "^2.2.1",
"snowpack": "^3.1.0-pre.14",
"typescript": "^4.2.3",
"uvu": "^0.5.1"
}

View file

@ -3,7 +3,7 @@ const { readFile } = require('fs').promises;
// Snowpack plugins must be CommonJS :(
const transformPromise = import('./lib/transform2.js');
module.exports = function (snowpackConfig, { resolve } = {}) {
module.exports = function (snowpackConfig, { resolve, extensions } = {}) {
return {
name: 'snowpack-hmx',
knownEntrypoints: ['deepmerge'],
@ -15,7 +15,11 @@ module.exports = function (snowpackConfig, { resolve } = {}) {
const { compileComponent } = await transformPromise;
const projectRoot = snowpackConfig.root;
const contents = await readFile(filePath, 'utf-8');
const result = await compileComponent(contents, { compileOptions: { resolve }, filename: filePath, projectRoot });
const compileOptions = {
resolve,
extensions
};
const result = await compileComponent(contents, { compileOptions, filename: filePath, projectRoot });
return result.contents;
},
};

View file

@ -2,12 +2,16 @@ export interface AstroConfigRaw {
dist: string;
projectRoot: string;
hmxRoot: string;
jsx?: string;
}
export type ValidExtensionPlugins = 'hmx' | 'react' | 'preact' | 'svelte' | 'vue';
export interface AstroConfig {
dist: string;
projectRoot: URL;
hmxRoot: URL;
extensions?: Record<string, ValidExtensionPlugins>
}
export interface JsxItem {

View file

@ -1,6 +1,8 @@
import type { LogOptions } from '../logger';
import type { ValidExtensionPlugins } from './astro';
export interface CompileOptions {
logging: LogOptions;
resolve: (p: string) => string;
extensions?: Record<string, ValidExtensionPlugins>;
}

View file

@ -1,4 +1,5 @@
import type { CompileOptions } from '../@types/compiler';
import type { ValidExtensionPlugins } from '../@types/astro';
import type { Ast, TemplateNode } from '../compiler/interfaces';
import type { JsxItem, TransformResult } from '../@types/astro';
@ -89,10 +90,34 @@ function generateAttributes(attrs: Record<string, string>): string {
return result + '}';
}
function getComponentWrapper(_name: string, { type, url }: { type: string; url: string }, { resolve }: CompileOptions) {
interface ComponentInfo {
type: string;
url: string;
}
const defaultExtensions: Readonly<Record<string, ValidExtensionPlugins>> = {
'.hmx': 'hmx',
'.jsx': 'react',
'.vue': 'vue',
'.svelte': 'svelte'
};
function getComponentWrapper(_name: string, { type, url }: ComponentInfo, compileOptions: CompileOptions) {
const {
resolve,
extensions = defaultExtensions
} = compileOptions;
const [name, kind] = _name.split(':');
switch (type) {
case '.hmx': {
const plugin = extensions[type] || defaultExtensions[type];
if(!plugin) {
throw new Error(`No supported plugin found for extension ${type}`);
}
switch (plugin) {
case 'hmx': {
if (kind) {
throw new Error(`HMX does not support :${kind}`);
}
@ -101,7 +126,7 @@ function getComponentWrapper(_name: string, { type, url }: { type: string; url:
wrapperImport: ``,
};
}
case '.jsx': {
case 'preact': {
if (kind === 'dynamic') {
return {
wrapper: `__preact_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.js'))}, \`http://TEST\${import.meta.url}\`).pathname, '${resolve('preact')}')`,
@ -114,7 +139,20 @@ function getComponentWrapper(_name: string, { type, url }: { type: string; url:
};
}
}
case '.svelte': {
case 'react': {
if (kind === 'dynamic') {
return {
wrapper: `__react_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.js'))}, \`http://TEST\${import.meta.url}\`).pathname, '${resolve('react')}', '${resolve('react-dom')}')`,
wrapperImport: `import {__react_dynamic} from '${internalImport('render/react.js')}';`,
};
} else {
return {
wrapper: `__react_static(${name})`,
wrapperImport: `import {__react_static} from '${internalImport('render/react.js')}';`,
};
}
}
case 'svelte': {
if (kind === 'dynamic') {
return {
wrapper: `__svelte_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.svelte.js'))}, \`http://TEST\${import.meta.url}\`).pathname)`,
@ -127,7 +165,7 @@ function getComponentWrapper(_name: string, { type, url }: { type: string; url:
};
}
}
case '.vue': {
case 'vue': {
if (kind === 'dynamic') {
return {
wrapper: `__vue_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.vue.js'))}, \`http://TEST\${import.meta.url}\`).pathname, '${resolve('vue')}')`,

View file

@ -0,0 +1,28 @@
import React from 'react';
import ReactDOMServer from 'react-dom/server';
export function __react_static(ReactComponent: any) {
return (attrs: Record<string, any>, ...children: any): string => {
let html = ReactDOMServer.renderToString(
React.createElement(
ReactComponent,
attrs,
children
)
);
return html;
};
}
export function __react_dynamic(ReactComponent: any, importUrl: string, reactUrl: string, reactDomUrl: string) {
const placeholderId = `placeholder_${String(Math.random())}`;
return (attrs: Record<string, string>, ...children: any) => {
return `<div id="${placeholderId}"></div><script type="module">
import React from '${reactUrl}';
import ReactDOM from '${reactDomUrl}';
import Component from '${importUrl}';
ReactDOM.render(React.createElement(Component, ${JSON.stringify(attrs)}), document.getElementById('${placeholderId}'));
</script>`;
};
}

View file

@ -96,12 +96,15 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
}
export async function createRuntime(astroConfig: AstroConfig, logging: LogOptions) {
const { projectRoot, hmxRoot } = astroConfig;
const { projectRoot, hmxRoot, extensions } = astroConfig;
const internalPath = new URL('./frontend/', import.meta.url);
// Workaround for SKY-251
const hmxPlugOptions: { resolve?: (s: string) => string } = {};
const hmxPlugOptions: {
resolve?: (s: string) => string;
extensions?: Record<string, string>
} = { extensions };
if (existsSync(new URL('./package-lock.json', projectRoot))) {
const pkgLockStr = await readFile(new URL('./package-lock.json', projectRoot), 'utf-8');
const pkgLock = JSON.parse(pkgLockStr);
@ -125,7 +128,10 @@ export async function createRuntime(astroConfig: AstroConfig, logging: LogOption
},
packageOptions: {
knownEntrypoints: ['preact-render-to-string'],
external: ['@vue/server-renderer'],
external: [
'@vue/server-renderer',
'node-fetch'
],
},
});
const snowpack = await startSnowpackServer({

View file

@ -0,0 +1,7 @@
export default {
projectRoot: '.',
hmxRoot: './astro',
dist: './_site'
// No extensions needed, React is the default.
}

View file

@ -0,0 +1,5 @@
import React from 'react';
export default function({ name }) {
return <h2>Hello {name}!</h2>
}

View file

@ -0,0 +1,10 @@
<script astro>
import Hello from '../components/Hello.jsx';
</script>
<astro:head>
<!-- Head Stuff -->
</astro:head>
<h1>My page</h1>
<Hello name="world" />

View file

@ -0,0 +1,5 @@
export default {
mount: {
}
};

View file

@ -0,0 +1,40 @@
import { suite } from 'uvu';
import * as assert from 'uvu/assert';
import { createRuntime } from '../lib/runtime.js';
import { loadConfig } from '../lib/config.js';
import { doc } from './test-utils.js';
const React = suite('React Components');
let runtime;
React.before(async () => {
const astroConfig = await loadConfig(new URL('./fixtures/react-component', import.meta.url).pathname);
const logging = {
level: 'error',
dest: process.stderr
};
try {
runtime = await createRuntime(astroConfig, logging);
} catch(err) {
console.error(err);
throw err;
}
});
React.after(async () => {
await runtime.shutdown();
});
React('Can load hmx page', async () => {
const result = await runtime.load('/');
assert.equal(result.statusCode, 200);
const $ = doc(result.contents);
assert.equal($('h2').text(), 'Hello world!');
});
React.run();

View file

@ -1,35 +1,39 @@
import { suite } from 'uvu';
import * as assert from 'uvu/assert';
import { createRuntime } from '../lib/runtime.js';
import { loadConfig } from '../lib/config.js';
import { promises as fsPromises } from 'fs';
import { relative as pathRelative } from 'path';
import { doc } from './test-utils.js';
const { readdir, stat } = fsPromises;
// Bug: Snowpack config is still loaded relative to the current working directory.
process.chdir(new URL('../examples/snowpack/', import.meta.url).pathname);
const SnowpackDev = suite('snowpack.dev');
let runtime;
let runtime, cwd;
SnowpackDev.before(async () => {
const astroConfig = {
projectRoot: new URL('../examples/snowpack/', import.meta.url),
hmxRoot: new URL('../examples/snowpack/astro/', import.meta.url),
dist: './_site',
};
// Bug: Snowpack config is still loaded relative to the current working directory.
cwd = process.cwd();
process.chdir(new URL('../examples/snowpack/', import.meta.url).pathname);
const astroConfig = await loadConfig(new URL('../examples/snowpack', import.meta.url).pathname);
const logging = {
level: 'error',
dest: process.stderr,
};
runtime = await createRuntime(astroConfig, logging);
try {
runtime = await createRuntime(astroConfig, logging);
} catch(err) {
console.error(err);
throw err;
}
});
SnowpackDev.after(async () => {
process.chdir(cwd);
await runtime && runtime.shutdown();
});