{"_id":"5sg","_rev":"7-50cac2ad081dee27508ac356657a0b09","name":"5sg","dist-tags":{"latest":"0.0.8"},"versions":{"0.0.2":{"name":"5sg","version":"0.0.2","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.2","dist":{"shasum":"71d41e042ee5e17bcd9e0981bc8a2f55b6cd309b","integrity":"sha512-pLqL6la/CyOAEdXb52chGwbmmbxVL8pHCvzwbt1O5j5WvQcY7JPbh44oGhnsDzwBXwJ6k8oam0lFZUAYPboWyA==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.2.tgz","fileCount":34,"unpackedSize":72605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsQ+ZCRA9TVsSAnZWagAA6VYQAINzL6LUH0shsBAgQByJ\neKeIW3LHf8DsgZFFwCypAcWwNeznDMfLroyDsakelJ8mPt/Tz2zRAZFH2Sai\nIrVn33RRDDZk8srTyly9zDVxAwNpGfTiGEplKsPD0IT+vR4b6X0aRQWYID6y\noohVMLymy4N4ccU1Irnit+qJG3VkuZlnRFm30/14yYaKyQXo6/ouKCO+MO02\nhFNZ362Rxgi1mFYmpEqAZAZtw6qcpeIdFtb9rkYh6Vbr+nC0xOrbB2QM1JU5\n3XpKdgeOx0Gny5Al3v/i9j8V+3ZHe59UCpiJRozfZRGstuUeO5SHeEljA29z\nSv+7dYBArETabbaUgEQaj3auYaxWYw88JH0IawLIotG4txwCAW5kEmQ85XhV\nHzApaH0O0K8wlz+4TGhPDYGmfDYrGQTMbTbN/PlZoy/L5s1FJXm7fV0tqsSK\nBNVJKl8T3N2vowopvrJZEDLKpXCmLVFPH1+4PwkymSmdqS7LkT5gwctOYWHX\nfK81PlNZtB9aCoN1NNFsbkXDkmDW+UuQJUnUYPXV/N/PZrB5qheJcqT0uzav\nn7sY0xhgSlP4lTiY5BhzWE/+iMDqauMAjy6EfAS1n8a1b0fzueougqtes7CP\nxeq5pe8+JHPC597BgPc5m4xW7lXSx8Kq+ZMbPzszpQmvp1GN/2VC9pIj9Mwm\n75uT\r\n=PGuT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEBr+9iWy/UukXRHDsSKU4euiJuBpRhebMPquQcNI4w0AiAKyhRbBlvpQr0Md6tyy/BZvyAjuO41lymLXzeH4MhEFg=="}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.2_1622216601292_0.9312947128389404"},"_hasShrinkwrap":false},"0.0.3":{"name":"5sg","version":"0.0.3","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.3","dist":{"shasum":"57e5f5a76668e1e211909c0906ea95397820c139","integrity":"sha512-N7yUtFyrEjmLChGAok7Y3jHcd/yKF8sOM+qU3EClU4uuBQ8j+z5MUiMHiUCobENOk9fHDHvNUXZ0L2i2OroUfA==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.3.tgz","fileCount":34,"unpackedSize":72605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsRCICRA9TVsSAnZWagAAZUcP/RBbKsJm4l9vvpW5BHFp\nunM6+25Dim4FNfF6VsaKU6qPb4v+c/aFDZ4dGMlN9xVFj5a0K/sC2Rz9sLF9\nK+pIft1DFnaCUFyLJyQx5S6PNLZsco40NXwv2sfL+sxSEwYMMozGP8jVc5mQ\nJNXJU6uLjHSz2oRKh1HpnSmwNuOuofkbZDCe3auhE9JUoE0TvrJGtWWllduC\nx8d0aRVFpPVJ4ZONVReaTwQ8YOvY0UCisxi9dmdKKqHcjJduQh2NwrVm+lSI\n5vrFRw+qFeoIur/+1c5LG/Ry2h+6X9Vv+ak0pm70GKyRbePRQIcpCr+4LM2D\n99p2tAGA0ng5teN+JpqV8cNKL4VttnImCG/x7NoJCEhVozkXwM1LOCkznAbv\nEhRvqFoy2SYNdZc6M2Wd/2CXh1VJC3QNmV/1EJMoxwn3c44UzIbpdYmZW8wa\nspnboSg0/QXol493EE/uU6Kh1TF+1TAalL28S6zvLWyCK8B3oQXPOECNc9x+\nLqZx9wIVGFWaSLNCzODA7mQ2X+64ZM45RCjaMWdSbRakyt3bgkwM1SXvTve5\nqRhz3K+o9CpQN3lNmoxlsXXfmD/oRCToXH8VMAdGZaPc8xdLXTImATfz6f1e\nrxuFUBFRueL7FqQARu9BukmOgtxUUPW86Px+AEHNB8dm5diSsgIwar2bwk3t\n2MMu\r\n=Zq4L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCW+hNuta5EkyER/F6WibFuvHT65shzStLMuVaPF3iQEAIhALuLoXYcrTZLbnn+lepVg99A6wuwTTqqiOsEt4Jjlc0c"}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.3_1622216839818_0.5866039036074466"},"_hasShrinkwrap":false},"0.0.4":{"name":"5sg","version":"0.0.4","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.4","dist":{"shasum":"e871d1c09371615712724da4882603703417d673","integrity":"sha512-Pu2LqGgr5T/qCr9bRfmcvxfuK0ZBYf6W7HNdtNEZe9fXY8F4rC/7mfAEWX+uneyaX2gXUF9pGM6412tbFwBADA==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.4.tgz","fileCount":34,"unpackedSize":72603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsRegCRA9TVsSAnZWagAA8AcP/24dXu1T9cmcCazjicBu\nB+l03TlW4lKMnhzXm7YoeGt95ERdf8oi0Rnl+k6Qc5xsVBWX3QQjwoi5LN3+\nxOkg/GANP/B0ua7gdG6vlcuVROf/ff+nxsGuO0o2qC1e+GEXpGLHVxMPZrrg\nJJw9Z+TZ9qlMaC+e1ZN66T5eldWeFEELJgu+CsbpyFKO9eLV+6DaGQM4/hRU\nJhEzikZP3dXcKvTm+1+FJ491MYlFuQYPT60+wpQpa/hLTUSWBhzAteVUP8QT\nIbS0I/SOOAvvNAqlF62K2DiqKrJ5nLDoSIFOvA7M/Z/SeVy6Y0as3QM8cr5b\nFYsgoFpd0WUi+PJhrIuVlNsz81cyyLwNofPYnKF/NW2JsOmzwK/LkqJpK3QU\nBhfWmq88CThZHahnk1U+XVR5J/Z/w9eFqcCpj4U8JiAgO/xlBkOBg+OjvIea\nUBl51ellbSEkV0C79cSBELns3HDOyIbDcrEV1Qgz0HAv8NdTSC1LGhx0nlFs\nX2t0kiF8hVbr7RTmwP9x5jJG7b/JjQbHNCjKweUa8ljnsBi5IZ2xdL+5COrf\n2o7CT3b+9sgsWbtpEmIs2nHaGRJX4a1NO93hfjosvttCzFpZN83QrRBA4JSV\nHY8s5U7pdLBIxYJ+U6JdFW/3gNqLg3fmHctqYAwpqxzBjqtm9FoazKDZYhov\n+5H8\r\n=TMyY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmhghknwA5ORlOW1USFLzOJAIvjnwveVdEDF5Xf9LQ4gIhAJBznvigISWsBvyUwV9jzqgVJT1RCk5Joz9JmqNi/7Ii"}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.4_1622218656172_0.2743841848067805"},"_hasShrinkwrap":false},"0.0.5":{"name":"5sg","version":"0.0.5","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.5","dist":{"shasum":"a27d4ec3ae010ea3d9d5c8473926d53473a0f63d","integrity":"sha512-iNPcpvSpSwmEiJQ8j2fbs9KiwlHTSLEDPTVTkdM0hK42W+PShOXRIDPcmou01d3PKwM828ns3jbjEIZfHGb31Q==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.5.tgz","fileCount":34,"unpackedSize":73152,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsRvCCRA9TVsSAnZWagAAZ+AP/RzwOlMB0vDLQ8c1iU36\nB5OjVNDj8IPClq2ZZbWZEqmCw99JUwkVli66GL1tL9Ms9eRx8KoyQtHCmnCF\nfxejjclaTmQJlC6sFAQX4io0iGTJHiDBdhNUfZCQCkVkcgiTHQkGN/bWIxlB\n8/oFl6QDB2Kz2Ytz86sow1Iiq60nKwSJS9ebe03sbulWynUnBrgA//G6wte3\ny9v6th1SvsREHrimeRx0xo49GKjxVRxSCanGB/OncHNyq6xWSBymaos7qnKS\nn0IAWw3fyFyYYZBo/eKd55oXvJ7nCiKnwG+jdyjp/87OBRTt5GMAa7bH95BL\nLxSI9KZJfP8amntV7KCkSZ1efJmzfzCHCK3kZ0dbkzQlsYRmi9ZPxTNICx4d\n0IWAvxK6m16tjgNdOb/EndwT5ITMS7kZN99K89JtIOXFA3kWmM+6ggs2G/Wf\n/PB5Q+GFozybaEiTYwqVxpIfZwivJd4XymfKQpL/kfDdF1gBWBvwTQHkUb+0\n6jZEk9Dq1XGUWrAk6+S5dL3C9+cEcBhH4x3s0zbpfl1fZiLm+Hfspn+Rdiqi\nKKa7mY69WCsJzbEfLc++CeIwWt8ZzZZF0PEnJBFE/b+stME01ER9wFk31PYU\nMkPHMyspLqfslzNoxNchQWDwc14WivzIjuJv5HatvWrISzBGKSFhiptxHzD+\nKITm\r\n=RIZb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFg6ow7jAMIL66uOMTCJ2UC8beWCl8CeLK8E5U/BLaiZAiEA8WorXevewLecGvUUpIMRi/+e7X2/gOG5RbggS3uRy1I="}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.5_1622219713535_0.9464920744366621"},"_hasShrinkwrap":false},"0.0.6":{"name":"5sg","version":"0.0.6","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.6","dist":{"shasum":"e101b1b1c935b2d6f1f979d0a5d77a25e0a5a625","integrity":"sha512-9xikQsNQfWSk7jgLS3G0QbZVm+ACqXw1rFEF99kbIrh7a3Mw+9+7KmfGJi7bbERNXSDrqfEVc0hKVz/M5SIs4Q==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.6.tgz","fileCount":34,"unpackedSize":79852,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtKQrCRA9TVsSAnZWagAA268P/jk2jzw5aa87dAwxUvYQ\n93WiBkNTds112oIr7ob9VTJUHD4KOrcim8FmNcqmeZDPsJYB+XOqABVtxuBI\n5HgrEgsunRiiAuQIXzq2CtB4DgXVLYwjt/hDe43gugq2DhyMnzBkwbsmXj3v\n2i0bq/b02HLPuFCIwTySu1j7/F1hSYUrliYpMoJCvhArHQGsiQjmR2E1N0n2\n4vIQRvswxiJ8/nuloHmGosNtbSOwhJDanJcZAdRz/evCN1tOZEvTX8V3K6nd\nmAshNvSsYcHwokC229DLRPBr6ReVppcT/JE1FAOIxTgszT04XJu+PHvKS5OM\nG8BeoAjmkjNQPq5gAO3EQk964GmoRb7rn3BbiM0+HPDQi/Au4hW55fc77AYT\nPIwNnNW6wqS/ZROQvTcsBp76xMtloJolW31rcUNm2PmByA8IhI53gDAj5Xjj\nos9XqgsaoKW0yTAB60FJgEaeXE4Vx594Qq14hekQB1kfz3LG3uMN/VS6AFC1\n3fLIFvscFlTQde7bHP3LBmvezAKE8bur74jeICEhCYdSOqVJgJtikhvGyQ4P\nwMvuXDXbK/L3T+SAn3VqAmJQifdj2l61ZlaKB57kSjVaYQQF+FnVsxotN9+m\nhcWRqXMYU3oydFsizlGkKWtM1Amh+AyEc4mPdZMkqQCQZnmKWEGPjzRQwiT1\nzRny\r\n=Ml5b\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC61ocrSBY+bnoSkAh7+HXrR8ORhi0riB8fq/8opzXlAgIhAJ2vRjPwsdH/wrLmX3xpKMs2lpPU585wYE/E5RFRpCJf"}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.6_1622451243261_0.7772203426075723"},"_hasShrinkwrap":false},"0.0.7":{"name":"5sg","version":"0.0.7","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.7","dist":{"shasum":"fa3673b89134081d6ec6e6ac125aade6f5f5ca04","integrity":"sha512-dJ9w69Kxhz4gC/uFxkXXMdCYaCEEonsEvYTZNSr3JwSr3+54UtKhzxn65/Hc0Om/F/ZWlLG2Cs6lgIlCdq6QSA==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.7.tgz","fileCount":34,"unpackedSize":91092,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgukw7CRA9TVsSAnZWagAAAg0QAIC0xetqh/e02uk6pwI8\namJDz4on7+4+d2wiFTc1aGQHPmGat+l91Y3Jzx4hV8CnXMmo3n+phf1wmfAg\n27cDrAM22c4QN1efddSk8uYLwajFviSE0LOlABggLEYSKpdKqFiTypUOeTM5\nsf23cXGpfpXFFSY4RsFWEqffDxK0G6Q4revm32kQo9zZ7fYg87tmu97IfuqF\n4xb8ag5C/wazDR+4eUnr7rUuXcXfZDW05hk6l4vM+Ndg40ggM6tdBkXMagQH\nEqTqcA9JvfBKoPdWgz/szHrYRnSUgvjmflW8uCUTewXl/hVsaW3PlXrbaPdW\nGuNkOkfszUq9dUm9XVpfatfrs99KqUmxwghgDXuqge15DGV+YVzs+ezAqh+2\nObLVAaeTq4yt7oW+hQEsE7oVPtlfT/Rk40jkMP9kJzyQ2PFRUuG9utOUJ297\n4/kXcr+yadsKgnTx4q0PyEJHvNTXTZdUAkIfwng+qx79SPlBc+hXCy3/lWcT\nh8iO7K3PSqHQesfEXBgU7C+e6/5fSIjDAbodxydi+v7ViuzvsILTKmqHfVz/\n+2uWF/rU3uBKrgHeQqEltMNNBgSk38VFC95DwBnapRn6Df7FWONPwjFyfbJf\nJvrYBdG6b+vN0fxVDrSXO71TeXvLvW9PvkT0axOWd0KGndSlHp6a5492cwYo\nP8F1\r\n=2IM5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCGSDp+BkLYeuP4DwqPWjSAWT67VL5CA3GwDQ2xKYQKqgIhAPUbFt3bud+IDAhyIvGOioWlvTYC79bphanDIFch50fs"}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.7_1622821947257_0.9744968851739866"},"_hasShrinkwrap":false},"0.0.8":{"name":"5sg","version":"0.0.8","description":"A stupid simple static site generator for svelte","author":{"name":"Christopher Borchert"},"license":"MIT","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"type":"module","bin":{"5sg":"bin/index.js"},"exports":{"./components":"./lib/components/index.js","./Hydrate":"./lib/components/Hydrate.svelte","./helpers":"./lib/helpers/index.js","./package.json":"./package.json"},"dependencies":{"@rollup/plugin-commonjs":"^19.0.0","@rollup/plugin-node-resolve":"^13.0.0","arg":"^5.0.0","browser-sync":"^2.26.14","chokidar":"^3.5.1","fs-extra":"^10.0.0","lodash":"^4.17.21","module":"^1.2.5","node-html-parser":"^3.3.0","path":"^0.12.7","pino":"^6.11.3","pino-pretty":"^4.8.0","remark":"^13.0.0","remark-footnotes":"^3.0.0","remark-frontmatter":"^3.0.0","remark-gemoji":"^6.0.0","remark-gfm":"^1.0.0","remark-highlight.js":"^6.0.0","remark-html":"^13.0.1","remark-parse-frontmatter":"^1.0.3","rollup":"^2.47.0","rollup-plugin-delete":"^2.0.0","rollup-plugin-multi-input":"^1.2.0","rollup-plugin-svelte":"^7.1.0","sharp":"^0.28.2","svelte":"^3.38.2","url":"^0.11.0"},"devDependencies":{"jsdoc":"^3.6.6","prettier":"^2.2.1","typescript":"^4.1.3"},"_id":"5sg@0.0.8","dist":{"shasum":"81dc938ce4d710a373b8f2501ee083d641a597ab","integrity":"sha512-t1l/PPMzdSVfS58XZtXIh7Webvu9qRZ17JBtqkvchgkGi0pDowimqHz+QeFK8xUXJ/dxphwUGpsfoZj4bXhIJg==","tarball":"https://registry.npmjs.org/5sg/-/5sg-0.0.8.tgz","fileCount":34,"unpackedSize":91429,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgyF05CRA9TVsSAnZWagAA/c0P/jUfp5asRRHwqJAl9XzO\nAUmj/lZtSX0L/enCA93rQIA9nn1LrOXT8fBz2x6d1fc/l729rQHb/5fYT5Gs\n8Lmc8zeuS+h9chpeqtEvvE8PS1J6E3ffmlG/n0mM9lOzx0USZ5U8zEjWwPlP\nWsLePItGFuiz3paGHJKIMdF71JJEpE5nb7LX+Oii/P7kNIexDvXrL/GYfqcf\n/PI5NUhSwtw5KhKfm6qZleskW/lMZA5K1dGi57mZdc2KP/TseMrNzJcskAs9\n+U9/O68KTnBjaSpcMRIoI6Z/J25wk7RU4u8s3i+VDAtJYuvoMKGJgRrYDnPv\n6T51rco8ujLVxXI/5qfn5r6qleXZa8AfkXxB55NF6c5P8k9tfYZFgotpZhoj\nvTL6GPqXCOBkCCKffpWsSUZh7KE3apaC4srb/38BK1Uet/NLU9ZIIOj4V3DH\nxe+P2jwev5twKLywBmEkQYOyqmJYPMycfEM4x5eQsi0Y/FsD4ezoXBFvOBkd\nBrTsSP4ySc0eiTjygOYDq49h4bOSxKCvjJ3D6tsvaSurqvukrBV8K3In9+C/\ncrc/7H2HXJQS4N90exBNdVGLbqC/XfcVr7HYxJm8NPe1pqzOs8Gg6jcQYhCt\nm8AqpL7nCUqlnQvkCcXQuWBy6o+w01xmXVz8nC4yVyKbwKxw5a2jV4+5ezsR\nFGBx\r\n=Fi7I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICBCcDUiHiazCTxAdnn0w35IRb7u9C38/x6sxESCIllWAiAhjxD/UKY6BJc4xOLOtR201elIqUVEcn0n1yTWbONkUg=="}]},"_npmUser":{"name":"cmborchert","email":"christopher.borchert@gmail.com"},"directories":{},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/5sg_0.0.8_1623743800977_0.14533067363254437"},"_hasShrinkwrap":false}},"time":{"created":"2021-05-28T15:43:21.291Z","0.0.2":"2021-05-28T15:43:21.439Z","modified":"2022-04-04T10:23:23.089Z","0.0.3":"2021-05-28T15:47:20.016Z","0.0.4":"2021-05-28T16:17:36.309Z","0.0.5":"2021-05-28T16:35:13.695Z","0.0.6":"2021-05-31T08:54:03.394Z","0.0.7":"2021-06-04T15:52:27.396Z","0.0.8":"2021-06-15T07:56:41.094Z"},"maintainers":[{"name":"cmborchert","email":"christopher.borchert@gmail.com"}],"description":"A stupid simple static site generator for svelte","repository":{"type":"git","url":"https://github.com/cborchert/5sg"},"author":{"name":"Christopher Borchert"},"license":"MIT","readme":"# Stupid Simple Svelte Static Site Generator (5SG)\n\n## Introduction\n\n5sg stands for **s**tupid **s**imple **s**velte **s**tatic **s**ite generator. It's a static site generator (SSG) in the making which focuses on ease of development, simplicity of structure, and speed of delivery. It takes in markdown and svelte, and outputs html. I had planned on changing the name, mostly because French google mostly turns up 5th week pregnancy results (5ème semaine de grossesse), but 🤷‍♀️.\n\n## Big ideas\n\n### Simple build process\n\n1. Install 5sg using `npm install -S 5sg` or `yarn add 5sg`\n2. Put your content files (`*.md` and `.svelte`) in `<PROJECT_ROOT>/src/content/`.\n3. Pick your adventure\n   - Static build: run `5sg` to build to the `<PROJECT_ROOT>/public` directory\n   - Development: run `5sg --serve` to build to the `<PROJECT_ROOT>/public` directory and serve on http://localhost:3221\n\n### Installation using a template\n\nYou can install a 5sg template using [degit](https://www.npmjs.com/package/degit)\n\nFor a basic starter site use the template at https://github.com/cborchert/5sg-basic-template\n\n```\nnpm install -g degit\ndegit cborchert/5sg-basic-template my-5sg-site\ncd my-5sg-site\nnpm install\nnpm run dev\n```\n\nFor more complicated a blog site use the blog template at https://github.com/cborchert/5sg-blog-template\n\n```\nnpm install -g degit\ndegit cborchert/5sg-blog-template my-5sg-blog\ncd my-5sg-blog\nnpm install\nnpm run dev\n```\n\n### Intuitive, file-based routing\n\n`src/content/foo/bar.(md|svelte)` generates `public/foo/bar.html`\n\n### Small files and partial hydration\n\nAll generated html is feather-weight and the client loads no javascript unless needed.\n\nAll images are processed to use modern formats where possible.\n\n### Customization and automation\n\nCustomize everything from config.js\n\n- Your sitemap and webmanifest are taken care of for you\n- You can easily add dynamically rendered pages such as a blog feed and category pages\n- You can apply custom layouts to your pages, either defined by the content path or the `layout` entry in the content's frontmatter\n\n### Dynamic pages\n\nIf you're building a blog, you'll probably want a blogfeed. 5sg provides a way to build dynamic pages using your content.\n\n### Access your content data at every inpoint\n\nUsing the special `deriveProps` export, every layout and top level `.svelte` file has access to the meta data of every other file.This means that you can easily create navigation between sibling blog posts, for example.\n\n## More nitty-gritty\n\n### Project structure\n\n```\n<PROJECT_ROOT>/\n├─ .5sg/ # generated by .5sg you can ignore\n├─ public/ # the output of the 5sg build process\n├─ src/\n│  ├─ content/ # This is where your content lives! src/content/foo/bar.(md|svelte) generates public/foo/bar.html\n│  ├─ static/ # Unprocessed content. All files are copied to public/static/\n│  ├─ <YOUR CUSTOM FILES AND FOLDER>\n├─ .gitignore\n├─ config.js # Optional config file\n├─ package.json\n```\n\nI recommend structuring your `<PROJECT_ROOT>/src` directory like this, but you do what you want.\n\n```\n<PROJECT_ROOT>/src/\n├─ content/ # This is where your content lives! src/content/foo/bar.(md|svelte) generates public/foo/bar.html\n├─ static/ # Unprocessed content. All files are copied to public/static/\n├─ components / # your svelte components\n├─ layouts/ # your page-level layout components\n├─ dynamicPages/ # your components for dynamically rendered pages\n```\n\n### Recommended `.gitignore`\n\n```\nnode_modules/\npublic/\n.5sg/\n```\n\n### Recommended `package.json` scripts\n\n```\n{\n   // ... the rest of your package.json\n   \"scripts\": {\n    \"build\": \"5sg\",\n    \"dev\": \"5sg --serve\",\n    // ...your test scripts etc. here\n  },\n}\n```\n\n### Partial Hydration\n\nAll svelte components are rendered to static html, and, by default, that's where the story ends.\n\nHowever if you need the component to be hydrated (i.e. interactive), you can use the custom `<Hydrate />` component from `5sg`.\nHydrate accepts two props:\n\n- `component`: the component to hydrate\n- and `props`: the component's props\n\nExample:\n\n```svelte\n<script>\n  import Hydrate from \"5sg/Hydrate\";\n  import Count from \"../components/Count.svelte\";\n</script>\n\n<h1>Hello, World!</h1>\n<Count name=\"non-hydrated, non-interactive counter 😢\" />\n<Hydrate component={Count} props={{ name: \"hydrated counter 🤯\" }} />\n```\n\nNote that the rendered component will be placed in a `<div>` which may have layout implications.\n\n### Custom markdown preprocessors\n\nBy default, markdown files are processed using [remark](https://github.com/remarkjs/remark/tree/main/packages/remark) and the following plugins:\n\n[remark-highlight.js](https://github.com/remarkjs/remark-highlight.js#readme): to process code fences (you need to add the appropriate global for highlighting to work),\n[remark-gfm](https://github.com/remarkjs/remark-gfm#readme): to add github style markdown transformations\nand [remark-gemoji](https://github.com/remarkjs/remark-gemoji#readme): to transform emojis\n\nIf you want to change this, simply define the `remarkPlugins` property as an array of plugins in `config.js`\n\n```js\n// config.js\nimport gemoji from 'remark-gemoji';\nimport footnotes from 'remark-footnotes';\nimport highlight from 'remark-highlight.js';\nimport gfm from 'remark-gfm';\n\nexport default {\n  // ...other config\n  remarkPlugins: [highlight, gfm, gemoji, footnotes],\n};\n```\n\nif you need to pass options to the plugin you can do so by passing an tuple: `[plugin, options]`:\n\n```js\nimport gemoji from 'remark-gemoji';\nimport highlight from 'remark-highlight.js';\nimport gfm from 'remark-gfm';\nimport customPluginWithOptions from './plugin.js';\n\nexport default {\n  remarkPlugins: [highlight, gfm, gemoji, [customPluginWithOptions, { foo: 'bar' }]],\n};\n```\n\n### Syntax highlighting\n\nAlthough we're using `remark-highlight.js` by default to enable syntax highlighting in code fences, you need to include one of their themes. There's an explorer [here](https://highlightjs.org/static/demo/), and you can use a cdn to include the styles (see [the highlight.js usage page](https://highlightjs.org/usage/)), or download one of the styles from [their repo](https://github.com/highlightjs/highlight.js/tree/main/src/styles) and include it yourself.\n\n### Custom Layouts\n\nBy default, content is thrown into a plain old html wrapper. In order to give it some style, you'll need to be able to assign it a layout. A layout is simply a svelte file which contains a `<slot />` that the transformed content is injected into.\n\nFor example, the markdown content\n\n```md\n# Hello [world](http://www.example.com) !\n```\n\nplus the layout\n\n```svelte\n\n<div>\n  <nav><a href=\"/\">Home</a></nav>\n  <main>\n    <slot />\n  </main>\n</div>\n\n<svelte:head>\n  <!-- import global css -->\n  <link rel=\"stylesheet\" href=\"/static/styles/global.css\" />\n  <!-- highlight.js theme for highlighting code blocks (for blogs and documentation sites, etc.) -->\n  <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css\">\n</svelte:head>\n\n<style>\n  main {\n    width: 1024px;\n    margin: 20px auto;\n  }\n</style>\n\n```\n\nwould result in an html file kindof like this\n\n```html\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"/static/styles/global.css\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css\" />\n    <style>\n      main {\n        width: 1024px;\n        margin: 20px auto;\n      }\n    </style>\n  </head>\n  <body>\n    <div>\n      <nav><a href=\"/\">Home</a></nav>\n      <main>\n        <h1>Hello <a href=\"http://www.example.com\">world</a></h1>\n      </main>\n    </div>\n  </body>\n</html>\n```\n\nYou can define the layouts in the `config.js` file\n\n```js\n// config.js\nexport default {\n  // ...other config\n  layouts: { blog: `src/layouts/Blog.svelte`, _: `src/layouts/Page.svelte` },\n};\n```\n\na markdown file will use the `_` layout by default, and it will use any other layout based on one of two things:\n\n1. If its directory relative to `src/content` matches the layout name. For example, by default all files in `src/content/blog` will use the `blog` layout.\n2. If the frontmatter property `layout` matches the layout name.\n\nOf note:\n\n- If the frontmatter property is defined, it supercedes the directory-based layout\n- If the frontmatter property `layout` === false, no layout will be used.\n- The layout name is case insensitive\n- Layouts are not applied to svelte components by default. You can just import the component and use it in your svelte component.\n\n### Markdown Frontmatter in Layouts\n\nLayouts receive all properties declared in a markdown file's frontmatter as an object prop called `metadata`.\n\nExample:\n\n```md\n---\ntitle: qui eius qui quisquam!\ndate: 2021-01-01T20:52:15.045Z\ntags:\n  - perferendis\n  - foo\n  - bar\nlayout: false\n---\n\n# Hello world\n```\n\n```svelte\n<script>\n  export let metadata = {};\n  const { title, date, tags, layout } = metadata;\n  // title: string === \"qui eius qui quisquam!\"\n  // date: string === \"2021-01-01T20:52:15.045Z\"\n  // tags: string[] === [\"perferendis\", \"foo\", \"bar\"]\n  // layout: boolean === false\n  // note, if we had had `layout: blog`, then layout would be a string \"blog\"\n</script>\n\n<slot />\n\n```\n\n### Layout and svelte file deriveProps\n\nTop-level svelte files (i.e. .svelte files in the content folder, layout files, and dynamic page files) have access to the meta data of all content nodes in the project. For the moment the way to access this data is a bit convoluted, and it was done this way as a way to get around atrociously large files in the build process. There may be a better way, and this is one of those things that, we might expect to change in a v1 release.\n\nHere's how it works:\n\nYou can export a function called `deriveProps` from the `context=\"module\"` script of your page/layout file which takes in all the content node data, and transforms it into props to be injected into the component.\n\nHere's a basic reference of `deriveProps`:\n\n```js\n/**\n * @typedef {Object} NodeMetaEntry\n * @property {Object} metadata the exported frontmatter\n * @property {string} publicPath the publish path with extension\n */\n\n/**\n * @typedef {Object} ContentNode a single block of content in the nodeMap\n * @property {string} facadeModuleId the path of the input file\n * @property {string} fileName the path relative to .5sg/build/bundled for the component\n * @property {string} name the publish path / slug\n * @property {string} publicPath the publish path with extension\n * @property {boolean} isDynamic if true, the ContentNode was created dynamically rather than from a file\n */\n\n/**\n *\n * @param {Object} context the context of the current content node\n * @param {Object<string, NodeMetaEntry>} context.nodeMeta all the content node information, where the key is the path of the content node and the value is the content node meta information\n * @param {ContentNode} context.nodeData the content node information of the current node\n * @returns {Object} the props to be injected into the component\n */\nfunction deriveProps(context) {\n  const { nodeMeta = {}, nodeData = {} } = context;\n\n  return {\n    //... the injected derived props\n  };\n}\n```\n\n#### A basic example\n\n```svelte\n<script context=\"module\">\n  export const deriveProps = ({ nodeMeta = {} }) => {\n    const numberOfContentNodes = Object.keys(nodeMeta).length;\n    return {\n      numberOfContentNodes,\n    }\n  }\n</script>\n\n<script>\n  // injected from deriveProps\n  export let numberOfContentNodes;\n</script>\n\n<h1>There are {numberOfContentNodes} in this project</h1>\n```\n\n#### A more complicated example\n\n```svelte\n<script context=\"module\">\n  // layouts/Blog.svelte\n\n  export const deriveProps = ({ nodeMeta = {}, nodeData = { name: \"\" } }) => {\n    // create sibling pages\n\n    // get an array containing only blog nodes, sorted by date\n    const blogPages = Object.values(nodeMeta)\n      // get all the content nodes in the src/content/blog/ directory\n      .filter((node) => node.publicPath.startsWith(\"blog/\"))\n      // sort by date\n      .sort((a, b) => {\n        const dateA = (a.metadata && a.metadata.date) || \"\";\n        const dateB = (b.metadata && b.metadata.date) || \"\";\n        // newest first\n        return dateA > dateB ? -1 : 1;\n      });\n\n    // get the current node's position in the array\n    const currentPath = `${nodeData.publicPath}`;\n    const currentIndex = blogPages.findIndex(\n      (node) => node.publicPath === currentPath;\n    );\n\n    // get the siblings\n\n    // the previous or false\n    const prevPost = currentIndex > 0 && blogPages[currentIndex - 1];\n\n    // the next or false\n    const nextPost =\n      currentIndex < blogPages.length - 1 && blogPages[currentIndex + 1];\n\n    // these will be injected into the component\n    return {\n      nextPost,\n      prevPost,\n    };\n  };\n</script>\n\n<script>\n  // these props are injected thanks to deriveProps above\n  export let nextPost;\n  export let prevPost;\n</script>\n\n<article>\n  <slot />\n  <footer>\n    <nav>\n      <ul class=\"sibling-navigation\">\n        <li>\n          {#if prevPost}\n            <a href=\"/{prevPost.publicPath}\">← {prevPost.metadata.title}</a>\n          {/if}\n        </li>\n        <li>\n          {#if nextPost}\n            <a href=\"/{nextPost.publicPath}\">{nextPost.metadata.title} →</a>\n          {/if}\n        </li>\n      </ul>\n    </nav>\n  </footer>\n</article>\n```\n\n### Site Meta and SEO\n\nThe site meta data from config.js is injected into each top-level svelte component (layout, content page, and dynamically rendered page) as the prop `siteMeta`.\n\nFor example, if in `config.js` you have\n\n```\nexport default {\n  siteMeta: {\n    name: \"My 5sg site!\",\n  }\n}\n```\n\nthen in the template `Page.svelte` or in the content file `src/content/index.svelte` you could have\n\n```svelte\n<script>\n  export let siteMeta = {};\n  const { name } = siteMeta;\n</script>\n\n<h1>Welcome to {name}</h1>\n```\n\nAdditionally, the following siteMeta values are used to create a `site.webmanifest` file:\n\n```\nname,\nshort_name,\ndescription,\nicons,\ntheme_color,\nbackground_color,\ndisplay,\n```\n\nsee the [web.dev guide on manifests](https://web.dev/add-manifest/) for more information.\n\n### Dynamically built pages using config.getDynamicNodes\n\nIn addition to pages rendered based on existing .svelte or .md files, you can create pages dynamically using the `getDynamicNodes` property of the config object exported by `config.js`.\n\n`getDynamicNodes` is a function which receives an array of all non-dynamic node metaData and which must return an array of dynamic page nodes to build.\n\n```js\n/**\n * @typedef {Object} NodeMetaEntry\n * @property {Object=} metadata the extracted metadata from the frontmatter (md) or the named export `metadata` from the svelte context=\"module\" script tag\n * @property {string} publicPath the final html path\n */\n\n/**\n * @typedef {Object} RenderablePage\n * @property {Object} props the props to render the component with\n * @property {string} slug the identifier of the page to be rendered (use .dynamic as the extension)\n * @property {string} component the path to the rendering component from the project root\n */\n\n/**\n * Given the nodeMeta, returns the information necessary to render some dynamic pages\n * @param {Array<NodeMetaEntry>} nodes\n * @returns {Array<RenderablePage>}\n */\nconst getDynamicNodes = (nodes = []) => [];\n```\n\nWe could create a simple page like this\n\n```js\n//config.js\n\nexport default {\n  getDynamicNodes: () => [\n    // will create a page at path/to/customPage.html using the CustomPage svelte file injected with the props {foo: \"bar\" }\n    {\n      props: { foo: 'bar' },\n      component: 'src/pages/CustomPage.svelte',\n      slug: 'path/to/customPage.dynamic',\n    },\n  ],\n};\n```\n\nThis could be useful, for example, for creating a blogfeed\n\n```js\n//config.js\n\nexport default {\n  getDynamicNodes: (nodes = []) => [\n    {\n      props: { blogPosts: nodes.filter(({ publicPath }) => publicPath.startsWith('/blog')) },\n      component: 'src/pages/BlogFeed.svelte',\n      slug: 'blog/index.dynamic',\n    },\n  ],\n};\n```\n\nWhile the example above is possible, it doesn't hold any real advantage over simply using deriveProps.\n\nWhat would be more useful, for example, is using `getDynamicNodes` to create a paginated blog feed, where each page contains 10 posts. Here's a somewhat naïve implemenation:\n\n```js\n//config.js\n\nexport default {\n  getDynamicNodes: (nodes = []) => {\n    const pages = [];\n    const blogPosts = nodes.filter(({ publicPath }) => publicPath.startsWith('/blog'));\n\n    let totalBlogPages = 1;\n    let posts = [];\n\n    blogPosts.forEach((post, i) => {\n      posts.push(post);\n      // every 10 posts, create a new page\n      // also create a new page if we're at the end of the array\n      if (posts.length === 10 || i === blogPosts.length - 1) {\n        pages.push({\n          props: { blogPosts: [...posts], currentPage: totalBlogPages, totalNumberOfPosts: blogPosts.length },\n          component: 'src/pages/BlogFeed.svelte',\n          slug: `blog/${totalBlogPages}.dynamic`,\n        });\n        // if we're not on the last post, set up the next batch\n        if (i < blogPosts.length - 1) {\n          posts = [];\n          totalBlogPages++;\n        }\n      }\n    });\n\n    // additional props to make pagination easier\n    pages.forEach((page, i) => {\n      page.props.totalBlogPages = totalBlogPages;\n      page.props.nextBlogPageSlug = i === totalBlogPages ? undefined : pages[i + 1].props.slug;\n      page.props.prevBlogPageSlug = i > 1 ? pages[i - 1].props.slug : undefined;\n    });\n\n    // return the pages to be created\n    return pages;\n  },\n};\n```\n\nIn order to help with what we think will be relatively recurrent operations when creating dynamic pages, we've included some helper functions which can be imported from `5sg/helpers`\n\n#### getDynamicSlugFromName\n\nDoc:\n\n```js\n/**\n * Formats a name to a dynamic slug which can be universally recognized\n * @param {string} name the page name\n * @returns {string} the dynamic slug\n */\n```\n\nExample:\n\n```js\nimport { getDynamicSlugFromName } from '5sg/helpers';\n\nconst slug = getDynamicSlugFromName('this/is/my/name');\n// slug === 'this/is/my/name.dynamic';\n```\n\n#### paginateNodeCollection\n\nDoc:\n\n```js\n/**\n * Given an array of nodes, returns an array paginated nodes to be rendered\n * @param {Array<NodeMetaEntry>} nodes the collection of nodes\n * @param {object} config the pagination config\n * @param {number=} config.perPage the number of nodes to put on a single page 10\n * @param {(i:number)=>string=} config.slugify a function to transform the page number into the slug/path/unique key of the page i => i\n * @param {string=} config.component the component to render each page\n * @returns {Array<RenderablePage>} the paginated node collection\n */\n```\n\nExample:\n\n```js\nimport { paginateNodeCollection } from '5sg/helpers';\n\nconst pages = paginateNodeCollection(\n  [\n    { metadata: { a: 1 }, publicPath: 'test1.html' },\n    { metadata: { a: 2 }, publicPath: 'test2.html' },\n    { metadata: { a: 3 }, publicPath: 'test3.html' },\n    { metadata: { a: 4 }, publicPath: 'test4.html' },\n    { metadata: { a: 5 }, publicPath: 'test5.html' },\n  ],\n  {\n    perPage: 2,\n    slugify: (i) => `test/page-${i + 1}.dynamic`,\n    component: 'path/to/MyComponent.svelte',\n  },\n);\n\n// Result\nconst result = [\n  {\n    props: {\n      nodes: [\n        { metadata: { a: 1 }, publicPath: 'test1.html' },\n        { metadata: { a: 2 }, publicPath: 'test2.html' },\n      ],\n      pageNumber: 0,\n      numPages: 3,\n      pageSlugs: ['test/page-1.dynamic', 'test/page-2.dynamic', 'test/page-3.dynamic'],\n    },\n    slug: 'test/page-1.dynamic',\n    component: 'path/to/MyComponent.svelte',\n  },\n  {\n    props: {\n      nodes: [\n        { metadata: { a: 3 }, publicPath: 'test3.html' },\n        { metadata: { a: 4 }, publicPath: 'test4.html' },\n      ],\n      pageNumber: 1,\n      numPages: 3,\n      pageSlugs: ['test/page-1.dynamic', 'test/page-2.dynamic', 'test/page-3.dynamic'],\n    },\n    slug: 'test/page-2.dynamic',\n    component: 'path/to/MyComponent.svelte',\n  },\n  {\n    props: {\n      nodes: [{ metadata: { a: 5 }, publicPath: 'test5.html' }],\n      pageNumber: 2,\n      numPages: 3,\n      pageSlugs: ['test/page-1.dynamic', 'test/page-2.dynamic', 'test/page-3.dynamic'],\n    },\n    slug: 'test/page-3.dynamic',\n    component: 'path/to/MyComponent.svelte',\n  },\n];\n```\n\n#### sortByNodeDate\n\nDocs:\n\n```js\n/**\n * a sort function to sort by date\n * @param {NodeMetaEntry} a\n * @param {NodeMetaEntry} b\n * @returns {-1|1} the sort order\n */\n```\n\nExample:\n\n```js\nconst nodes = [\n  { metadata: { date: '2021-01-03', a: 1 }, publicPath: 'test.html' },\n  { metadata: { date: '2021-03-03', a: 2 }, publicPath: 'test2.html' },\n  { metadata: { date: '2020-05-30', a: 2 }, publicPath: 'test3.html' },\n].sort(sortByNodeDate);\n\n// Result\nconst result = [\n  { metadata: { date: '2021-03-03', a: 2 }, publicPath: 'test2.html' },\n  { metadata: { date: '2021-01-03', a: 1 }, publicPath: 'test.html' },\n  { metadata: { date: '2020-05-30', a: 2 }, publicPath: 'test3.html' },\n];\n```\n\n#### filterByNodePath\n\nDocs:\n\n```js\n/**\n * Creates a function to filter the nodes by their public path\n * @param {string} dir the path to filter by\n * @returns {(NodeMetaEntry)=>boolean}\n */\n```\n\nExample:\n\n```js\nconst nodes = [\n  { metadata: { a: 1 }, publicPath: 'blog/test.html' },\n  { metadata: { a: 2 }, publicPath: 'other/test2.html' },\n  { metadata: { a: 3 }, publicPath: 'blog/test3.html' },\n].filter(filterByNodePath('blog/'));\n\n// Result\nconst result = [\n  { metadata: { a: 1 }, publicPath: 'blog/test.html' },\n  { metadata: { a: 3 }, publicPath: 'blog/test3.html' },\n];\n```\n\n#### filterByNodeFrontmatter\n\nDocs:\n\n```js\n/**\n * Creates a function to filter the nodes by their frontmatter\n * Returns true if the given key equals the given value OR if the given key contains the given value (if an array)\n * @param {string} key the frontmatter entry key\n * @param {any} val the frontmatter entry value to test against\n * @returns {(NodeMetaEntry)=>boolean}\n */\n```\n\nExample:\n\n```js\n// get all nodes with metadata.tags including 'bacon\n\nconst nodes = [\n  { metadata: { tags: ['bacon', 'eggs', 'cheese'] }, publicPath: 'blog/test.html' },\n  { metadata: { tags: ['cheese'] }, publicPath: 'other/test2.html' },\n  { metadata: { tags: ['eggs', 'cheese'] }, publicPath: 'blog/test3.html' },\n  { metadata: { tags: 'bacon' }, publicPath: 'blog/test4.html' },\n].filter(filterByNodeFrontmatter('tags', 'bacon'));\n\n// Result\nconst result = [\n  { metadata: { tags: ['bacon', 'eggs', 'cheese'] }, publicPath: 'blog/test.html' },\n  { metadata: { tags: 'bacon' }, publicPath: 'blog/test4.html' },\n];\n```\n\n#### getFrontmatterTerms\n\nDocs:\n\n```js\n/**\n * Gathers all the existing values of a given frontmatter entry on a node collection\n * @param {Array<NodeMetaEntry>} nodes the collection of nodes\n * @param {string} key the frontmatter entry key to collect the values of\n * @param {(any)=>any} transform the function to apply to each term (for example a=>a.toLowerCase())\n * @returns {Array}\n */\n```\n\nExample:\n\n```js\nconst nodes = [\n  { metadata: { foo: ['A', 'b', 'c'] } },\n  { metadata: { foo: 'd' } },\n  { metadata: { foo: ['e', 'C'] } },\n  { metadata: { bar: ['lol'] } },\n];\nconst terms = getFrontmatterTerms(nodes, 'foo', (a) => a.toLowerCase());\n\n// result\nconst result = ['a', 'b', 'c', 'd', 'e'];\n```\n\n#### groupByFrontmatterTerms\n\nDocs:\n\n```js\n/**\n * Groups a node collection by the values in a given frontmatter entry\n * @param {Array<NodeMetaEntry>} nodes the collection of nodes\n * @param {string} key the frontmatter entry key to collect the values of\n * @param {(any)=>any} transform the function to apply to each term (for example a=>a.toLowerCase())\n * @returns {Object<string, Array<NodeMetaEntry>>} the grouped nodes\n */\n```\n\nExample:\n\n```js\nconst node1 = { metadata: { foo: ['A', 'b', 'c'] } };\nconst node2 = { metadata: { foo: 'd' } };\nconst node3 = { metadata: { foo: ['e', 'C'] } };\nconst node4 = { metadata: { bar: ['lol'] } };\nconst nodes = [node1, node2, node3, node4];\n\nconst groupedNodes = groupByFrontmatterTerms(nodes, 'foo', (a) => a.toLowerCase());\n\n// result\nconst result = {\n  a: [node1],\n  b: [node1],\n  c: [node1, node3],\n  d: [node2],\n  e: [node3],\n};\n```\n\nFor an example of how all of this can be used together take a look at the `getDynamicNodes` in the blog template: https://github.com/cborchert/5sg-blog-template/blob/main/config.js\n\n### Image processing\n\nAll .jpg image files which are not in the static folder will be transformed into images which are at most 800w by 400h. We add .avif and .webp file versions, and then we transform all image tags into picture tags with sources.\n\nThis will likely be refined before v1, and it will be customizable.\n\n### The static folder\n\nThe `src/static` folder is copied directly to `public/static` without any transformations.\n\n## Questions and answers\n\n### What's the deal with the tsconfig file ?\n\nThis project doesn't use Typescript, yet, mostly because I wanted to avoid a build step. But I nonetheless wanted to make sure that I had a way to implement type-safety. I'm using a weird mash up of js-doc style type declarations along with a ts-config file so that my text editor and linter can catch type errors. It's hacky, but what about this project ISN'T ?\n\n## Inspirations\n\n5sg was inspired by Gatsby, ElderJS, 11ty, Grav, and MDSvex. I did extensive research on partial hydration after the version 0 was finished, and would like to thank the developers of ElderJS and 7ty for their implementations which made the most sense to me.\n\n## Future plans\n\nCheck the project [v1 release candidate](https://github.com/cborchert/5sg/projects/2). Once I have a v1, I truly doubt that I'll do much more work on this other than bugfixes. Hopefully sveltekit gets to a point (and it seems to be rapidly becoming the case), where this project will become obsolete.\n\nAlso, the documentation needs A LOT of work. Sorry for anyone who got this far and has no idea what's going on. No promises, but if there's enough demand, I will probably go through and make a few tutorials and/or clean up the documentation\n\n## How fast is it?\n\nIn my test project which contains 100 images, 994 static pages / posts (md/svelte), and dynamic blogfeed, category, and tags pages resulting in a total of 1124 page total built, the first build takes 30 seconds on my macbook pro, and 3.5 additional seconds when a file is modified.\n\nThe experience is pretty subjective, but it seems more or less consistent with what I've seen elsewhere: it's quick.\n\n### First build\n\n```\nbuilding\nbundling: 10.612s\npruning: 0.007ms\nnodeMap: 0.948ms\nimport: 901.282ms\ndynamic: 234.995ms\nrender: 1.113s\nhydrationBundle: 131.178ms\npublish: 773.428ms\ntransform: 16.434s\nstatic: 11.309ms\nsitemap: 1.579ms\nmanifest: 0.201ms\nbuild: 30.216s\n```\n\n### After a modification\n\n```\nbuilding\nbundling: 2.555s\npruning: 28.73ms\nnodeMap: 3.191ms\nimport: 255.307ms\ndynamic: 84.215ms\nrender: 180.369ms\nhydrationBundle: 61.854ms\npublish: 246.609ms\ntransform: 28.427ms\nstatic: 17.949ms\nsitemap: 1.734ms\nmanifest: 0.211ms\nbuild: 3.471s\n```\n","readmeFilename":"readme.md"}