├── .gitignore ├── importmap.json ├── package-lock.json ├── package.json ├── readme.md ├── renderers ├── htm-preact-renderer.js └── htm-react-renderer.js ├── templates ├── preact │ ├── _layout.preact.js │ ├── components │ │ ├── _counter.preact.js │ │ ├── _hydrator.js │ │ ├── _init-hydrate.js │ │ ├── _script-manager.js │ │ └── _script.js │ └── home.preact.js └── react │ ├── _layout.react.js │ └── home.react.js └── utilities └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | output -------------------------------------------------------------------------------- /importmap.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "preact" : "/output/preact/node_modules/preact/dist/preact.mjs", 4 | "htm/preact/index.mjs" : "/output/preact/node_modules/htm/preact/index.mjs", 5 | "htm": "/output/preact/node_modules/htm/dist/htm.mjs", 6 | "preact/hooks/dist/hooks.mjs": "/output/preact/node_modules/preact/hooks/dist/hooks.mjs" 7 | } 8 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssg", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "version": "1.0.0", 9 | "license": "ISC", 10 | "dependencies": { 11 | "htm": "^3.0.4", 12 | "preact": "^10.5.7", 13 | "preact-render-to-string": "^5.1.12" 14 | }, 15 | "devDependencies": { 16 | "http-server": "^0.12.3", 17 | "react": "^17.0.1", 18 | "react-dom": "^17.0.1", 19 | "rimraf": "^3.0.2", 20 | "yargs": "^16.1.1" 21 | } 22 | }, 23 | "node_modules/ansi-regex": { 24 | "version": "5.0.0", 25 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 26 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 27 | "dev": true, 28 | "engines": { 29 | "node": ">=8" 30 | } 31 | }, 32 | "node_modules/ansi-styles": { 33 | "version": "4.3.0", 34 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 35 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 36 | "dev": true, 37 | "dependencies": { 38 | "color-convert": "^2.0.1" 39 | }, 40 | "engines": { 41 | "node": ">=8" 42 | }, 43 | "funding": { 44 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 45 | } 46 | }, 47 | "node_modules/async": { 48 | "version": "2.6.3", 49 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", 50 | "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", 51 | "dev": true, 52 | "dependencies": { 53 | "lodash": "^4.17.14" 54 | } 55 | }, 56 | "node_modules/balanced-match": { 57 | "version": "1.0.0", 58 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 59 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 60 | "dev": true 61 | }, 62 | "node_modules/basic-auth": { 63 | "version": "1.1.0", 64 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 65 | "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", 66 | "dev": true, 67 | "engines": { 68 | "node": ">= 0.6" 69 | } 70 | }, 71 | "node_modules/brace-expansion": { 72 | "version": "1.1.11", 73 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 74 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 75 | "dev": true, 76 | "dependencies": { 77 | "balanced-match": "^1.0.0", 78 | "concat-map": "0.0.1" 79 | } 80 | }, 81 | "node_modules/cliui": { 82 | "version": "7.0.4", 83 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 84 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 85 | "dev": true, 86 | "dependencies": { 87 | "string-width": "^4.2.0", 88 | "strip-ansi": "^6.0.0", 89 | "wrap-ansi": "^7.0.0" 90 | } 91 | }, 92 | "node_modules/color-convert": { 93 | "version": "2.0.1", 94 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 95 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 96 | "dev": true, 97 | "dependencies": { 98 | "color-name": "~1.1.4" 99 | }, 100 | "engines": { 101 | "node": ">=7.0.0" 102 | } 103 | }, 104 | "node_modules/color-name": { 105 | "version": "1.1.4", 106 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 107 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 108 | "dev": true 109 | }, 110 | "node_modules/colors": { 111 | "version": "1.4.0", 112 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 113 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 114 | "dev": true, 115 | "engines": { 116 | "node": ">=0.1.90" 117 | } 118 | }, 119 | "node_modules/concat-map": { 120 | "version": "0.0.1", 121 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 122 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 123 | "dev": true 124 | }, 125 | "node_modules/corser": { 126 | "version": "2.0.1", 127 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 128 | "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", 129 | "dev": true, 130 | "engines": { 131 | "node": ">= 0.4.0" 132 | } 133 | }, 134 | "node_modules/debug": { 135 | "version": "3.2.7", 136 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 137 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 138 | "dev": true, 139 | "dependencies": { 140 | "ms": "^2.1.1" 141 | } 142 | }, 143 | "node_modules/ecstatic": { 144 | "version": "3.3.2", 145 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 146 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 147 | "dev": true, 148 | "dependencies": { 149 | "he": "^1.1.1", 150 | "mime": "^1.6.0", 151 | "minimist": "^1.1.0", 152 | "url-join": "^2.0.5" 153 | }, 154 | "bin": { 155 | "ecstatic": "lib/ecstatic.js" 156 | } 157 | }, 158 | "node_modules/emoji-regex": { 159 | "version": "8.0.0", 160 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 161 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 162 | "dev": true 163 | }, 164 | "node_modules/escalade": { 165 | "version": "3.1.1", 166 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 167 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 168 | "dev": true, 169 | "engines": { 170 | "node": ">=6" 171 | } 172 | }, 173 | "node_modules/eventemitter3": { 174 | "version": "4.0.7", 175 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 176 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 177 | "dev": true 178 | }, 179 | "node_modules/follow-redirects": { 180 | "version": "1.13.0", 181 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", 182 | "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", 183 | "dev": true, 184 | "funding": [ 185 | { 186 | "type": "individual", 187 | "url": "https://github.com/sponsors/RubenVerborgh" 188 | } 189 | ], 190 | "engines": { 191 | "node": ">=4.0" 192 | } 193 | }, 194 | "node_modules/fs.realpath": { 195 | "version": "1.0.0", 196 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 197 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 198 | "dev": true 199 | }, 200 | "node_modules/get-caller-file": { 201 | "version": "2.0.5", 202 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 203 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 204 | "dev": true, 205 | "engines": { 206 | "node": "6.* || 8.* || >= 10.*" 207 | } 208 | }, 209 | "node_modules/glob": { 210 | "version": "7.1.6", 211 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 212 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 213 | "dev": true, 214 | "dependencies": { 215 | "fs.realpath": "^1.0.0", 216 | "inflight": "^1.0.4", 217 | "inherits": "2", 218 | "minimatch": "^3.0.4", 219 | "once": "^1.3.0", 220 | "path-is-absolute": "^1.0.0" 221 | }, 222 | "engines": { 223 | "node": "*" 224 | }, 225 | "funding": { 226 | "url": "https://github.com/sponsors/isaacs" 227 | } 228 | }, 229 | "node_modules/he": { 230 | "version": "1.2.0", 231 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 232 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 233 | "dev": true, 234 | "bin": { 235 | "he": "bin/he" 236 | } 237 | }, 238 | "node_modules/htm": { 239 | "version": "3.0.4", 240 | "resolved": "https://registry.npmjs.org/htm/-/htm-3.0.4.tgz", 241 | "integrity": "sha512-VRdvxX3tmrXuT/Ovt59NMp/ORMFi4bceFMDjos1PV4E0mV+5votuID8R60egR9A4U8nLt238R/snlJGz3UYiTQ==" 242 | }, 243 | "node_modules/http-proxy": { 244 | "version": "1.18.1", 245 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 246 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 247 | "dev": true, 248 | "dependencies": { 249 | "eventemitter3": "^4.0.0", 250 | "follow-redirects": "^1.0.0", 251 | "requires-port": "^1.0.0" 252 | }, 253 | "engines": { 254 | "node": ">=8.0.0" 255 | } 256 | }, 257 | "node_modules/http-server": { 258 | "version": "0.12.3", 259 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", 260 | "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", 261 | "dev": true, 262 | "dependencies": { 263 | "basic-auth": "^1.0.3", 264 | "colors": "^1.4.0", 265 | "corser": "^2.0.1", 266 | "ecstatic": "^3.3.2", 267 | "http-proxy": "^1.18.0", 268 | "minimist": "^1.2.5", 269 | "opener": "^1.5.1", 270 | "portfinder": "^1.0.25", 271 | "secure-compare": "3.0.1", 272 | "union": "~0.5.0" 273 | }, 274 | "bin": { 275 | "hs": "bin/http-server", 276 | "http-server": "bin/http-server" 277 | }, 278 | "engines": { 279 | "node": ">=6" 280 | } 281 | }, 282 | "node_modules/inflight": { 283 | "version": "1.0.6", 284 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 285 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 286 | "dev": true, 287 | "dependencies": { 288 | "once": "^1.3.0", 289 | "wrappy": "1" 290 | } 291 | }, 292 | "node_modules/inherits": { 293 | "version": "2.0.4", 294 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 295 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 296 | "dev": true 297 | }, 298 | "node_modules/is-fullwidth-code-point": { 299 | "version": "3.0.0", 300 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 301 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 302 | "dev": true, 303 | "engines": { 304 | "node": ">=8" 305 | } 306 | }, 307 | "node_modules/js-tokens": { 308 | "version": "4.0.0", 309 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 310 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 311 | "dev": true 312 | }, 313 | "node_modules/lodash": { 314 | "version": "4.17.20", 315 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 316 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 317 | "dev": true 318 | }, 319 | "node_modules/loose-envify": { 320 | "version": "1.4.0", 321 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 322 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 323 | "dev": true, 324 | "dependencies": { 325 | "js-tokens": "^3.0.0 || ^4.0.0" 326 | }, 327 | "bin": { 328 | "loose-envify": "cli.js" 329 | } 330 | }, 331 | "node_modules/mime": { 332 | "version": "1.6.0", 333 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 334 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 335 | "dev": true, 336 | "bin": { 337 | "mime": "cli.js" 338 | }, 339 | "engines": { 340 | "node": ">=4" 341 | } 342 | }, 343 | "node_modules/minimatch": { 344 | "version": "3.0.4", 345 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 346 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 347 | "dev": true, 348 | "dependencies": { 349 | "brace-expansion": "^1.1.7" 350 | }, 351 | "engines": { 352 | "node": "*" 353 | } 354 | }, 355 | "node_modules/minimist": { 356 | "version": "1.2.5", 357 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 358 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 359 | "dev": true 360 | }, 361 | "node_modules/mkdirp": { 362 | "version": "0.5.5", 363 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 364 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 365 | "dev": true, 366 | "dependencies": { 367 | "minimist": "^1.2.5" 368 | }, 369 | "bin": { 370 | "mkdirp": "bin/cmd.js" 371 | } 372 | }, 373 | "node_modules/ms": { 374 | "version": "2.1.2", 375 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 376 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 377 | "dev": true 378 | }, 379 | "node_modules/object-assign": { 380 | "version": "4.1.1", 381 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 382 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 383 | "dev": true, 384 | "engines": { 385 | "node": ">=0.10.0" 386 | } 387 | }, 388 | "node_modules/once": { 389 | "version": "1.4.0", 390 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 391 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 392 | "dev": true, 393 | "dependencies": { 394 | "wrappy": "1" 395 | } 396 | }, 397 | "node_modules/opener": { 398 | "version": "1.5.2", 399 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 400 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 401 | "dev": true, 402 | "bin": { 403 | "opener": "bin/opener-bin.js" 404 | } 405 | }, 406 | "node_modules/path-is-absolute": { 407 | "version": "1.0.1", 408 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 409 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 410 | "dev": true, 411 | "engines": { 412 | "node": ">=0.10.0" 413 | } 414 | }, 415 | "node_modules/portfinder": { 416 | "version": "1.0.28", 417 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", 418 | "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", 419 | "dev": true, 420 | "dependencies": { 421 | "async": "^2.6.2", 422 | "debug": "^3.1.1", 423 | "mkdirp": "^0.5.5" 424 | }, 425 | "engines": { 426 | "node": ">= 0.12.0" 427 | } 428 | }, 429 | "node_modules/preact": { 430 | "version": "10.5.7", 431 | "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.7.tgz", 432 | "integrity": "sha512-4oEpz75t/0UNcwmcsjk+BIcDdk68oao+7kxcpc1hQPNs2Oo3ZL9xFz8UBf350mxk/VEdD41L5b4l2dE3Ug3RYg==", 433 | "funding": { 434 | "type": "opencollective", 435 | "url": "https://opencollective.com/preact" 436 | } 437 | }, 438 | "node_modules/preact-render-to-string": { 439 | "version": "5.1.12", 440 | "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.1.12.tgz", 441 | "integrity": "sha512-nXVCOpvepSk9AfPwqS08rf9NDOCs8eeYYlG+7tE85iP5jVyjz+aYb1BYaP5SPdfVWVrzI9L5NzxozUvKaD96tA==", 442 | "dependencies": { 443 | "pretty-format": "^3.8.0" 444 | }, 445 | "peerDependencies": { 446 | "preact": ">=10" 447 | } 448 | }, 449 | "node_modules/pretty-format": { 450 | "version": "3.8.0", 451 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", 452 | "integrity": "sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=" 453 | }, 454 | "node_modules/qs": { 455 | "version": "6.9.4", 456 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", 457 | "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", 458 | "dev": true, 459 | "engines": { 460 | "node": ">=0.6" 461 | }, 462 | "funding": { 463 | "url": "https://github.com/sponsors/ljharb" 464 | } 465 | }, 466 | "node_modules/react": { 467 | "version": "17.0.1", 468 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", 469 | "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", 470 | "dev": true, 471 | "dependencies": { 472 | "loose-envify": "^1.1.0", 473 | "object-assign": "^4.1.1" 474 | }, 475 | "engines": { 476 | "node": ">=0.10.0" 477 | } 478 | }, 479 | "node_modules/react-dom": { 480 | "version": "17.0.1", 481 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", 482 | "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", 483 | "dev": true, 484 | "dependencies": { 485 | "loose-envify": "^1.1.0", 486 | "object-assign": "^4.1.1", 487 | "scheduler": "^0.20.1" 488 | }, 489 | "peerDependencies": { 490 | "react": "17.0.1" 491 | } 492 | }, 493 | "node_modules/require-directory": { 494 | "version": "2.1.1", 495 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 496 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 497 | "dev": true, 498 | "engines": { 499 | "node": ">=0.10.0" 500 | } 501 | }, 502 | "node_modules/requires-port": { 503 | "version": "1.0.0", 504 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 505 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 506 | "dev": true 507 | }, 508 | "node_modules/rimraf": { 509 | "version": "3.0.2", 510 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 511 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 512 | "dev": true, 513 | "dependencies": { 514 | "glob": "^7.1.3" 515 | }, 516 | "bin": { 517 | "rimraf": "bin.js" 518 | }, 519 | "funding": { 520 | "url": "https://github.com/sponsors/isaacs" 521 | } 522 | }, 523 | "node_modules/scheduler": { 524 | "version": "0.20.1", 525 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz", 526 | "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==", 527 | "dev": true, 528 | "dependencies": { 529 | "loose-envify": "^1.1.0", 530 | "object-assign": "^4.1.1" 531 | } 532 | }, 533 | "node_modules/secure-compare": { 534 | "version": "3.0.1", 535 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 536 | "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", 537 | "dev": true 538 | }, 539 | "node_modules/string-width": { 540 | "version": "4.2.0", 541 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 542 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 543 | "dev": true, 544 | "dependencies": { 545 | "emoji-regex": "^8.0.0", 546 | "is-fullwidth-code-point": "^3.0.0", 547 | "strip-ansi": "^6.0.0" 548 | }, 549 | "engines": { 550 | "node": ">=8" 551 | } 552 | }, 553 | "node_modules/strip-ansi": { 554 | "version": "6.0.0", 555 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 556 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 557 | "dev": true, 558 | "dependencies": { 559 | "ansi-regex": "^5.0.0" 560 | }, 561 | "engines": { 562 | "node": ">=8" 563 | } 564 | }, 565 | "node_modules/union": { 566 | "version": "0.5.0", 567 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 568 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 569 | "dev": true, 570 | "dependencies": { 571 | "qs": "^6.4.0" 572 | }, 573 | "engines": { 574 | "node": ">= 0.8.0" 575 | } 576 | }, 577 | "node_modules/url-join": { 578 | "version": "2.0.5", 579 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 580 | "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", 581 | "dev": true 582 | }, 583 | "node_modules/wrap-ansi": { 584 | "version": "7.0.0", 585 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 586 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 587 | "dev": true, 588 | "dependencies": { 589 | "ansi-styles": "^4.0.0", 590 | "string-width": "^4.1.0", 591 | "strip-ansi": "^6.0.0" 592 | }, 593 | "engines": { 594 | "node": ">=10" 595 | }, 596 | "funding": { 597 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 598 | } 599 | }, 600 | "node_modules/wrappy": { 601 | "version": "1.0.2", 602 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 603 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 604 | "dev": true 605 | }, 606 | "node_modules/y18n": { 607 | "version": "5.0.5", 608 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", 609 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", 610 | "dev": true, 611 | "engines": { 612 | "node": ">=10" 613 | } 614 | }, 615 | "node_modules/yargs": { 616 | "version": "16.1.1", 617 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz", 618 | "integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==", 619 | "dev": true, 620 | "dependencies": { 621 | "cliui": "^7.0.2", 622 | "escalade": "^3.1.1", 623 | "get-caller-file": "^2.0.5", 624 | "require-directory": "^2.1.1", 625 | "string-width": "^4.2.0", 626 | "y18n": "^5.0.5", 627 | "yargs-parser": "^20.2.2" 628 | }, 629 | "engines": { 630 | "node": ">=10" 631 | } 632 | }, 633 | "node_modules/yargs-parser": { 634 | "version": "20.2.4", 635 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 636 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 637 | "dev": true, 638 | "engines": { 639 | "node": ">=10" 640 | } 641 | } 642 | }, 643 | "dependencies": { 644 | "ansi-regex": { 645 | "version": "5.0.0", 646 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 647 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 648 | "dev": true 649 | }, 650 | "ansi-styles": { 651 | "version": "4.3.0", 652 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 653 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 654 | "dev": true, 655 | "requires": { 656 | "color-convert": "^2.0.1" 657 | } 658 | }, 659 | "async": { 660 | "version": "2.6.3", 661 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", 662 | "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", 663 | "dev": true, 664 | "requires": { 665 | "lodash": "^4.17.14" 666 | } 667 | }, 668 | "balanced-match": { 669 | "version": "1.0.0", 670 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 671 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 672 | "dev": true 673 | }, 674 | "basic-auth": { 675 | "version": "1.1.0", 676 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 677 | "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", 678 | "dev": true 679 | }, 680 | "brace-expansion": { 681 | "version": "1.1.11", 682 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 683 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 684 | "dev": true, 685 | "requires": { 686 | "balanced-match": "^1.0.0", 687 | "concat-map": "0.0.1" 688 | } 689 | }, 690 | "cliui": { 691 | "version": "7.0.4", 692 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 693 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 694 | "dev": true, 695 | "requires": { 696 | "string-width": "^4.2.0", 697 | "strip-ansi": "^6.0.0", 698 | "wrap-ansi": "^7.0.0" 699 | } 700 | }, 701 | "color-convert": { 702 | "version": "2.0.1", 703 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 704 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 705 | "dev": true, 706 | "requires": { 707 | "color-name": "~1.1.4" 708 | } 709 | }, 710 | "color-name": { 711 | "version": "1.1.4", 712 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 713 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 714 | "dev": true 715 | }, 716 | "colors": { 717 | "version": "1.4.0", 718 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 719 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 720 | "dev": true 721 | }, 722 | "concat-map": { 723 | "version": "0.0.1", 724 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 725 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 726 | "dev": true 727 | }, 728 | "corser": { 729 | "version": "2.0.1", 730 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 731 | "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", 732 | "dev": true 733 | }, 734 | "debug": { 735 | "version": "3.2.7", 736 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 737 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 738 | "dev": true, 739 | "requires": { 740 | "ms": "^2.1.1" 741 | } 742 | }, 743 | "ecstatic": { 744 | "version": "3.3.2", 745 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 746 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 747 | "dev": true, 748 | "requires": { 749 | "he": "^1.1.1", 750 | "mime": "^1.6.0", 751 | "minimist": "^1.1.0", 752 | "url-join": "^2.0.5" 753 | } 754 | }, 755 | "emoji-regex": { 756 | "version": "8.0.0", 757 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 758 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 759 | "dev": true 760 | }, 761 | "escalade": { 762 | "version": "3.1.1", 763 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 764 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 765 | "dev": true 766 | }, 767 | "eventemitter3": { 768 | "version": "4.0.7", 769 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 770 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 771 | "dev": true 772 | }, 773 | "follow-redirects": { 774 | "version": "1.13.0", 775 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", 776 | "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", 777 | "dev": true 778 | }, 779 | "fs.realpath": { 780 | "version": "1.0.0", 781 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 782 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 783 | "dev": true 784 | }, 785 | "get-caller-file": { 786 | "version": "2.0.5", 787 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 788 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 789 | "dev": true 790 | }, 791 | "glob": { 792 | "version": "7.1.6", 793 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 794 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 795 | "dev": true, 796 | "requires": { 797 | "fs.realpath": "^1.0.0", 798 | "inflight": "^1.0.4", 799 | "inherits": "2", 800 | "minimatch": "^3.0.4", 801 | "once": "^1.3.0", 802 | "path-is-absolute": "^1.0.0" 803 | } 804 | }, 805 | "he": { 806 | "version": "1.2.0", 807 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 808 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 809 | "dev": true 810 | }, 811 | "htm": { 812 | "version": "3.0.4", 813 | "resolved": "https://registry.npmjs.org/htm/-/htm-3.0.4.tgz", 814 | "integrity": "sha512-VRdvxX3tmrXuT/Ovt59NMp/ORMFi4bceFMDjos1PV4E0mV+5votuID8R60egR9A4U8nLt238R/snlJGz3UYiTQ==" 815 | }, 816 | "http-proxy": { 817 | "version": "1.18.1", 818 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 819 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 820 | "dev": true, 821 | "requires": { 822 | "eventemitter3": "^4.0.0", 823 | "follow-redirects": "^1.0.0", 824 | "requires-port": "^1.0.0" 825 | } 826 | }, 827 | "http-server": { 828 | "version": "0.12.3", 829 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", 830 | "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", 831 | "dev": true, 832 | "requires": { 833 | "basic-auth": "^1.0.3", 834 | "colors": "^1.4.0", 835 | "corser": "^2.0.1", 836 | "ecstatic": "^3.3.2", 837 | "http-proxy": "^1.18.0", 838 | "minimist": "^1.2.5", 839 | "opener": "^1.5.1", 840 | "portfinder": "^1.0.25", 841 | "secure-compare": "3.0.1", 842 | "union": "~0.5.0" 843 | } 844 | }, 845 | "inflight": { 846 | "version": "1.0.6", 847 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 848 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 849 | "dev": true, 850 | "requires": { 851 | "once": "^1.3.0", 852 | "wrappy": "1" 853 | } 854 | }, 855 | "inherits": { 856 | "version": "2.0.4", 857 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 858 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 859 | "dev": true 860 | }, 861 | "is-fullwidth-code-point": { 862 | "version": "3.0.0", 863 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 864 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 865 | "dev": true 866 | }, 867 | "js-tokens": { 868 | "version": "4.0.0", 869 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 870 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 871 | "dev": true 872 | }, 873 | "lodash": { 874 | "version": "4.17.20", 875 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 876 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 877 | "dev": true 878 | }, 879 | "loose-envify": { 880 | "version": "1.4.0", 881 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 882 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 883 | "dev": true, 884 | "requires": { 885 | "js-tokens": "^3.0.0 || ^4.0.0" 886 | } 887 | }, 888 | "mime": { 889 | "version": "1.6.0", 890 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 891 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 892 | "dev": true 893 | }, 894 | "minimatch": { 895 | "version": "3.0.4", 896 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 897 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 898 | "dev": true, 899 | "requires": { 900 | "brace-expansion": "^1.1.7" 901 | } 902 | }, 903 | "minimist": { 904 | "version": "1.2.5", 905 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 906 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 907 | "dev": true 908 | }, 909 | "mkdirp": { 910 | "version": "0.5.5", 911 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 912 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 913 | "dev": true, 914 | "requires": { 915 | "minimist": "^1.2.5" 916 | } 917 | }, 918 | "ms": { 919 | "version": "2.1.2", 920 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 921 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 922 | "dev": true 923 | }, 924 | "object-assign": { 925 | "version": "4.1.1", 926 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 927 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 928 | "dev": true 929 | }, 930 | "once": { 931 | "version": "1.4.0", 932 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 933 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 934 | "dev": true, 935 | "requires": { 936 | "wrappy": "1" 937 | } 938 | }, 939 | "opener": { 940 | "version": "1.5.2", 941 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 942 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 943 | "dev": true 944 | }, 945 | "path-is-absolute": { 946 | "version": "1.0.1", 947 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 948 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 949 | "dev": true 950 | }, 951 | "portfinder": { 952 | "version": "1.0.28", 953 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", 954 | "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", 955 | "dev": true, 956 | "requires": { 957 | "async": "^2.6.2", 958 | "debug": "^3.1.1", 959 | "mkdirp": "^0.5.5" 960 | } 961 | }, 962 | "preact": { 963 | "version": "10.5.7", 964 | "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.7.tgz", 965 | "integrity": "sha512-4oEpz75t/0UNcwmcsjk+BIcDdk68oao+7kxcpc1hQPNs2Oo3ZL9xFz8UBf350mxk/VEdD41L5b4l2dE3Ug3RYg==" 966 | }, 967 | "preact-render-to-string": { 968 | "version": "5.1.12", 969 | "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.1.12.tgz", 970 | "integrity": "sha512-nXVCOpvepSk9AfPwqS08rf9NDOCs8eeYYlG+7tE85iP5jVyjz+aYb1BYaP5SPdfVWVrzI9L5NzxozUvKaD96tA==", 971 | "requires": { 972 | "pretty-format": "^3.8.0" 973 | } 974 | }, 975 | "pretty-format": { 976 | "version": "3.8.0", 977 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", 978 | "integrity": "sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=" 979 | }, 980 | "qs": { 981 | "version": "6.9.4", 982 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", 983 | "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", 984 | "dev": true 985 | }, 986 | "react": { 987 | "version": "17.0.1", 988 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", 989 | "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", 990 | "dev": true, 991 | "requires": { 992 | "loose-envify": "^1.1.0", 993 | "object-assign": "^4.1.1" 994 | } 995 | }, 996 | "react-dom": { 997 | "version": "17.0.1", 998 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", 999 | "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", 1000 | "dev": true, 1001 | "requires": { 1002 | "loose-envify": "^1.1.0", 1003 | "object-assign": "^4.1.1", 1004 | "scheduler": "^0.20.1" 1005 | } 1006 | }, 1007 | "require-directory": { 1008 | "version": "2.1.1", 1009 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1010 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1011 | "dev": true 1012 | }, 1013 | "requires-port": { 1014 | "version": "1.0.0", 1015 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 1016 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 1017 | "dev": true 1018 | }, 1019 | "rimraf": { 1020 | "version": "3.0.2", 1021 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1022 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1023 | "dev": true, 1024 | "requires": { 1025 | "glob": "^7.1.3" 1026 | } 1027 | }, 1028 | "scheduler": { 1029 | "version": "0.20.1", 1030 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz", 1031 | "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==", 1032 | "dev": true, 1033 | "requires": { 1034 | "loose-envify": "^1.1.0", 1035 | "object-assign": "^4.1.1" 1036 | } 1037 | }, 1038 | "secure-compare": { 1039 | "version": "3.0.1", 1040 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 1041 | "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", 1042 | "dev": true 1043 | }, 1044 | "string-width": { 1045 | "version": "4.2.0", 1046 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 1047 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 1048 | "dev": true, 1049 | "requires": { 1050 | "emoji-regex": "^8.0.0", 1051 | "is-fullwidth-code-point": "^3.0.0", 1052 | "strip-ansi": "^6.0.0" 1053 | } 1054 | }, 1055 | "strip-ansi": { 1056 | "version": "6.0.0", 1057 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1058 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1059 | "dev": true, 1060 | "requires": { 1061 | "ansi-regex": "^5.0.0" 1062 | } 1063 | }, 1064 | "union": { 1065 | "version": "0.5.0", 1066 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 1067 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 1068 | "dev": true, 1069 | "requires": { 1070 | "qs": "^6.4.0" 1071 | } 1072 | }, 1073 | "url-join": { 1074 | "version": "2.0.5", 1075 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 1076 | "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", 1077 | "dev": true 1078 | }, 1079 | "wrap-ansi": { 1080 | "version": "7.0.0", 1081 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1082 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1083 | "dev": true, 1084 | "requires": { 1085 | "ansi-styles": "^4.0.0", 1086 | "string-width": "^4.1.0", 1087 | "strip-ansi": "^6.0.0" 1088 | } 1089 | }, 1090 | "wrappy": { 1091 | "version": "1.0.2", 1092 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1093 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1094 | "dev": true 1095 | }, 1096 | "y18n": { 1097 | "version": "5.0.5", 1098 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", 1099 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", 1100 | "dev": true 1101 | }, 1102 | "yargs": { 1103 | "version": "16.1.1", 1104 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz", 1105 | "integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==", 1106 | "dev": true, 1107 | "requires": { 1108 | "cliui": "^7.0.2", 1109 | "escalade": "^3.1.1", 1110 | "get-caller-file": "^2.0.5", 1111 | "require-directory": "^2.1.1", 1112 | "string-width": "^4.2.0", 1113 | "y18n": "^5.0.5", 1114 | "yargs-parser": "^20.2.2" 1115 | } 1116 | }, 1117 | "yargs-parser": { 1118 | "version": "20.2.4", 1119 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1120 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1121 | "dev": true 1122 | } 1123 | } 1124 | } 1125 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ssg", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "render:preact": "node renderers/htm-preact-renderer.js -t templates/preact/ -o output/preact/", 9 | "render:react": "node renderers/htm-react-renderer.js -t templates/react/ -o output/react/", 10 | "serve:preact": "http-server -c-1 . -o output/preact/home.preact.html", 11 | "clean": "rimraf output", 12 | "rebuild": "rimraf output && node renderers/htm-react-renderer.js -t templates/react/ -o output/react/", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "htm": "^3.0.4", 19 | "preact": "^10.5.7", 20 | "preact-render-to-string": "^5.1.12" 21 | }, 22 | "devDependencies": { 23 | "http-server": "^0.12.3", 24 | "react": "^17.0.1", 25 | "react-dom": "^17.0.1", 26 | "rimraf": "^3.0.2", 27 | "yargs": "^16.1.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | React-SSG 2 | ========= 3 | 4 | NextJS and Gatsby can be overkill, this is simple 20-line example of doing react static-site generation using [htm](https://github.com/developit/htm) instead of transpilation. 5 | 6 | ## How to use: 7 | 8 | Included are two flavors, react and preact. While both are included, if you use this as a base you'll probably only want to use one (and I'd recommend Preact because it's much smaller). 9 | 10 | ``` 11 | node renderers/htm-react-renderer.js 12 | ``` 13 | or 14 | ``` 15 | node renderers/htm-preact-renderer.js 16 | ``` 17 | 18 | | Option | Description | Default | 19 | |--------|-------------|---------| 20 | | `-o` | output directory name | "./output/" | 21 | | `-t` | template directory name | "./templates/" | 22 | 23 | Files are exported using the same name to the output folder. Files with preceeding `_` are partials and will not be exported. You can use these for layouts and such. Path for folders must end with `/`. 24 | 25 | This is designed to be an example you build on, it should be easy to hook up other CLI tools to render other assets. 26 | -------------------------------------------------------------------------------- /renderers/htm-preact-renderer.js: -------------------------------------------------------------------------------- 1 | import { promises as fs } from "fs"; 2 | import { fileURLToPath, pathToFileURL } from "url"; 3 | import yargs from "yargs"; 4 | import render from "preact-render-to-string"; 5 | import { getScripts } from "../templates/preact/components/_script-manager.js"; 6 | 7 | import { ensure, readJson } from "../utilities/utils.js"; 8 | 9 | const args = yargs(process.argv.slice(2)).argv; 10 | const templatesUrl = pathToFileURL(`${process.cwd()}/${args.t ?? "./templates/"}`); 11 | const outputUrl = pathToFileURL(`${process.cwd()}/${args.o ?? "./output/"}`); 12 | 13 | const files = await fs.readdir(fileURLToPath(templatesUrl)); 14 | await ensure(fileURLToPath(outputUrl)); 15 | 16 | const importMap = await readJson("./importmap.json"); 17 | const patchScript = src => src.replace(/(?<=\s*import(.*?)from\s*\")[^\.\/](.*?)(?=\")/g, v => importMap.imports[v] ?? `Bare import ${v} not found`); 18 | async function emitScript(path, base){ 19 | const outputPath = fileURLToPath(new URL(path, outputUrl)); 20 | await ensure(outputPath) 21 | const src = await patchScript(await fs.readFile(fileURLToPath(new URL(path, base)), "utf-8")); 22 | await fs.writeFile(fileURLToPath(new URL(path, outputUrl)), src); 23 | } 24 | 25 | for (const file of files) { 26 | if (/^_/.test(file) || !/\.js$/.test(file)) continue; 27 | const outfile = new URL(file.replace(/\.js$/, ".html"), outputUrl); 28 | const path = new URL(file, templatesUrl); 29 | const { title: pageTitle, body: pageBody, layout: pageLayout } = await import(path); 30 | const body = typeof (pageBody) === "function" ? await pageBody() : pageBody; 31 | const { layout } = await import(new URL(pageLayout ?? "_layout.js", templatesUrl)); 32 | const output = render(layout({ title: pageTitle, body })); 33 | await fs.writeFile(fileURLToPath(outfile), output); 34 | } 35 | //export scripts in use 36 | const scripts = getScripts(); 37 | for(const script of scripts){ 38 | await emitScript(script, templatesUrl); 39 | } 40 | const preactScripts = ["./node_modules/preact/dist/preact.mjs", "./node_modules/preact/hooks/dist/hooks.mjs", "./node_modules/htm/preact/index.mjs", "./node_modules/htm/dist/htm.mjs"]; 41 | for(const script of preactScripts){ 42 | await emitScript(script, pathToFileURL(process.cwd() + "/")); 43 | }; -------------------------------------------------------------------------------- /renderers/htm-react-renderer.js: -------------------------------------------------------------------------------- 1 | import { promises as fs } from "fs"; 2 | import ReactDOM from "react-dom/cjs/react-dom-server.node.production.min.js"; 3 | import { fileURLToPath, pathToFileURL } from "url"; 4 | import yargs from "yargs"; 5 | 6 | import { ensure } from "../utilities/utils.js"; 7 | 8 | const args = yargs(process.argv.slice(2)).argv; 9 | const templatesUrl = pathToFileURL(`${process.cwd()}/${args.t ?? "./templates/"}`); 10 | const outputUrl = pathToFileURL(`${process.cwd()}/${args.o ?? "./output/"}`); 11 | 12 | const files = await fs.readdir(fileURLToPath(templatesUrl)); 13 | await ensure(fileURLToPath(outputUrl)); 14 | 15 | for (const file of files){ 16 | if (/^_/.test(file)) continue; 17 | const outfile = new URL(file.replace(/\.js$/, ".html"), outputUrl); 18 | const path = new URL(file, templatesUrl); 19 | const { title: pageTitle, body: pageBody, layout: pageLayout } = await import(path); 20 | const body = typeof (pageBody) === "function" ? await pageBody() : pageBody; 21 | const { layout } = await import(new URL(pageLayout ?? "_layout.js", templatesUrl)); 22 | const output = ReactDOM.renderToString(layout({ title: pageTitle, body })); 23 | await fs.writeFile(fileURLToPath(outfile), output); 24 | } -------------------------------------------------------------------------------- /templates/preact/_layout.preact.js: -------------------------------------------------------------------------------- 1 | import { html } from "htm/preact/index.mjs"; 2 | import { HydrationData } from "./components/_hydrator.js"; 3 | import { Script } from "./components/_script.js"; 4 | 5 | export const layout = data => html` 6 | 7 | 8 | ${data.title} 9 | 10 | 11 | ${data.body} 12 | <${HydrationData} /> 13 | <${Script} src="./components/_init-hydrate.js" /> 14 | 15 | 16 | `; -------------------------------------------------------------------------------- /templates/preact/components/_counter.preact.js: -------------------------------------------------------------------------------- 1 | import { useState } from "preact/hooks/dist/hooks.mjs"; 2 | import { html } from "htm/preact/index.mjs"; 3 | 4 | export const Counter = ({ title }) => { 5 | 6 | const [value, setValue] = useState(0); 7 | 8 | function increment(){ 9 | setValue(value + 1); 10 | } 11 | 12 | function decrement(){ 13 | setValue(value - 1); 14 | } 15 | 16 | return html` 17 |
18 |

${title}

19 |
${value}
20 | 21 | 22 |
23 | `; 24 | }; -------------------------------------------------------------------------------- /templates/preact/components/_hydrator.js: -------------------------------------------------------------------------------- 1 | import { html } from "htm/preact/index.mjs"; 2 | import { addScript } from "./_script-manager.js"; 3 | 4 | const hydrationData = {}; 5 | const componentPaths = {}; 6 | 7 | let id = 0; 8 | 9 | export function WithHydration(Component, path){ 10 | return props => html` 11 | <> 12 | ` 7 | } -------------------------------------------------------------------------------- /templates/preact/home.preact.js: -------------------------------------------------------------------------------- 1 | import { html } from "htm/preact/index.mjs"; 2 | import { Counter } from "./components/_counter.preact.js"; 3 | import { WithHydration, HydrationData } from "./components/_hydrator.js"; 4 | 5 | export const title = "Home Preact"; 6 | export const layout = "_layout.preact.js" 7 | 8 | const Header = ({ text }) => html`

${text}

` 9 | 10 | export const body = html` 11 |
12 | <${Header} text="Hello World!"> 13 |

A simple SSG Site with Preact

14 | <${WithHydration(Counter, "./components/_counter.preact.js")} title="counter" /> 15 |
16 | `; -------------------------------------------------------------------------------- /templates/react/_layout.react.js: -------------------------------------------------------------------------------- 1 | import { html } from "htm/react/index.mjs"; 2 | 3 | export const layout = data => html` 4 | 5 | 6 | ${data.title} 7 | 8 | 9 | ${data.body} 10 | 11 | 12 | `; -------------------------------------------------------------------------------- /templates/react/home.react.js: -------------------------------------------------------------------------------- 1 | import { html } from "htm/react/index.mjs"; 2 | 3 | export const title = "Home React"; 4 | export const layout = "_layout.react.js" 5 | 6 | const Header = ({ text }) => html`

${text}

` 7 | 8 | export const body = html` 9 |
10 | <${Header} text="Hello World!"> 11 |

A simple SSG Site with React

12 |
13 | `; -------------------------------------------------------------------------------- /utilities/utils.js: -------------------------------------------------------------------------------- 1 | import { join } from "path"; 2 | import { promises as fs } from "fs"; 3 | 4 | export function getRootUrl(){ 5 | return new URL("../", import.meta.url); 6 | } 7 | 8 | export const exists = path => 9 | fs.access(path).then(() => true).catch(() => false); 10 | 11 | export async function ensure(path) { 12 | const pathSplit = path.split(/[/\\]/); 13 | let currentPath = pathSplit[0]; 14 | for await (let part of pathSplit.slice(1, pathSplit.length - 1)) { 15 | if(!part.trim()) continue; 16 | currentPath = join(currentPath, part); 17 | if (!await exists(currentPath)) { 18 | await fs.mkdir(currentPath); 19 | } 20 | } 21 | } 22 | 23 | export async function readJson(path) { 24 | const content = await fs.readFile(path, "utf-8"); 25 | return JSON.parse(content); 26 | } --------------------------------------------------------------------------------