{"_id":"@adobe/hypermedia-pipeline","_rev":"253-6674ac3e09d9703f4b99e4bfa88fbfa3","name":"@adobe/hypermedia-pipeline","dist-tags":{"latest":"0.8.0","next":"0.8.1-pre.2"},"versions":{"0.1.0":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"1bf60cd68b418741874e8a84e947b3660d11a78f","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0.tgz","fileCount":20,"integrity":"sha512-JdPloJ83Nvmz4aYKEnriFduLMzX4P0Iolqo0YQ1V/A3IMxdlcB+dqdx80ioDbegYjpNzBOL/jHhnXIPNqjj6Aw==","signatures":[{"sig":"MEYCIQDGeG2iWT3biupfLapckqhyaUDpLUeoXicP9E5HMSRBzwIhAO/TXLiMBk7XHUqx9/hdyOVfV+gqCnq0Q2VEz9xF14se","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50464,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNMDBCRA9TVsSAnZWagAAMTkP/iL4Xo3KXUJ1ZzLiRHcn\nZ0H6aPb7o9hGtSfFXrZBBRfFf3KdLp4NjzGY0t+K1bZ8VtK2GU48f6PdxkvL\n24aLpnjUp0cNL3mvYQvipLskZsZ2LGEe00m4uBlJddjHIobF+ZLtuXkObOoy\nCaPzGwB5iLRjZTbpN1WToEydbOfF6ts2fYhhAPlUEWKVOVNqugq7RqoqNb/k\nRkR82+yGoM9ihePUtH8+LV3Y3M3SlPS5Oa/Rkq5bC6nVMw5KEek1Tb5urHR9\nTq1FAdh7jD34I5fAEaf9GpLiwh4KflgDyeZeOvY2Yhk6L74hKTjJN2L0egzr\nyhIv5vJIPp1xB+MqJGTk4skrZ3y4a30iM2AQ0EmhEiKPwcEcNrTMzb1p39X7\nuW/fj3JyqFgeTUMFWZicsukrwSoB+6MkSFQi/xCyi3ZPz//kte4afh0Upd00\n339Mp2BoveWo9reX71kVuVSCvXGdK/xXbmOuFfHAJbXtexN9Oa7yNdfGuI9q\nweGg8GPG6TWUI8kYSCOjhajU5wH00zTpH9r8VXBSZAdhTbhjmvJ+TDFC6wbl\nB4mKtP4jh+yA8lnaloXNMYSnWZwARuozLjkP9BbU6Z0/gl+8wLjztOck6dY0\n8COvCOmWkTXzblwhhY2sLAkuaKU4Fb4SK4A8/UZCFHS4vb4YNAzgEsu+C2We\nGeWU\r\n=AlSn\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"521d70c8cb2c2aa57ed764c49ec3ee21372a7053","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0_1530183873000_0.24977253280873501","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.14":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.14","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.14","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"17d8374c1279425e8fea8860a935aaad808d4487","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.14.tgz","fileCount":20,"integrity":"sha512-Adow3vc8CiKfLJTjfebLtUaolmAmfGWUMJuRaL0O7dGeD5G/rddDmFfdHZPPtOcQeAoIMTH66h81SxElheAEyQ==","signatures":[{"sig":"MEQCIB50fzRSaIeSIGP86a4zDYNfk0gGbMBIscmmOG3YYaZ6AiBOLhOfshUCpxv9AqaXXyHSUM7KN/76C2GHvlzn0CdgwQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50465,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNMHXCRA9TVsSAnZWagAAplYP/j8qTDe5i+kybdoTzovd\ndtUHiz4/9labv4TW7vKUxtz/jTbZJKHGzp/uneElG6U+oqbQhqWgAilA/42z\ny9kgcdLfegRp+IAleWgPHMD8LVNaDpdqJQXX23QVmm35quVeUg2Fy26VCvK2\nezDXPB6H7aLLUpMb53th+bDDjP0DPOR7kk+7+v1Wrr32UDGpZfCIqhHAIDSd\nVH87qQE5QIx2NpdCDJGnLctohe0iA7Wf6PuSfLh3OSijTDh9FEomQwq/Q6pq\npWqeVwYHr6CmcseQVFHOTY6S9E4oU82Nwj1lScQX66JsBJRzvCOEfg9vbnCo\n4tQPyHFn23mJBr3cUvVtis/FSNglWrPwbcVPbBzFFkdO7OxudAWKE38HP45z\nunL132+2V6SwuyGZxxU+Ri+NETMTFwb7od/p9VD49RBEjR6UtY2tldC6REt5\nUAYEI/oJhUHqKuuDCCowCdmB4tKwnccIfS/oxvSo6uc21KyMyy88jsg+4qrP\nMnUjPKYDTB9uV2wTNFPJ//0PHx5oiFD6TtI8ujxIk96mJtcmB5A2vRwYrTXQ\neE1aE8mqynb98hH/g9s6/WNmUOoIz0Jn0YMNPDtXBtt9/hSGOELpdANml0fN\ns0UM9/FYJIhBtNnrkxqfmXbsckN/leISRkxr+BhrCJFs535EIfGkPx20ANK6\na3yG\r\n=lLuU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"cb3e7d9632c125f102bd646dab672d3a6f2c41ed","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.14_1530184151534_0.17088844092172173","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.16":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.16","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.16","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"617ebbf53a1ebdfc3adf5a694739816e66583733","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.16.tgz","fileCount":20,"integrity":"sha512-i8DNuf4TzGwzfJuqJj+15YaRvkL7pss29EXz0aT5PqYC7zCPDeSaSJjBjhRCeq1YGyhP/ogeWsa9sVWT1en9BQ==","signatures":[{"sig":"MEUCICuzol/TDg1cFuUzvJmNZEgwO6bkbcN86nGzAwsNV38BAiEA0x3pe3O71MVg1MamVuX7axZ2/3qDUkzrLjF5r1edu8w=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50495,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNMIFCRA9TVsSAnZWagAAUX8P/iCIHYPoYOPWZ5Zax7Yo\nVzfaJFZ/kRLKylJZLTrxmfa0lHPvfHhjBVimGum9fqpPuUCKKwItra9hQeQV\nCQmDY8Jrqd69c0LIXRRlCUtFNemTI+HEHwYCDpahVRtyTqRZMt7REwatGv5w\n6zWzIvJcyYGi6tlKZ+wcHZrink09Y/ZUH1AN4HdDKT6L3I+I5ZHKE6JEmRuf\nIrtRYn6nNQPztw+t1h08G419xAX4LUHEMExIWgEMMGrb+/peI+p3u/H2sqM9\n7FyDKImmpP38hNveHXjUMGDBtPwcgxuEdseAgNpiElZKJOx61XSQYLLkvqZa\nXWDn9JdrSRJjPFcU5g20OnWpkU8pX7kjPdNuNtQ99DrvybNbuIm2ANOTRFTG\nexp5LvNao3vHuCxeqx0bZS8eKWPGrxAfXpp5u4JabF+JH4fR25nq+q7PkB+Q\nn8p5lOUY8x/JWHv8FDSwZbWB8TsLFVc+/G2Cl05qBm8dtjJymvxdYPe/s5bx\nbJ3uju81gR0SE4vvYf0CI+FZzeIBgWhvS9mvN4mZ6OhPst0bJlXUdRoxMTo3\ngBvzml77TlOLj0bnkxgF+MZpcQh2FT/NBFvdNGzjete8B0NiCKcdDh+hxT7f\n358C/nznuQ6rI4stkQkALbKSnJDqBbkJPozC9Cny/+Aq3eg+/ERDPh7ef8VN\n+ldj\r\n=E+kc\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"d8f9b97dc763eac7cc432aab0f425d96eb5713e3","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.16_1530184197157_0.21069124616450763","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.18":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.18","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.18","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"97fc398c86b9130d527dec8f3ff1ba3b6b1b0a29","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.18.tgz","fileCount":20,"integrity":"sha512-1Gaz+TAwxZA6fugkb1dpbGEqr//0IQXMCt41idjdYdfofeyn6iY9RKAqWyC45WA/0wYtAbW/x9wuz5AQtnB32w==","signatures":[{"sig":"MEUCIESWD14+7uKJgM2Q20Ng+7uylpqZikb6j1KsESNNo2IgAiEAqTeI24mGWY6pKu6wrRtLKR6CBbaOtXUFwLHUkLZeN1U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNZRACRA9TVsSAnZWagAAxIAP/jWstHB4AdjIBv/lKTsH\nepSz0//WN+HVr5QH4fKCxoO+JMK/ktzL+l4tB1s8ihoNOZvn/ooTEO9BnF9t\nYu0Zs0RGSDNquTUQsSYy2GjcTvt4hrHk9Djl8OuQdknASXtibLJ/tlG0X0RN\nzKphj0NnJk+CVJzSf+OEEuV3yEKq42lS+5ysF7Q4ZaC0xl6OtzSG6+igb1RO\nvXwMoXW8apI1R7Xpuib5Nu7VpUgt/CHlZiM8vVZDBLNVX96erircUT7KqJGU\n5OgCUFtIJ586vhVeHv+W6RX1THuV6HuxF89moV1SLq+odIBk/GWRd0YYDBaj\nEuhr6gF/rq2GVWZm0RaOQinGsjf9I57Fy9A2SNYcLXLL6xmiDtZSVuskFGHq\nvAquVD6NZg7x805aJa4lAddcr+ofCY7hjVm+UCZr5NedKCRHtO5WBRvlnu0b\n9n0lloux6XCFsUPwTq/JXqDYQm4EtArjjDp6tQpJzLmmOn5dJ3qmsbWBgYmb\n3jXsEsNDpOyXJnIOuhJPXa42YLkH5fD0YhxyuvB20ZrZ4StH4tnBU8KoVcGt\nEY2IjrCTar5G1cGcSptrG9sPzh93KLW8UVsV7Q0ZS5w/E2Htmw4x08kFqAL8\n13Ei0h0myEyZnKx8+XbSe2scSlRy0ErLf19tBf8akzhae6Re6Mfz0JGnsnRr\nqXHG\r\n=VY7k\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"94fe83376e136b91b3d8b58d9c51659c503cf6cb","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.18_1530238016419_0.0028195448688994595","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.20":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.20","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.20","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"762dcfcfd05fcdca7224a444ecedc8a0d6cd15d0","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.20.tgz","fileCount":20,"integrity":"sha512-Bs96coFnXMOzC51y9i/6D7qD3fU2/hgXS06Fbnk36eMCSOFXYPjd6qL3lzOivypgVp/pGFGkP4l1frJC8F+f9w==","signatures":[{"sig":"MEQCH0lgPlRjpLo7qrclINrLNWbTrtN/sJ+duQW2Wvc1b5sCIQD7LvrHdZveRVbIArcbge36jeyAmpoWm/MwcUflMo3hhg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNZxUCRA9TVsSAnZWagAA7p4P/ihG6Jcy+jDv007+5LRa\nlUkbKcOZGXqWJ+ZWJkgcXm3cSPTlOa4KoXAjTIqXtxSHjqO2gtjYMVqqUMM4\nvg++YfE22aHAmUkv+C4IpCKGLGRi6d5utCoO2vZ48cuQEU3xkkCeWPoMic4c\nN7/hrPUK8ntrCTGDmvfYnLN9j8Tk2CG3LHrG9J4KXQnym/E57vt6S+5IZDWx\nQm+2bGIfXdw+0/2w1oSgg7H2JlqDhBGEfxT4oQEq6jf8NPpzVNPdgHXPubT+\nJV3kmAWoi5GripYBkWlSiHpUXZE1mC8uNOQl0c1dsk5qM7wpvnwTeXQfDmSW\nNL+L2fT3bkJ5ONqryXPin9UkKg5nplZigRZzRA0CzbJvGIs5Cfvdrzt6RzEc\nPpOMHCq7K+nwZHe4ssfXIo7PBstsBFPxLa2mo9B7+3DvWY0pZ4lrpLUavXMb\nIIGFfxdHFO+UnlAykslyeRl3q1G8hDSgfbDPMVhlNypv0ma1YPt8mUEZUs7f\ndcaivTU4WPpsC/C5BAQsUK61ajxetsB7edCTDgvpfejJ9TCaM/UmhWrcVwTT\n2JnUJGzwYA8tP2Yo9YeNjLfi1FIkmrg5ieboJl1hLcwcpiY59vpYhTxCRNPD\nB9eq3Wua5lYKPz0Pitj7xwY3M3L8x2ytmBrb5GKOwEJPprbMVE8KUx8/RU9y\nN3cw\r\n=KCEh\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"a4ff0b2560c3c7181fa02a03d51198bcbf6eea3a","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.20_1530240084175_0.36018060157088727","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.22":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.22","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.22","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"edc5dd71a934226c5c307ac1b23bd4b7122b638e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.22.tgz","fileCount":20,"integrity":"sha512-mlXDmEOyABfysc5zf1AZ67Ch2mz9z/yiM1lZ1dC1iDf12wASKjq/ixA50sGlfxPM9Xlw7bE/INxFYyIiJK5jvw==","signatures":[{"sig":"MEYCIQC1k9VfGmj73ddW774i3y6S13TIubhRkgkFr6EdOgLTxQIhAK/0l3+N2kwmbgvRQPmu7avs7PA4iKjhilL9X6ZHEDqY","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbNZ6dCRA9TVsSAnZWagAAK4QP/i2JyyQsEZfAsGPvJ+dm\nCF5s+k6TCjNfBIyJqil+YXGRPB4pPO9ZtuYm/HzGuaxuonYT8M1KAp9bBU/1\njpfE3YEmWJtNGOy8hZG22N3FgFavrAWAunuJoxILlBWg9z+lx8XFnQLGCWAp\nlQFDBoZV2zReXaX0Q5H1UB0TpyhXXqOxIWpEWM81SLaGekO5oih4dquHzsqM\nfjv+uzRm+WH0WDwHS/r6v25hj7hAmWnBWXA3cCxBcjlsE5CqGI37Cvaaz8v6\nHT5c8SQLubkaP0iXpS/UyNrNyCaL2c58Qak3nYqnaUGV5i7VmcFdi+PCAxlk\n1N8r+A9/zK0fL/Rhne3VfUkcPRRJNECToN2jo+1GFH+oAqUSz6IkgsL4+gi+\nPdglF/cXyFISePYE0RCiEAcs0dog4pJUrL9M2IB4pAwu07jrF8R/pqRzXHjk\nTwyPoTu8y1CCxIvXX/RbqGkeooGF3o6G7odtPnd7YXo+WNcRswp1TRkZ/XSR\nZqzp7jhwH6Kx6fLiGGZRFIVCkik7nOoBoCkj5coeH31vNK68Qjcuje0QjGOy\nHvd0OrpMSj1nTUvNzYxRdClB7yo83LexsVOrErt+GdfcH+MY8qINuGuKZXAr\n1mJbTJFYdwBb0Wi/NV/obzlXBvY3fVID9PceYBW5k+JkBM71XGt2V4QeCrWb\njAJR\r\n=487Y\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"48ff22ff6b862a205e85a70d61af3678f5950680","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.22_1530240669670_0.040408854425581175","host":"s3://npm-registry-packages"}},"0.1.0-SNAPSHOT.24":{"name":"@adobe/hypermedia-pipeline","version":"0.1.0-SNAPSHOT.24","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.1.0-SNAPSHOT.24","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"dd2020d49532ff366c67a6b7f55840fcad8a6fed","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.1.0-SNAPSHOT.24.tgz","fileCount":20,"integrity":"sha512-Wjf4hZMmKXkrUmLoOzKsivEuGe/a2n4qXXFx7upS1/XzkZOobqbj7D00wQ9bbvFmwgj36ZBCkZKvk8NSmbjsaw==","signatures":[{"sig":"MEUCIFPqoHt35ULSFdDaSjmN/e54V5n45JmyR4w4tx0bmnCpAiEAhc4R/4qgLNGHwGqP/4DVLRxJAOzxjE8bCce3TcHAGGM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":51230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbOl5SCRA9TVsSAnZWagAAedIP/14LvENtXtDm7Q+/xFZ+\nqSd6f4Hp8hlsbR77/0n6TZF7bnPfM3vrNBJb5iBtzd3Ldu0Oj16U4xYmPJ+1\nPFiSyLGQ2qBqk2nSFJDnKOGSI8utTt7cQlfWsejMZnLzlXwolXnfHVEjKcfQ\nNzOEWo9N9+1DuIWeKFE6wJK86WIwXQgNOGPwGl/RPqxWpvdwN8DIbGgLRyK5\n5gcKofyGXySLufoMALUtl8pAHQSeKYzP2nep6MHqijM+VCT3bhJQbasgR45x\nYpKEUCLk6BZLyrvGmkwNiZKmhCSIBVmsueeoMKFnwUhSpvt6thrLZFuStEN5\n+c0zNVKARW/ZrnHIU+tEMvZFMIHAGQPs6rh5vuvwLZTPkm7rSdsPAUUinFc4\nWm/Rh/YCn6FRYmaeaZaGLR80oSd2cU9PMOslFgKsGCT8dXc8AwVqPtA29Lm0\nEP9bXK3V1vXeliARq+wHbwZPu7cL1Cxz5Jo8CK3p3N6aZK7chqCPYJ4gNVqF\ngYISqgESkHDYzlnafaxNMGyZ9DCDU4yWF5khYEENt3m8YfrK6zTEYw2kt2Vk\nYjbLRW6U3D90mR/NXEL659oqtgPHiN95e0/BDsg6Ctjo59OM9Ae/SGfVR1KW\nhGdTIsmYWmJ87axFlxn2nXRfSRZ9Q1as8UNtFSSQkReHNGo19bwpXIjMLa4L\n5N8e\r\n=+Lay\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"9416fc17a7d9060f8ef17931a92e6e487c6c2a18","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.1.0-SNAPSHOT.24_1530551890614_0.7018791804953055","host":"s3://npm-registry-packages"}},"0.2.0-SNAPSHOT.26":{"name":"@adobe/hypermedia-pipeline","version":"0.2.0-SNAPSHOT.26","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.2.0-SNAPSHOT.26","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"c9ffcbdc4f7146699937df6562c2a24707ce1432","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.2.0-SNAPSHOT.26.tgz","fileCount":20,"integrity":"sha512-r/RpcaT0ZlLTHck9hjhgBrQvF6Y3PLGw2qafSuERpi0oohdkRNT48ZAJxAKOXxFIJclr8k6CilfY/LHvTBmOmw==","signatures":[{"sig":"MEUCIQDnmmDNwIYGGiNbq8QCU5l1rtx1RzBkGjZoZEaY00tHHwIgKyDUa6zoeUtV174OnEFifcBMDI0zoQjMymSLkBIFUYg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":51230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbOmOdCRA9TVsSAnZWagAA4ScP/2RvDmrheED6nWUBj2g/\nLarJ0BNHoEsyZ3dySN+zdDJ1gHU+1oqVQRisgUw+xFoczYfD9L4ykwXeh9Yf\nwnhXsCz0YfDUyBdFnF9GyEhWrz0ZHAKKOdSJxSfWSiY2sUGrN1H4oEipCK1O\nQsANVaI0wOwTxox0D5qGV0mDALNQ5fgeUVPBPWqsqSvrOnPT1uAlMKxcMnjf\nlhnhC/mKUxDQjWTDFWtnE012b+qXuaoMkw24vpnT8blLCgUpXxvBPkDHmgeW\n4Gly9rKvLwBdITiPOIRtC9/eFz1F3T1Sw6Xtgivm0ca/3ZJZru15xA+dZlBk\njl79r8z4bnF+zUSiOMhKoXqE3OL9eo+FKQKNq0aHDdKpzfx/RVFrH/yH2n3x\n6GGCiYj9OXF+2LUIEuE8YeQQLj917Ndm4Mdj/RYY4/Ij3W6pNYITW6AASure\nS4FU5OzaijuLRb8GWz0G5Zmiewed3ELnggh2tt5+WQSqSPIOMIx9RuU54A+e\nwlA4l1RFa0r7lIwfYCWAOTVsdeRUTzD1Btv7w7flROUAsjKGQ2y8CtsyBLDD\ndF1xjbSEXuwAilbU/8hPrYB8zjZc8GFVHCHS/PUV6MAk70yVoPZRxuYFZLk2\nM2UZLBnax7mqA87bCiBGzbRIBL4dr3ncg/+buw9ixWtL/Ow6FtnPpaIJubYN\ndbHB\r\n=BxnL\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"3aea9945afb0b69f51acadb097f973419176ae38","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.2.0-SNAPSHOT.26_1530553245799_0.19195235933721322","host":"s3://npm-registry-packages"}},"0.3.0-class":{"name":"@adobe/hypermedia-pipeline","version":"0.3.0-class","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.0-class","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"1f353b6e56c28500012c81498d58d6362975f136","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.0-class.tgz","fileCount":50,"integrity":"sha512-0/3Z4TsgP5NSff3hYOIqCj7XbJAlEdpjQoYgQdYDC7ro6rgimVPj4QKAFEeH17u++NLQkWJhQnYXqqm1sUL7iw==","signatures":[{"sig":"MEUCIQD/RV9aHoxo0t9XoxgLyTfIKoqp4GGW+7JbkMxW+3jjLwIgQlH1Oo878dfTqHJSObHNZaQExBhZgvmARqd+1dEnluM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":266763,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbO3LDCRA9TVsSAnZWagAA2iMP+gJgfiI9Q1++p6Q8HDJv\nsLcgeCh7pnr7VAQkQW9QSZ9RbKz6NeutIGlZKmUO5mdQ16xwBahwqNu8R6aJ\nzFDOcCmb9lKfNF0OLI6XcxQfgP+wqvCagVMsZfg/GFt8tsE+sP1EOWicGxPc\nZY4AEJmwQmTLSi7mgec//4RrTprfwgeo1uCgF7F1bW3VXm1L7olrq8HJ9fGV\nrg8TEk40xz6XaMrHBcfMIWZji4MGUuCjPaxjLoJrmUY6EXDnSrjKTYq0ilUa\nkVrKSu6y2hiNePtNXGYht0W679/Qq7Rl3KRsaoOY8Yvi7CSlSVEAgsPY8NtG\nf7ScyePGPUJtNd63aX/CAnTLw9Sr5GjhcBoIOtSVA7TjqkJhiMeAyzwtLEl+\nBR1UQD+kiqzPB4MSS6PvwlwA2WvTY8uA2uHTodn0I9zf8/EHEpaiaY7DGHLv\ns5FymDafnsw3NXS++eUgPcXVtOCuj80HgIunxfBpHxgPqN4EONBXoQ3UVzTE\nxa56O3ltQ7OX9wgAmDVSzwQ5gjX95mLv0jsq4SJMz8dGjrKMph4HhIO8GRsb\nT52D3H2erYiCUgmc8j7HTe5oPA8Oq7zJ6uKXvsN1zffo7LNlMdua5k/ROOQB\ndXgWpD/7F/Pn/KWgzc/mgxg9xp6b3X1+penz7vuTrnXPOSGLEIMybQ6xIccu\ntEp9\r\n=lkG8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"09ae7e14320aa7c03b32181662e80630451fe6b5","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.1","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.0-class_1530622659496_0.08239875735212965","host":"s3://npm-registry-packages"}},"0.3.1-class":{"name":"@adobe/hypermedia-pipeline","version":"0.3.1-class","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.1-class","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"2f60fdfe9931292ff12e6d22084a59163d89ecae","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.1-class.tgz","fileCount":51,"integrity":"sha512-ONzqwFthfBL3x+SSwS5NW1P6ksTygbfTU3oH/jeZVvE4rl4CRhJuuzQQn98vqogIHX/FWD/Z+VOMHRUyrvEIDw==","signatures":[{"sig":"MEUCIBBV4+yehAAHOYDxxKh8ga0g+J5D7xzINhAYD12GBAviAiEAg377BYsbLduCIijjhR9DoEdwkvZI90qbW3jFT91r59g=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":267909,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbO4ieCRA9TVsSAnZWagAANeEP/229esVNm1e2HABZrWdM\nAdW7c1JgJVIY1MI2Jt2ToNSGXXwjGlJhJhwK3H0yQoWrv2aWOPFMBBXB7Ge6\nWt08EHPHtHlWi6yjYHbD5G12P5veD7SBkYP45+gPo274IMtXvPelidJ6Hh2z\nmrV1Vn0iGrLjUuE8OOphlQhUAL2TVY8pa/Vpz2NGXAiVlbHf9rGPfCX4fPCs\nXV7GrLl2Pyr42r8zSm6BY/eiXdKVFiC9zWBy+wRRoIFh5nKY27stOhnuhp5I\nED0xYsBlpJfYH73FMkHAE5g1WZldPLhGYzmRkxO+fZPFDyBBnhxrXVV6xdvX\nVGOBQPhftJFP8ZrJ8WAtKQZIkf3PnTh96aidxvhDiUIxfeIMA/uWoiFDibx6\ntEjwiv6ry+1cxoShSodR4dTaHWqwrDXFoqPEpjX/u+X0nUQb1KOWYU3XI/ST\npDIx5w+e4gRoiXQqKVo8EkOEys3KvN7tEtEeyCqqe8cCpuvrdqoUIITy1gmo\n0zUyiE08Pr76KG8nu+5avSIUdIU4d5xzMRyfBFoTgPlEAgSIjQ3/TBaM4AcZ\nZDjxrLcNoVA+3qw9vzhh/5Gayzs8zi8RCjkn2all1hMnp8AL1JXUF4jycyr4\nDmmdT1G/4eUQGjeklEdqLvzc6ZWGg5bZQtip53Es/gz0TsbzzvA7CDDkWT/f\nTsyr\r\n=HAp8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"698a7c441a2196cf5d354c100ba33e70a26aaf9b","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.1","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.1-class_1530628254538_0.7977910644587827","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.42":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.42","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.42","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d800e7c00fc83c3be0c71aa826045f895e11b196","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.42.tgz","fileCount":23,"integrity":"sha512-xd9q8ARdMuH0k91/E2RJ0Ld74H1BQjINRq5Q3CiGnD7Uv9xRRtylusXFsAPhPWKHI6pTBEQkvolQYJharTnYLQ==","signatures":[{"sig":"MEUCIQCxUsugzs7Q0A3VkQI8O58Env7sHUkplJsO/9EhvfgXtQIgJCNXY4s2sFXWzKd7t7Zrp9TdQsbDe/z2JGuCQfo0Zh0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":61620,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPHeHCRA9TVsSAnZWagAAdzgP+wXzMftQE6xu0whDiMoo\noCENTAtT32nu/Bk4X+Bkx9m6/dL2P7i2q4Um2cSBZgKNgaHbLnDpbfWqe8Ah\nTe0hNMwktDRdra7Ncq052/sEKL5vjroyo9mPjFWeMUGrCUxrv0T8pccYZ+vz\ndd3eoHn2uNnHzZPSUbs5Oo3LJEynvmrHNJW77xG209AKApuXXNhXLNimW5bR\nmelGVaq6BNC8WZ5L3AiFfpkZbSt8S2DhaoOowUVHRrV5yLdQmIdlF9vAWWJS\nBGHl16O5Q/+ga5ibNDoLTcDSpyI1Smc6ujidO0XVAHqSxz+4mVHSlo1LVLbG\nVsrunZfFtJ38e/kOoGZ9rHvP5RFVAtRQtUD6e01EF6sD4SwCe/s2yzQe3xll\npugKcyq/CcPUNx7RMIhSxYJW0ecNF25kS8znRHx+/u9KMDN2HBTIYtsnu817\n3Kd7EEHPpy+hqNPM1IZ3qZ8jfVZvqW/rqDbSS8aKZcMYbpBxvB1YE6OQRwU0\nVaFfelF9eR25M/gZPOZIBorT5kqH0Cua7bFaxcjocN/ypbSFI0sL+OkMccMj\n8lxxh9/0FzT1xGHmU55aGld5YnR7jFVTKaGFGAky5s3dNAcMOxv2gWT3rUjj\n+HKHPRbBNUQurCiTHCb25CHdGr/+jWE3KPETKSmXtmSbGd6bnZSGFyHi6kR/\nsADC\r\n=NbrU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"9a7a511e9dc5b776fa1e32765bba336db0e1e33d","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.42_1530689415874_0.423630656140229","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.44":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.44","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.44","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"69873781b0f9efab90f6ea109f071277393c992c","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.44.tgz","fileCount":23,"integrity":"sha512-ETjUzuDqoN+b/ohvGUTdoSXhRl7xgEIi0m58qyZkoDIiFh3ch7JLI+XciqXVvlOxcTENE61F1UExt3G+Uv1ZUw==","signatures":[{"sig":"MEUCIQCl0KvTGa44EicGQjs2ZzdFiGfqvPWKIHlmpOuXgBcqwwIgR+4HDXieMPrnv5EomRGTPyAinCzVxINf95QbcZLAuDA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":61746,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPHzjCRA9TVsSAnZWagAA8bAP/1n6/zsVFRhW1bqJsdMK\n3LMujyL2LWSwKrBwj8tSJx/csWxTewCyayr6iEeakpk2io/L1fxpsaiahTgR\nZ11IoowV28AmTTi6HQ2oVwlS1W9IkJaF70GNrH3xJ/GLEqRhqk2Vp+owlfRj\nCTLot7me1M8RhCjvEHoLT8cNKFuAiPPjw3w1/iRX/EUKymMPXbM4+iu9L3Vs\n60kw6VPO2JXRWMD7+Xw9N6b/tGVDkNO27gVnYPvPCT+oCY9ovAEYeAAVfNQX\n0esaIh8Okuv1Yprrl1KJArHfY5sCWBXJuGkEDmGZYjMCLeqq6/Qu9hwHB43W\n4WX+ULyo72X1Xxn72zX4GecF+/Vp7E80gvqUMlgkIYJdtT2mZy1v7bbbvGXX\n86mZ0AJQCen7WpHIO/BBnwobpWIE9MLiq70GA63LVW40sF0l065sq119nRpH\nkEKA8PFu3I2NOYn2dbDMVP0mQJOSAvzDTOm0tkHDKe/8F7nlwrS8IS4HB/Wv\nZqdPwDQv22a/WGAJRJRHzE2alepATVVf9Z3air5b8hJcqad2vZvuNSbGHACL\nhGcq725UzTIFNCmFpv1MMBp1MitH0Zp0dcl7Jx6G786jBNgStHvj+U7wfw04\n4F9pgH63Z31NAURAvv2yN0M+mFuzhmsDnTLtSME61IyLWgAJhvqa3GBkmrBx\npUcD\r\n=zeen\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"0aaba3784f001cf263ab53d51fff7486af5ceec8","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.44_1530690787816_0.4484440181111997","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.46":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.46","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.46","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d5523a32ce85f228fc236842682877b706b044ef","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.46.tgz","fileCount":23,"integrity":"sha512-Ea7R3L1Wcbx06Er9nIghOTLvyfMeIHvE9DvVVJuaitOycilKbRnxNZt+IXEVv5wxrPUN1eIULS4NgV4Msd0zEA==","signatures":[{"sig":"MEUCICAsNGNp9Lj5a8Uwi31QVSO0NiHyMrIS0YAKW+8Gx+IIAiEAxSGLbtrmkCxXWVvPAFwa2LsQQV0BQKZDfjR9P+z2BxE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":61799,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPH28CRA9TVsSAnZWagAA8OIP/iO2H+3CPPE8xes/Ya0w\n9A+Q0ddXTINQ+QKU8JqVxxxjuNo+JZb1Jrpn5TrwKKodwOeWLpOsEqua39oG\no/tD58LkrdEw+NpXcZkUm6y4SgxLqYIJOHvly78suxfBbgRiVYjiwRRj+4ea\nVE2HCyZWwjuczSW25tc1Pwf27+vO7afRRjAriohO6xXgE64a6Atjwg49SvWf\nbQxZntkzO4GpwOyE4z6iVPTp5C4TKKw18Gs7zDhcBcwtHSY408v7HrCS8r4q\ngQqCS5aTwDKheLKaxtXMW0zg1CJvuQzQehwnE06XjoMJ7GqzEAvY3NeKjJg8\npfjMrNqxAxvCOMMCZsvKkSLckGHQ8BbcW3hNz+1KdPbT/ygYD1Fq3D1CeHhQ\nqqhgpyIEjfFImpF1+GFMDvTFx3j5KQs7E21xVyhzicqDVfzu0xb0AkDDeENQ\nQlHmu2lfXDSqb5wFlN80KDLV00tVeEnmNF0nNE7tibpV74JRLZp9mFq3StSb\nuY5tbjy8IX1Nj+REFjVVPO4NCK1hgMClIcaRzHUHOiBsq7of7mb4VhlwLlYS\nyWkW29FEzzC6kz8dx/OhO2kE6CN+FlHXSzceeussota8dPS0EA6bnqa2YTPG\nmuxywTxfruoITd/8fud6LwrW/BF9YDcc0uABbID5eZmCTfzjTba9E5q+DplP\n6ZCu\r\n=xoQh\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"1c2346005e1c4a1100ed52a9181bb53ad793eeb7","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.46_1530691004901_0.6828612030090346","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.48":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.48","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.48","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"b1641a0f3d286276795dc70831e205a7350993c3","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.48.tgz","fileCount":23,"integrity":"sha512-ynGIg9td507WCfVPEseBksf2CFNHStsguLhK4UshaTBKJUnibLJtwdmzKfhMZv5UXMkXFAxp02Uspt1CiGMdrw==","signatures":[{"sig":"MEUCIQDzxXzTviyARt8kQd5BLyU/NXQbcQwVqNhpydrsffRp6AIgOyBj362C5KnnbOGwU634OwuG0eO14I9pUjl2jaPpCW0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":61753,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPH6bCRA9TVsSAnZWagAAQicP/1LYpa+FpY6UXBQHQCMF\nMeeunVTlXDNJa+UFM23AlG6c1SiX9rowS9DwnfqnZuff8Jod/c035gY3jd9s\n8JmYEQv3U/0iw4EYlUeYq4yIF8VeMBs37gwTvMtx9vvL1A2Dgn5OVfxCEN2Z\nPdoljENj8iN1G7TI1+6pi79m3eLYNqRjgsx5HivoUcCT2JMdpqZE7/Id4oPW\n1uGFuZGkcWlQz/84X4K2Oxsbz8816aCN/vD8iPQ74gkVR2WcULmYgRoqsLz6\nZ3hJ2XjvWT9ehbmOK9g6wEdVlu5gD1jRf/1e/RKSdnNTPxSu0m+3eRfa/PQK\nWWY7FpraCzh6g8Kt64PZvYMy1FlGJYgKJ3GSoXkHHX/9l4CFpB2Fx9njT4D1\n5xEANXIn0b1Z65pjRoMJQvDnzuiNBCjKKCvgEIZ1DcqX3wLGRetEI8oMc7TG\nRUiTwKjiGWPs0ZSFPetROOAgHYjVY5Z/UNSpsHKxa6mcwp+7A0KgpZaN33Gy\nBPNymFs2Jtz/ENA7KYHvHmriN9VjRnHOqmEb2AeDvNAPyiD9Ee9xAxTOgxvS\nGfjdHGeOzfp3nHcop0qR1Dmmuz0r2C0bwrS221E0lydJ8zRPLx9/P868l4vw\nN6yBWmxUSWO8cyKTqCoTMo9KKKWdzuewpaHpOO0RA+QYFuv/C24TLrtLLuK7\nCA0Y\r\n=Wv5A\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"05b8f4dec038626a50b162e27b4719c761f675e3","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.48_1530691227853_0.15773328372331052","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.53":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.53","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.53","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"203d3ef2d1b232a23928e219fd286d15f8a065d3","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.53.tgz","fileCount":23,"integrity":"sha512-+i0p1c+etLl4cfXK7iqRsojh81+vVfdPiNupAWTjrAYxtxRMO7RuaggtpZ+kwXFDLuYhw6t4TRu4o7Bm9NAJww==","signatures":[{"sig":"MEQCIE4s4vgb/zubOLTQvnSnOwNMQzyu/uKcJV3mVCclgskMAiAN3eDxIDsr/jddGJIAgPOXjtZq0EFX2UEO4sf/Aas3Xg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":62233,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPKAzCRA9TVsSAnZWagAA1j0P/2q/lxwJW325xkRDAwXz\n+NdL1WaKcnx7v8+T/KVj7a5eXCq/GwFpxqlXGhuywO5SR28SnPJf1znkNuD1\nS1RM8zZLvr1AgdRSlnNCJ0LEeieh10zIHhARXIVGIAIQXJ09lJ5jfWHATNxn\nS0zyI3IaYP8/HLwDWvdVY5t2Wn5Nn/Qgcsxb3N4VYTaYChVW1oq1NnXlFwvc\ntOHtn82XLeJSJFLYdS9Zo/X3n6XBKPtyS3/tSCI1quPtiAPzjgoGO0BsfVVp\nlWLN50wRyt43a59hnnQV6zUO/a5tiSxyV/f7Ea748OfAqLVVcGU4uFCyuxbF\n9hwFjVFnWKaXa0XTOeW+XGMVyvlumoPqPOtCtxGGyWLG5LxLFAzsAcypwIdP\nlQ9MbdEXXxS7MPd5sK2ffpgv+35rhBro23R3Dc39ppznGeCgp9DhxH4t7pAd\ncnaL+eaOyHkzpXuScIZUV6phGFz3QmEKSO44tdZ7lfLkAJBrcKOV3x16FXnh\ni83zTwkOKTaTGt/3ub3cG534vlDo9oDs8c+nATxT53RlEqNDwYzzCiqG4a5Z\nftnfTklAcTgnN1nbBUnQ/4s2GTtg0+ITebRG4exe1tL3thmQ8Lgy0ktPijlb\n3W5mjpznKzmNcZhEyzirV8VcjpRLRTKe0X5o9oinxK9dALplpEbfbi3VQQ2j\nJomR\r\n=TWLp\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"a5a2cb1b8bcc55cd32e23f1f10ca2dd66311cf2f","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.53_1530699826880_0.17546048845947526","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.57":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.57","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.57","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"84536718eb2c3aeba62aec145eecd57e6e8efa43","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.57.tgz","fileCount":26,"integrity":"sha512-NfBL/ZhDVsel64cgF7b8YE2cJSXbOS+j/kqeu+eiQoWY/D/u9QpTjkHwgQV8P4sKYKavAPnPz1K/iz7cAx/UtA==","signatures":[{"sig":"MEQCIEumwxQ9kubrHOPTm0KuMNfgKrlaiYs0fH+LGdNB3CFkAiBH10tT3OVBxPE0xl2BpFtBMJJLsqXVc2uuMLavXKKTaA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":70809,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPenFCRA9TVsSAnZWagAA9jkQAIqPCPVnD+GmzCvLUwP3\n7TRXhA7fEaS1n8zEIXTJH2ymq78gbdxV+eAujHYiBz9vFsmndN5HyJnMrQ3r\nsQBiZ3rKPHXyglgoO+zw1KB48JP6P1P1jDNfBnmdQnUze0HdvJA1PIAH7qyF\ngFnC1Hxy54pAtLUJonMTf0JJP1PzgY+ewG9cnRciEaR9XK1sAYr75ngITZND\n0wsnYnKLxVODV+x/iHOAnN0xpTyWeDRfy0e99J0BMRfn6zbOz470rC1yPBcm\nesxVn1My6KtPxpcXynt5hU7MmmBbSo1KJlOtecay8mFCMMzQnaI0TZYVWPmQ\n1lJCfiZxs7PzAtKESSq4PcdqTt/Iz8FfvcemOVLYa9KG4sRysAOorRZWfhzo\noA4cDQKsytb8nraKNEcTIOdQfy3YPWiif1qk8qUMiW8KIIedOORU8kR0Sb2y\nlOXr5kuArrpgmQpyzTtFAADsUeMMn9S6uT8qvMTSaEWamJof+cAQgaOyYryM\noCJsM9MRDVvtlTMFeRrCECLZpXVHzGUTU3ylJuP0Fwvltq3v4riKKXMjPLzj\n8yHMxYUF6bmNI5S1dhSGHNRViuMwjjwWSNtFPCnyiGZUFO/QlFRTZR3GUVD7\nzM1NBOpzNtj0LdM/93VF8EVHEF67sLM1dTfQmHVRHI+2Q7NB0Whs6UkqQPfb\nBVhE\r\n=SHZV\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"306c29ac91c678840deb47b3676fb2cde0e984c8","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","uri-js":"^4.2.2","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.57_1530784197668_0.6877598581466986","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.61":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.61","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.61","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ec87a4aa486d9a5c11edb910ad92911b534bf766","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.61.tgz","fileCount":26,"integrity":"sha512-xCdhz9js3yJ0LA93Owc14zzSQxalJEs1yetXp6ffFeUBMZrlHic5ZRpqj4/MSHvS+PAkT35MnLdaSL/6fV/ZzA==","signatures":[{"sig":"MEYCIQC3iGTrSx25s3bwNjUVrhxdJ2AQkZ70D0pUXzNli4x8NwIhALywT6dFAKWX9J65OB95fHn4NR7utUNieoFkiaXSp9Mk","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":71237,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPkAICRA9TVsSAnZWagAA4LsP/jfETuSlTrQ73NctJxd1\nxF27bm/5ihE2LHyF3lM52pjTRCcXc4UjJO+enUEMaWhIYjW0BenWgh4kbhCQ\nHMmQjmBWE6sJ9ecun8kfH2+lScH15weyz2dtRGlA95swAR+Ct+fsb5GTMKhP\ntV9p5mw/yQEnhJqi1QCgPnT5b21tXdkh7wwc8fJlt9x4B+QlJNefu1rg2bt+\nCYxaQO0HgCRPC3vjc97xWyLFwkEBExz+Q/gvF86CzQ/w37jF9Y9b6/hpYPHu\ncledjbTHE4NIy3klxgNOLWqzqsIc+xsk7n/6zzI3KgXcHihtfqi0u39G+q1X\nFzJc1bE1J4OkjmIX5sQIzokUf7apiUyhIN4B33PIV5n9FOeKc+RHX+ByW7jk\nRTdh7IwFj/6KLCxyVohsHPKFf34CSi1txbvC85Tv3KI0dKXya8x8bYgBXNHa\neeD53D9ehA56UYMRMXjGe7+HoCxHZsmCYn6Y6kQukjAnl5/X/jylfnHwbRtD\nfm2BPZCjEc61vJSr7qeWKi3YhIXDjEaQPDR2TpS8YoDr9fIM2LX/rYhgNmn0\ncZJ7JuwHDLux2K6X2ll+TJVNlp3mB+3I2BHe+fnCD4FIK9HhiZ5A3LOfzeIe\nSHHWd5/Bjok6c5lQknC/xXb1tIvA9U3NVkLma5KKQHF5bQdFYXhaMbRO38Zt\n9Qsn\r\n=EYT8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"de4cf26abfbb46d404c0579f1e0cd6da2cfa3df5","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","uri-js":"^4.2.2","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.61_1530806280422_0.2387466594406451","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.66":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.66","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.66","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"66c5d72004e00594309cad7eef429740d69538bd","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.66.tgz","fileCount":27,"integrity":"sha512-ffAU/I6JeeNJhnOXrMxTRqrIlrfoZTUKuNULxU/mRk6GLkxrTv3GXy3R7anFHqCnmv8AX6waw9N1Rznrml06CA==","signatures":[{"sig":"MEUCIEjG4YmKYG0DAbFDdLhKXZ17iZmv9NV2nnuAe7J4PAJVAiEAtpUkQy6DoE8NjOhRypxnfyKtpJfnBmRZmB9WLBy/GGg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":72594,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPkIDCRA9TVsSAnZWagAA2m0P/25BbFw1KYp4Co3M6Q2e\nSAqdn+l2s6hI1lDUBOvXRGj4qUPCkHqOHv71j8WyYYcEmaDihO55IbSNPy4j\nmjM3ivUF+DPWuvLONsL4JCZ0jaPrxhgLwp15PTivIsfJhwfsvX4czJzG6qaJ\n37oT7N7v06iPSzOUvnUBerFh1a9hQgGi5qBLhynRrjLbpUsXa6N9uZumQsL0\n1Hw2l/wVKLB0L0Q8x7Z2MuoutHUDDPRBAsDd3cNOJ1PVCeNR3mjJhLL/7ECr\nHAJRVtcJ7+ptvjcXDcTgKj1USgbwuRwavdNuHBp/LB2geBbSJXPSM9IcbcIC\nhaJhZI2qRAt3rFre58+seEZurTLG4n3H2ZgK+srGArz++eZQ1xV+wpCMAbM3\npUrIpZ2cbRwSeoRQmTGadmOE3VZ/RL6GE70SgIM4XndoCb5nFfFCzebGHtuN\nrTi5qr9DrjOkKK3Nc4vhHjce0JUwviOrvAAFYz4H4p3GwM9+aH+Io1Dlseqc\nMfFqlkiC9MBdJ/OXaJH6msv+h5mNZGcw00Ay30M2SrlYcW/NGdRkuTT2t2Yf\nEjPXDDrPk2oIuLMX0+1FyMiZO2+JhUWm4LTYelWfWmLHsUSa8zFMGmOT9vZ9\n08nc8E7bJndMuWr6mOxQdwGYJSh5P0yxOLBxlqhwxet2mK/C31t7g8AScELA\nzMMk\r\n=dnDO\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"63554d1d0f1b1cafeb34adebbed099b1e74a6034","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","uri-js":"^4.2.2","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.66_1530806787276_0.9092939307088035","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.72":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.72","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.72","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d2184e190cd132b79e1f7bc7d3d7f1afd5059a0e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.72.tgz","fileCount":27,"integrity":"sha512-VO4cljnsIgdPPRpycJ5Hvz4cFRmj7ReSXWrUjs2FJo4WcCT6eZbP3L0N7kq9GPvmBNXNQ3J5N6sQrNae8vqDtg==","signatures":[{"sig":"MEQCICgk2P+YzfLxV/MQosN5PswcC8zoA2SnqCElj1t+YR/VAiAyILy1K6w7fnZpbF9luvDTnxoAd4YJZ6pPN4/2L4D+5Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":72697,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbP1yWCRA9TVsSAnZWagAAJE8P/21p9Y/eMNBhVzA6yVtU\nBmqsFV1hP6HVAa4fwGTJ9QQxat84+og8MiYum5xqHv3GwZ+Cs8/+z9O+/VCd\nfxliakWO9gAc7TkrqE3989Js+8jVFkTd5aA3gYNWuXylqAitvip9XWHWVyFp\ntnwH3phQEeJ79xUO/A2h7GOVZZXOUFlc99k3HijgS+80E3rTWB/tm85M6PAs\nNPjRUPhBlznYfrSDkdZiNbZ/ZO09xL8lDuuzDVDB8UTw/N8MyyOcoQwQmYaY\nahyunYEhEMFhUG+p3bH/JsPGu8as5QsZcyad8JYdAu2XrJFLXIeyaJKGB/jU\npBjTd5dAxTh2TYJpgQb83b/Dl4TpPHO5uBb3FnTvOGehar8sgasyqHa5/UwU\nHi/IRFPxVaciAF0Mjn0SkVjBC8/D5WrhsETPQTKDT0mrG4NbyGnghOSFMbyN\nVSJtfKjEDZtItT6rIF5IIli3r8BIquh2UaN9j0QR+oz4zr5Jus4yKYl63fhg\nc/xZuGKLCbnXbHSyF0R2dTKmM1tK2anSX/gYlMOZi9/c0hwnmK1+Q1nFxEc4\nMTr1guMk1iKZyAPTbXdpVubbhGFnDAepSuFyDp7DO71WXR9azZ0jLoOa8gut\niNhGqRM/O9vi+2u06a+PEHaT5YOpXRvJGDBEJY2PXSeV4VVZ0vuuI+e1UCxC\nRTsb\r\n=DURv\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","gitHead":"93acf83762068edaaeb21ef1c767c657a909f20d","scripts":{"lint":"npx eslint .","test":"mocha"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"yaml":"^0.3.0","lodash":"^4.17.10","uri-js":"^4.2.2","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^5.0.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^17.0.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.72_1530879126148_0.11313342734079734","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.74":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.74","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.74","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"b879a6bda05c519a18e7e737b39c665d4d83de0e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.74.tgz","fileCount":28,"integrity":"sha512-wmZLWaiYgWeyfjRr04gnukHN/4opEwGIsuRCIxoHPwdl0nb3M2ySrcWmYvEN1yzFxgf+2QCG3tupFtE9MXmGgg==","signatures":[{"sig":"MEUCIQD+eE+nGx9iok0Jkavgm2DWVOf3gBTYU6aKxozVCqvOxQIgZ2NcrdW8WC/5HUQCMuCEyI1KpOcgQrc7jsRwHWKjwz0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73383,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbP1zzCRA9TVsSAnZWagAAQuIP/2XiWayPokmaRkyDch7Z\nj7Az6+7wpgleVeaKhQFc9oOCmZy7UI/ZjA2IngqpfwmckIupg7isZpAKKb77\nTt8EoxhjMqBd2SPHqMAGwut98MQHPHwFbXTms/PPEwPILAihgxB4hRebSy8Z\n00YJ13ZhyTMWaFtaaGJj9JUqw4SiUWi8ghXsgKx1FuAIDdnSaaWD5by/nETK\nL0zZdxMpmPSF8b0cMExJ86dA1esAimeTYtraEFVbPeFgbSTdSO1DdKgfQplk\n/BbFs0+5iQe5Nb/ewR+7bzeWgx35l1CYbXtYmwHf8qvoBBB4kyD3Emxde//N\n5gWn+1erLRbWjMZU/X/8pGxrQ8U7vF5PwmxzorQR91ggPtqCbp9Pg/SoPbGD\n8wutMddLwinCCnBXIAt7zUkThtrqQsb5K3o4UGK2hlHqMQfk9loGVH0UMbqg\nHnqi0Ows/j6QxPy400eJl/Sxh+6dBm/xzDKvM47H83NQqP/WeQ2XLkIMheSJ\nkiOlDeWbtNlZ9rv0O5Hj3uo2FMnmN2IGayLhQwf3f6YS+Pc8AZ79+U+o8Zfl\nUAA7MJak+LBIvZ6x564rwDPKnaRa1CxzUh9Kc/Z1HhKLjmoYp9l6UL3u2NLS\nMIelrP4pjHKpx/v6SJL9aPgbXFy5dabYnO9EcAsrdHoR6WF+HW5EAVM0SfKt\niQyN\r\n=YlXw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"715ff5c0c55a2df5f024e9aa34f08b1432386b3e","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","yaml":"^0.3.0","lodash":"^4.17.10","uri-js":"^4.2.2","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.74_1530879218879_0.23560461922126597","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.78":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.78","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.78","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"798307528d14c27108fc38be5f00db77be597800","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.78.tgz","fileCount":28,"integrity":"sha512-PGp/e2SSk9Aff7fu9QHzCgEgbJGdVFPrU7RCeVIXSgIm5i5myUrhEpk4+YkIcJQ3DNBsHMSPtP7KpC6ckjaO1g==","signatures":[{"sig":"MEUCIDtLBmlGILAlq2T9TXJWdMgJ6VIWo5dT92lfKPLyjiXpAiEAhgTyYGan0xep3JtRC8hZ49HTbOAe4eALGx1yoD6oLnQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73394,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRrsHCRA9TVsSAnZWagAAd4wQAKHPZyR3UzNx9cO9BDiS\nopl3UBchZXEEOQX/l/YwksKp4VxScfBFd7E90QFKVydqCgAJRFWqGDqmGnMn\nJOH5HiRk5Y7gGZmdMRAvM84raTr8T9sFYDAqT1iluOYRKhR50eyR4Qwt4OUk\ngUX/sN89+BCeX9VNLDufRA/7AddqIM+RISiPu1IK92rP82/CA5Mcm+JVk3aJ\nfuCdUbYEZHsHkM9O4PKPIB9/DEHtNlsrBsItap1GqQOz+pOVVDxbNoDu16/S\n2CFBczw6sw6mpnWcXDE0G+iEnOAne8RFwzTfuRdax/rziG1JWC2zQzGYAl4p\np53V6iCzICmzjOP4evfpl/Jglh5/g4FJ3omtpkhkXcszgYIGoTn8/412EOS9\nxHdPSE25SPi7qh8V8t/jw5aLaOhTMylbEyQkNYZXNhk5HepUZdB1zvqRgC7W\nVglWNEkf3upVX3CUyIQYKlMaULgKASxM/PcdPxbCFWkD8oXD8KvK6WywMaMG\ntN9GAYy6/HixYaq5zNqQBzRQZhUf9ZUMNOmMJ5LpCNV08l4l/hiAzymGHu8T\nlCrn6vt92vSu6vk48cKRxkFjwt0leRTUL2vGv1C4aCsxHVw2W/M/b/daiQ4t\nzunD6s1kSjh2ODw/tgLxZwCsKscSW1UqLjVn6VZ2dmknAgkA09rkTFrtWsXI\n/VEj\r\n=VOb9\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"0b153a345dff01fd80ebc99cc47de45214242919","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^3.1.0","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.78_1531362055628_0.781836359684233","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.85":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.85","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.85","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"79149d1207dbb42fde455099daf76cb6169fb085","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.85.tgz","fileCount":28,"integrity":"sha512-zKuLl5Np17pi8mw2K4UH6gcG04V6o6Nz4PmpfqaeWToahSAyF0HXLo06dmOppyOWM0ClCwXGBBkmrFRNqNYedQ==","signatures":[{"sig":"MEQCIHy3PkCEy7LiMGfOx3YwuhXMgrQ9o9/NwUUtgLIm3hZgAiBXJTI1toM3XPKS4221RhQRfL4eKSaTN6STVreVKL+ArA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73394,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbT41aCRA9TVsSAnZWagAATgAP/2rOkhNpj3uF8qcm7ufH\ndQHZ3JVe4435uEgrOwF9IziMu4jWiHAkX7BmaaNwGOcNifvpV3NxoDk5fmPL\nl/n+0XoBO47fkGGtmQydK86azFDt1oEKrTE/H6WLnX1OGBVzKbxJWu90SlBE\n1tJhUJHSwBs515qAGpxf7ovn54QiozYweRENac6YzmvpN75YC1ATRbZe++yv\nu1lU/wosqkQw8eWqaqY3Lam0YTHXYMcg86kl+0Qr/OIi0cu4IWJgKLfktpaP\neFArQDdqBLsJNxkMTdcTRXQBFCN0/3TwA/rnXsJn36DIoTX0l2WQ9fNwiGge\nTTHmAGB+a7v1jDpj8Od7+FqhH/mRQUUzkO9VbSFpGff5jp8ETHRrNSjC114L\nKdnNfZ6kaRgmuTchKCXhnEDWuGmPJJILOVRzEUv1O5xLxXGgP539GByIkhuq\nZFsIoo71Zyi2e9RDplO9Pcv4ATa2Bhpdz7opRbH/oHwBpKG4bz6Zki/1viHd\nB62119k9rLrFVKd75GmvMp/pg6SwHhKPgQtsPg0Hgi2UEe+yKjmHB96aCiYu\nuy2LjjTtQcQvHGWxON91lcNd6qz5KW7yb3tAwxQjBLLYFvtBFYTnYZoXro7W\n3UkTPONPrRHLAuE0kMM68dg4Ir5ZxSHzMW7vKGaYucJ3mOxUcIUlpw1cJ9iM\nFORm\r\n=Rnvq\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"d164a7f79ba8b616937390c221e9afabe9a51cd2","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.9.1","eslint-config-airbnb":"^16.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.8.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.85_1531940185973_0.5834476068482188","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.90":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.90","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.90","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"2b3015694fcea70549368d88babb07e42e9a0a38","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.90.tgz","fileCount":28,"integrity":"sha512-OhbKmE2mB3fpJWzfAA/8WGLrYcRRxqdx02/BvVAZOqVJftaPoW8S5v4ZdO7MjQhL3SK/ZfxG6GXBEvoT7G8CYA==","signatures":[{"sig":"MEQCIEbXVH0mGYSPQ1VxD/FF6q5h8hamcdWnjwGtQiWkNG9dAiBpCg+6wiTPMSpS+NbD1+CykQGYphzqUBOSBMJ21dNDxw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73467,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcoaACRA9TVsSAnZWagAAj08P/20spQZvPkFQ6D/1RaXo\nqqVkSBoIvi53qSlEhfQ2jwjBwr9JeUHtVufcp+0fXasyNQ3Ge9lSgCyN5Lq9\nWxk5i21eDPaDCCQhRkTPGvMKRl9U0HeSrOJY66sN6pZrTdyvr4nT0+ioRJQy\nXM/f5RndAVkc9TaGmLQzOcYj6iR1Jet9KTyuFN9fiBcGD4mRh9jss1Y2oOEF\nwRESnJsBO6IdqT3tCoY6McoD082ZSJtXZjhFNSrOi4wpSUVddE1qmNmMICeb\nd77riqU6AR4v3w9h1T9zbhH4uW2j0aJsqWt1S8SY+JxG+0R5R90g7jnySRNO\nqJaYSP7y+y/N3KM/a7HvOA7b2KXNrPBOiutCWDkX1mpkm7+d7/pL8CNDUp+i\nIr3tIjkn1maNTktWoRJD0nT08twpGpg82/uZl6K/tpiwp3orUoC109CogeVw\ns8sqsyV413auh8MgaKDW1VDVL8kXxJJ8sNIufUioZobvld+ggBm8WCYkbNzj\nfZGHpCxMq5Dw/q6qTpQIIbYCTq3R0h1fk69uq34bLAvsAKxWySKj0YR9Luoh\noAm32U3J9QHgUNvs48JtqODb2mWJruWeqbXkSFZktY3/ChdU/+Z8KsQ1S65p\n4x+dH5F4ep9/n9uP27SVjLpKjdj50R98upJihKjpSEQRVvEgzIHjGfXwYH0s\ngST1\r\n=2uBg\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"ee9c5d23a1a38fabad2057062790771b11cdd7e9","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.90_1534232191594_0.7108460877340896","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.93":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.93","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.93","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"fbc968e8ecb1f8f40d222247a04d700afc2c8f90","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.93.tgz","fileCount":28,"integrity":"sha512-fxWIAnf2GTuodZBklF/x9WHu40ZayMYitH2uV/71Z/kDrcSthcYWh3wu5+bjr3Kxli7reCV4SRDKkGolOAB6iw==","signatures":[{"sig":"MEUCIBYFxSSBPvS5Y6TPnnWAurCsRCRZ7lR0RqHSd63lUvtdAiEAhCynuf1okuXeU4Iz6DmJ4pMHegLHEfkI064YQNQJdbs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73479,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbcuZoCRA9TVsSAnZWagAABToQAJppvWrn/++7Gm30tdJk\nQ5l9s0stBkRXFEP53/nMyrJpSkOn50qeaS0wmFwikxBJKtX3pO/rkF74yHcK\nF4FGbIDb8Tbm1fa7MR4Chs6RfdiLHkZsC68i7ss8I5INqaiRbqTwk506TkqS\noxOdfXWLvjqUwh3z89zaXiYb941nIGtbtEuLcsKGkFxZv8RcZ2qu5KiDTnXH\ne5QnmskZ5dVDEz5oM4erBZrXyZSihlbLRrsTLmhAoIqyO30hbKTf56Y7nbZu\n763oPAdLZtu2qm+TzNRSuunlH9SuTwgeiuNU3394vwATIngvcG/IO6n7Q9cQ\ndtMJ3V3X/WQCmHc92Ef/YogrsBmkKWDvd45qlllla3bekyH0lb5QXmCjVUvF\nOV9ODlIAZkC8DcwoJGjhPPshAKSufFdkPsHvLTRgdyAw0kPvf12iZb2kaTvG\nQethv8ww379R3ny5CYR3URXg3VNTD/Ddhlr66S6VQJf1hH3cO4KqV7g0ucBi\n2pN1rZP8h3a/3rHSbzk+Vl1G+2+j0FUvmWFyafaqHkxZWNPU1XvWwCqRbe8P\n+glGK6cBHKBwGhBLCALzfNWyDQHU3de9gW8kIBlrwLvt1XCTnJGJn5uF/m1D\nLuq8JdTjjWP9jIejc2VYo/h7nRhhh304ebsNcuCYIRZMSqFysqz1Wbu6e0oq\n/yfJ\r\n=RzU+\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"ebeebeedd13c8fdd955513c309def5fd6a50afc8","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.93_1534256744463_0.3706767281027632","host":"s3://npm-registry-packages"}},"0.3.2-SNAPSHOT.95":{"name":"@adobe/hypermedia-pipeline","version":"0.3.2-SNAPSHOT.95","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.2-SNAPSHOT.95","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"de13ddbd452ef0fa6db5fbfba23f906509a246f2","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.2-SNAPSHOT.95.tgz","fileCount":29,"integrity":"sha512-ISYK3uwBoEnywg6GS+DHcTcoDr6zseNvllbM5ihVv3yqQXiZ7nKG3n4Rn0Ri0rS2hkAxfJIX7eJ5jT688VsSwQ==","signatures":[{"sig":"MEYCIQDmuRWoIsXn2gSLA3VCVGY+8cfI71Cyv5ZEKepLOxISgQIhAK8zv/nU4WSEGChjRqJnYnyhapfwM3qckyzUNhNJtIJA","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":73885,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbeoarCRA9TVsSAnZWagAAv3QP/R5skMX6agnV8RZAHcGF\nzF6NhRc5o0R+86AykQ7zogPBdMAcyspeNSxU9Oe/jBGQuoIRIka/ReXUKbPL\ncAraP4yJ+Vx2fYQ9Ax/NIFmWkDQ4mBW7nOEgn1Zo1T2DbrygdF4LUE9YbJkv\nyznmPxkVXPO+NvpkohclusK6UpIq4jBEEdCGuMmrrT7vTf9VmPzPRIc2qUfZ\nzzdu/3pKhiyCE+fzDWfCyvFPiWgxvwjKzSly3tPzoySIZoQ4zTHpleuVvCxH\ngEXBkBqVC1pPeK2UsCsSMGBeG0W3kUvyNTDM129+zwlo6zZOYi7Sg0Rt+6pt\nqX7LtsltkedWrWKXRsAkkoT2YUehuVb9X2VutJvJKFgXrkaIUXDX7ikaTLot\nf7MV/HhIaeB1UI7lSLQsQqGP3XVt1NngD1JcDssSWMapheM2hGU+vZB/rQZh\nKJpzpEqSmr10n7ti3gMWFF9ugae8oNJWoSbVmAxe3/phDLmQOAIsKsm3EGg0\nYRq7M0MklGHT70YEVhl8RJ+jkWnn36eEnjqaG8Qh4iBXfWjg/6ZzieHdAMrL\nT2nSpxxJG/FHmJMh3hQC5yStGW3OnB0kShywqttO7kPV5sOuZ+J8f5ydZ9ad\n+a1Bq3r4DtDunAF71mSq8J6JSNIDf3JFwEHaalXeOwt/pMrnWwxOPE6UTTd4\nfsX1\r\n=Ku/U\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"c6cf77bc5de5a0ca7c048ba3ad5fe2209dad7c05","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","snyk-protect":"snyk protect"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","npm-snapshot":"^1.0.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.2-SNAPSHOT.95_1534756522665_0.6645918152078936","host":"s3://npm-registry-packages"}},"0.3.3-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.3.3-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.3-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"a53f571f24edea31e914fe163813677d72acee4d","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.3-pre.0.tgz","fileCount":29,"integrity":"sha512-RykFW5+YRidSRMQuJ+OSbhDicQGA+ckwb4bfhLaPJsJLLPYiLnEbpoL5rjCva8TC3DPKTUwU+NsSV7XWklO/+Q==","signatures":[{"sig":"MEQCIB24NNZ3TiQ+y+N9C6+pD/orL3Zuera2KY8Vewd07tt3AiB98ZHjSQ6xGDyRtYxmYPSbDRbKulnjQk3Ss+i+1NpNag==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":74439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbf10KCRA9TVsSAnZWagAAPQkP/1hOJdbLI79Q6DoG+rbi\nDgYsHtCzivW4f4F97H+qmzsDbFWVTFdWo8AJkqlKEgMdwsyJpm5LUkiX+w9X\npbqPf5zl/ZhrasdOZS+jndhASsUadUcN2kHJcht1vnTD/hqbHooy6ju3OfJL\ntnPzn6QWyk97Rc6o9fJItZJqiGf7nvpW0cV5aYc2fdKigF2r18Zn+ngqn0BD\ntM2LpZf1dfM5HfvHQ4FxyAMTtDKH35qw7rUaSP9YrHc5XlmaWjERnAf3wF9S\n0Pl2MUGWMdW7VKucpVfTTi2L0xRJUuZ0M6Q7oci3pNf7Hap1zLviIg6gAMTA\nVXQhEUqveIfqj4JlYeOkjJXqoVnwC/eVLGlhTR85mBcLJviaUbz0i+N89hQm\nEp/JuvK7sMhG6oMkukMMjv/BsnIVUatHk60Sjr+5VxTSZoNWtC+ElZO8Fgff\nOiLaTlggZFnlOK1wsVtYrx2SEonZ5eTEA/yCpczBV08qENlP3UzeAnNOIUBa\nVNqxoUdbYPUGzwJE2IN4CWFc765dTF6vxzL2N+F0pvcPjMYTkrUU4iTjFsAI\nkAQzsFXfkFODepnwXU4f5r6tPDN03FimtjC7faYXJVpFJozud7AtmrWH17kd\nKJEfR6iY00XRZ8AWQ9jzKc8Qed1rE1Q1S5vWT2w0FdPNLIm3dwP5pkhRPqCG\nn4cZ\r\n=CkWy\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"823a19d910ec9baebab6f0a3b54cf816787db646","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.3-pre.0_1535073545534_0.01777239655037066","host":"s3://npm-registry-packages"}},"0.3.3":{"name":"@adobe/hypermedia-pipeline","version":"0.3.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ebea57f037b6fad51656b807a621a4050253f20b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.3.tgz","fileCount":38,"integrity":"sha512-QKUdiHCLsOvXCuZym/ni6Ue2ugTKwBLG+unukkkKwQM09hVfXTVPSY26cmypuvSE8U61m9mz2rVnkN1jtujXhQ==","signatures":[{"sig":"MEQCIArDJOaFksmOlcFGmHFh1mlaKsZ1lXMxQFxjs7aUTXlhAiAMYeO5S53YMtOVl4mFXriAvJbb3qXGO39xMPi4WRtR3g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103996,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbf12fCRA9TVsSAnZWagAA4FcQAJuOn9iNiCjVW0tAWaY8\nyAk+uonLThTNzasgE2EYmgTgViJXHR2AVD4HMZZW0EAYDLn54eHY+TBTSLfc\ny24/fl0Rx7c+61PpquBx8vrPJOJtCe9xIhuEGxfD+xyjMjDzdVAlu9sojxdw\nrHAMCsIfFbR+JXXqqwemJaE4B7jCFL2HYIJj5a5C2EwRak14sRCnkO7kxP1X\ny7gqgtLtYmV+IiqP6fAhgpKVe++LhxrqgCVvGCqKfiYgWit7xun1dYX/RMWN\nNI/VUmmri3xdZfnCrFCpJzJflnPXgqh2TZlrFnZK0yaxWdwGAm+CbDhX8ffl\n0rC0AJ+wez6S0SUuuqIGY+aF4Bx01nThfGwpwIBvI8QbXFxIGbZn4GLHRVw9\nmGBzbm8GRDpdMH3ocU/ubjOjAckZRgX9B7g8jyTHjVkYdPV30eAyXYIVjkUQ\naC5liIzujfskcjsm+oiikfUwlYkFxdZuw0L+V+hZKgSJZH+CmO/0Ho6jeayF\nNNj6jvh33TCX30GSo1VngARUz+fLVxCivxuQx+DfpWnaeG1TA/2GPjxpDIP0\n2zBRyWja0k2mwVCyN5k18phU6Q/I+Qclf6/hU94cT4OsQvHFOI3BUdda/P+i\nUf2gRpjZUwe/OuuxvmWg188oW//ovxJF74NmxvA+Ok2y6faLD5AR2H2Ocm0a\nZaxn\r\n=hjvm\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"c3604ffcd67af3824eac3c3ef698f2d6e0aaea1c","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.3_1535073694511_0.18041487303318804","host":"s3://npm-registry-packages"}},"0.3.4-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.3.4-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.3.4-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"34f3cd11d0a9d182c4e5a963cac1684e356337bd","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.3.4-pre.0.tgz","fileCount":29,"integrity":"sha512-zZogqX2UPy76jT4wCK9secpaMVFg018IXegQRM6D6bcr0a6ocZMjIXnzt2jopcSOFKPhsWfuINmdwzV/eoFvfw==","signatures":[{"sig":"MEUCIQDs6Seuxuam1OLgdMsKZ3zNmD6tzBa2qjc56PsfVLOvhwIgdmaSO0HyVf+GinwhQ7tp2J0Fsw0uxXwOU6hKG2N3uG4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":74439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbf13pCRA9TVsSAnZWagAAj0wP/1oOR7bj23mejrdRRCtL\n+lI2ptY87RJWmH3yG+4zu+S6gzoTrcPXdkrFkiAXuMmWeyATX7j8Vmj9ffcJ\ng3VBOrNGHD1fcJIWUPaJ4v8qqekejZAoO1WqRuaoRlO6IljDDUK2470YqdjQ\n+hf2wmeaTSoRB/DSauww3yTFq8PtJqPWhT0FWjbqwyX2csxPE6tCq5oxYtgM\nMcFNoVBSOwFP/wE3UnwNPv73uUkBht/o6g7pVlFSKDpyAb+pd6kG7Rq8TpqZ\nTdMM9LV2mYQeAzDCTlUdOmq/Z1FP8F6+5MjP0QjYxSn9QXQAdTJ4mY7CZLYv\n379y1CNqp/Ab3J13C4fuVEA6t0fKayb7QuN47r+n35l13FtXUHvefNzi5C4p\npW71nbkIBDp/vwSfQ3Tf1jTXkc4usQLo0bZcYf+JCqblbWsV7zxd5OtV3lDq\nSLroA5cWgcuEjMoC0FHu2Z7kj2J3MWJsImDExwWpDo1A3uK6HUa/OlYrRk2V\nftpdVryQj2wn1bj3MjTmek6cO8OZmHfdNsm5Clu2hGGmW+kKuMg4minCiWTc\nTP2ouFjFKvmLlC2vEO/HMEsUK9iptDGt643Q7Ug8LD2wIbeqQQyMiCC8SOim\nCKA034zGzmTBb7mU+nB5+IC8KfQYWYndUZJPC9OMUTQoiV571f+FLtxF7+Qq\nNQg2\r\n=Qx+s\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"d06f912e7eafc378c2b9433f68b8ec52945f081d","scripts":{"lint":"npx eslint .","test":"mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.3.4-pre.0_1535073768948_0.99758391418615","host":"s3://npm-registry-packages"}},"0.4.0-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.4.0-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.4.0-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"187dddf41e563dec7d385a77fd2aa45d16e25e22","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.4.0-pre.1.tgz","fileCount":30,"integrity":"sha512-dmOLfWNRevNRxlAdo8OxAuCA6sl+FqTh9wg8vjwSKT+5sQTBxIRXcBtok2I05GymxGkhJXMLRhbhVZcgEYQr+g==","signatures":[{"sig":"MEUCICIOG/C29f0VoOwBQ5XAuaazFiC1/fb3d/eclwq3iFmNAiEAqTGp9ARWi1EpBAy6/xC/djbIZeguAFdEIZX5wLyDUHQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77220,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkL0RCRA9TVsSAnZWagAAxaMP/20yhqJ0Seinz7X+oOkV\nXWZT+Q7cKszjWGe1jzhkTvvzaqrLAECAMniJpW7AF41RboqUL36mB8plpq5k\naXpxX/iUpziM16gKuzmsuVmacK5cBW0g2W3wWVR7Wx+/U7D7PLzZODQH4QJf\nOBwRIiU9Jv/VBUrLOWVocrvXpMzaXE7roNXYsUB5Hsns2FTJJ6219vPjsNnV\n1Yyv86WcR7bofoFhKJGAWmI5B/5BzKCyfcQgoGinfyy5REvV4Ogu0etalx3P\nnZuEZn2PnZeMEd/ooVhfMcxlaGCfn34lc0VgyOjZTGFGm2zT4qwfh7d0bM0T\nL2ixH17YicKuDdDCxNglSiA/w4PZwy1v9nVvvjRJ5SGAPPF39zKVB8YnkA+6\napHYE3XSu3iGq++KgDSpjCRblW6JRPnT7O05ZbkPcXxtMnGkcFl9acxLdHCT\nYUJ06uTpjmkTkZl4ePtlqXb9SKGgko88jZFZXG7Yj0khukUERX6hHOB8/SMn\ne1lEm+1/UqTtBZ8rkkGDBR2XMuRpghPBQUh0/Mv7J3/q0pKJNOyd2Zkz/+XG\nIpKYPLLA3kyG2JKDjygs4KfISXU5lZwAoJmGSLQsxpLOh83yX4kdxyWbmqqJ\nOITY4hwlO+o/1FCAxdpdBmt4T/3fcODLJGyG3mZVqG24aKF5XH+IFELy+dRb\nlbLM\r\n=2f+O\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"7d7cc548dbc45705c927a10ac1669d2225adaaf6","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.4.0-pre.1_1536212241219_0.7877864711530165","host":"s3://npm-registry-packages"}},"0.4.0-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.4.0-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.4.0-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"fc3577733431b6c57820407f103e9918c7031738","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.4.0-pre.2.tgz","fileCount":30,"integrity":"sha512-5DNS2bemq5aAAw9efxs1aCvEucieYSUZv6YaGBtxgJYeo+TFHWM0U6NQiCpxxRtJ8niUYDHdCfKDLX3dmDCXaQ==","signatures":[{"sig":"MEUCIQDGn/NSra+M99/LCsjIoPgBueN7AnOCzY7r2A8R5jWyUQIgIixJg4P6aW8uprMPFHa2a+nML/eMGZy+csadS/okkbg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77310,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkMShCRA9TVsSAnZWagAAZ08P/Rxc+znoSpuxjBVth4fq\n/HNJAwl6gN86BybXpMzx6FoYzt8l1JaMFFBZ9eW4EPK796xebsdMb0TjTXhd\nzLYplEa2V7HdL2dge+/SisfaK0iRqgGGXptx955LIBxIOM+r41DZrnmL2E+E\n8iLjJb2pRTCD9h57RlSRJIZEhS1xb+jpgESQ314OFOk58+IDoI8L9FEEyWPR\n8nJvTr2z5QFVTuyE0lZO0qhSxGmxYP+OdGn8jA+JCNk0Aa559pYNLIQrPDMP\nonojJF3LMtJJy0wacD9hMY5bJOGaycoe5EUsPXabZW9QfEbo7g25I6eOa1kb\nGPdmkye47tZkLLqnH23evJlSC0HqVFqixo2/5yqk+2sYkw6kyz2RZjg845a4\nGjupIo2MFUXDBgoSBZbqcEsTIbFzw4Ch8B23tF1OjPVTsfhxeJ6bq19kovWI\ntaAhkT1oXmDB+UUI/jVwBdWeGHH7Vo2TLle5n8sKOOolZMyACpkbSgb+C9Jm\nuQzKAO3MDpJ4LgjBVe27EcxoVfIV86pdSdrjihIC1ID41yobOWRacd7TrX96\nFu4Iz/q6bttOfnAmW64KIKZwVcYh3v11A0jBGtcSUwwWHsvWbJ4WOUIAMvcb\n82MiAcf5J0yBLYklhUBjb8IRX+aKuN4G0zvYC1u1ijGAnE2tyEm8KL9FooGS\nUyl3\r\n=0GCk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"8ae6e353a20d97730b892031b25e7947f8e7b98c","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.4.0-pre.2_1536214176996_0.9625000504470007","host":"s3://npm-registry-packages"}},"0.4.0":{"name":"@adobe/hypermedia-pipeline","version":"0.4.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.4.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"37636fae1f80ed27894fb4e5b2b65b1d5c9c8222","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.4.0.tgz","fileCount":39,"integrity":"sha512-FVW/JgdaU3l8GIJz3t9PnyQTZH0ANZ0WakI1HxM1LeieUZUwQy68fnaHO+JuacTLg14ECD7yykP4f/rRX4/HJQ==","signatures":[{"sig":"MEUCIFG/DG3jz+1xc6VLceJtDP59QQ/JM9hU7DoflCW96g+zAiEA9+ukfSXB1GvdFyKIIjiWwyz1xEQif1lnK0n+YBkxSb4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":119086,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkNsXCRA9TVsSAnZWagAAkYsP/35oExnZWFwh9FZ29mj7\n3xcx51YZ2ccwfIZF365C8fU7YWmMLuLPYT6bbaRmsFZuZNSJ9oywg0ThDxjh\nzPuQM5H2HZTbMlqPldl94B+R9pUUzLFRjODVGCOyjCimzoWnvFhnWUT4p5E8\n5oQ09RoUvocQjOfDi0mkWBRVQGZs9/UHweW3o+ML32jTYciHy09Ou4+FC22q\nIsSm9xDshjgcE1YUkKVjwaHwjIQVuWz5HP8WU1yG2oIo2fUKfwsFJbmVUyKl\nU3/N4v04pxSMPqa+G/RkMKD5oi1+q2eQHJVeXhfzfqm26z1QKmmvJQucxMnZ\nPkcFARsbAz1Us8PtOr3/jx53s8eNaoX/f53johu8JtfmJG/J2tvB9BtmadZn\nS+PhWMUEySOemB5C64cLlhw91khzYvLEyN6eKXXkg/g+TWS/VaNLH+XSHL2m\nlhlk/23dn06FOm+4Va0HckuctOL7buMZfvzDreUBLn6g0DBVK31c4o/vvfsO\nh2EyN4IFwgjUeXJB5JO86M3hT/nxHUuHP+5EXIQbkdLhUrG+wOxk9xym7TYi\norl2cQkGEd6aFVi6eXmmyb3UDOCBLOjF0LjrCDLEJ1OWfOEW/BsAS4xH+WVS\noVq34MhMf+dqAuemEHqqX84Z6zGRxLGgo38ou2/S6sZ4bV9QX0ov+5KumWij\nr8k7\r\n=VoBn\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"6d069ab26343513e9a23d93d786735b1e0e2b507","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.4.0_1536219926939_0.062368988585144614","host":"s3://npm-registry-packages"}},"0.4.1-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.4.1-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.4.1-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"17ec1cf783f3c2b56f628a20903f9376a435504e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.4.1-pre.0.tgz","fileCount":30,"integrity":"sha512-u2Z6xDdzWcek3Epfrs64dXKzp+t+nnr7QG7QqY8gf1Kq2QJNgJkULPpb53C8cfXIk9nJyLaii83d2sfMjoqAaA==","signatures":[{"sig":"MEUCIQCSG6B8Fyn/ttfzHalhZwwCYsq9TXZSKEpwObvN8iRiVwIgOcRqqKmC3Md9ypv6Qr7pKAoiHm0wH+k2yc0skgJXNNI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77310,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkNthCRA9TVsSAnZWagAA/EIP/iugREhur2Q60oIcSrjW\neThCyqjmmMjC4oxHFr6iaclVX8hy6ofS4v8K1KD+cSUfLP4NC5g4cttDi2N5\n1d7tsNH+BEVWmtOjo/UQ2r0yNkFkAcXvN7s6XOfo312/JMWWqzhL1hi2+Xfy\n0rrmFAtlOmHlS7fk3zRdatYKm0rF+wY2zXsDxfy+GWFJsiGUgbh6mkVL6HOF\nO66y4+NKq9XrnLkNe/RTStk/Y+ef0PxfPltEBhlV8cH20O+ciPTk7BVDX7tn\n/ShEDmXiN+AZs7m6rv3e7bPT/TrNBaHnD8mJbEsb4wzC/vPcx1GU5srS3Egf\nyUgH+UzqWYoxmbKV+9G/+vDPpFxqudidvS53wG4AHtIb26l/NT8rXWr9qCdu\nF/HVX4gu0TM6fZ/heQT3DNow54XpTol5eOieUrN+WMGnfyVO+3yxAeVxYDee\naIL4hk0egRbit6gvUvsbYZDxuOP3bH7jKAtE0BnC9J8FZbbMnNV7NRIahL6U\nVs4E7ffHqk6fqyoLVsQppelcrCvWej3U6ySIENb3EKBzCPKq+vD0S1P2RRlG\nl+WQN0KxSw+7qG/HQ8I5JGiLMYiEgRuytXgBM2Vb920sZXMVRt0tdJ7+3gMX\nD3avnMyH2FL38nVScchrQJJIrWRBaIR6KngNGje0NC4E8oVuXeXSE1Uic3dW\n4lq7\r\n=wfiB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `resource` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, resource, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, resource, context, response} = payload;\n    \n    // modifying the payload resource before invoking the main function\n    resource.hello = 'World';\n    const modifiedpayload = {request, resource, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested resource\n- transform the requested resource\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `resource`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `resource` object\n\n- `body`: the unparsed resource body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `html`: a string of the resource rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered resource\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither resource, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"6b40a835d21bd59ce094432d5a3b603cd99c866f","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.4","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.4.1-pre.0_1536220000755_0.7101450215859157","host":"s3://npm-registry-packages"}},"0.5.0-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.5.0-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.0-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"83b989a1e1e72c8b52c608ae5b5f9daad67f2a4c","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.0-pre.1.tgz","fileCount":30,"integrity":"sha512-0eI1wOuMZaJU7NBIAEYNNO1XmOrArArSljMpL8BKkl2qYBahTJGf0dPe/UYTQuWfraUS3rhPYjIUM8Wsm5u5og==","signatures":[{"sig":"MEUCIQDqmd5sFf7VE0IErrGF0AAEJ6DVRU+39XXZoZUXgA3ZogIgSOfqMkNYkTfI+mAfKAai+haavs1aZoEEFSR+k2K1B5k=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77284,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmLfLCRA9TVsSAnZWagAA1yoP/RNvhV76iMtkIFPifV8f\nZnZrT9luiBZDmP4DfQxNkd2EiRwq8V7mAzEDruOhOcttefIRDx3BLFvAPyN6\nfFeeIdh22fF6/SRhlKJCmiOTP2unSENYPNFRgrRJ6dvnqvZHnbNbsqVgP+kS\nNBSN9h3qXlpSXBwmDvNNmC/z7EOrSLVEJrJVqtLFhS3FwDC2njsoG3CjsMct\nn0arpLFBlOM1PXTNQxeGRcyH1uZQyciuE7dgjRKjLeLDTJWtBeUzQ5B5XbE5\nui6X8xvyHLvf/VCJn6ez/oX2sniEresalBO/fTTGF979nlkxndWW6jFR9/iN\nh/hGbohpSmzc4wbOeZmllcpfquopu7uyekJGbcEbGPNbG3xWaMZO6HXaJyYU\nTV9hUiFnegOsDH9OIjsRzvPq2SeRrdllvBx5zdhTKACuIqXcJF893DvYPuH8\npeizeLlxntDD9m8oRog5Tzx3wUXQ3C4vUjMMSVsyTItU5e+J3NQkpOF5O5i7\nOcZQ5S5J+TpbW7qPeGF3srtJCX1mbAtyhoZZfI7PAV3uKX+sQESKGl604uCr\nU5wWnE1hb2qhdfEwgyTNmWyaLXtMm6zNrRwURPgYkEI7sjxPpVddlhq0siUU\nvLHWwhuCQZ+/JXzHUcRKEdXq/NJ0aljnfXV7cHai4SEF7f1iIRpkXluAgs4k\ncuDU\r\n=Nq6d\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"c149f7474bd581f464cea738e7572cbaad6b1248","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.0-pre.1_1536735178306_0.6758713669634191","host":"s3://npm-registry-packages"}},"0.5.0":{"name":"@adobe/hypermedia-pipeline","version":"0.5.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"07a39b710fc8cc76ea70c0c8ed162135477daf72","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.0.tgz","fileCount":39,"integrity":"sha512-dFwarnDklJG4HkZsERo9/Kor7x6Zqj1BDyBzA/gRWOvVp0E/uMX/ES4xEQ7/YkO5eZH6zbgK/A9BWeyUvq/OKQ==","signatures":[{"sig":"MEQCID6VI4DIrrbL00H4fwcT9aAxyEd0h26cACLGa/5BVdHpAiBu/eo9oqaszjwBhEAmHD/OoM3AGf3gJHJ4jLQOIjPPvg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":122894,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmL48CRA9TVsSAnZWagAAqm4QAJmrz+d4RvfimwlkT0bi\nkOT9LvBRKjpzGMHa97lpIxrMZ0ZSW/RG0Dagax7nvhdUoFate5/TXjtYl01x\nJYRGITwoGEzIKOQC0Cp6bpSkUBB+j1+MrHzKTd4uOdhR4tPA5DVu7MIGx7Sw\ne5/Bkv+qA1hxm0GrZPt92Kn6QpCeWIJkdMQP/Qso/MOsMPUe2z7gTIVT6BXR\n3o46AFOC+zW2NjKpSRqDb1C6ncRFWl4ixWWlt/37umFCgZcyHAW9a/I+59MC\nYtl+6YeMGKSqdjb6CIEvm1fODYRqVqRuNAZpPvak9NwIVijlwZozIaKaTFjd\nlMoEMRwIoVzWeWKthSYK9apQZ+Ini4Z2xql9Rc+TyqIzxvZ9DqJbuSiuvdKf\nqvVB6sfzdwo2l3VMYN2yb2Aa9Evm4lF96o9NBYjl9Tl40jI7sRd5ujoXNgSz\nfOCwlKGC6Vhnm7EttSAmW3V7fXypnD9YDmokLX0QOSBLzR5QmhPCB3dIYG0F\n5ueZrz6owaAyTpy7Yb94BeO91c1SoaTjLM9WIngfozjbEMEGFG5rY/IeQ20d\nZvKYtWUr1RDYcT02RaNKvjdpSZTjIAc589lqRXJDT4oKtw7tAUmNFcxuVJJI\nQyGPXt8PfcV2O5d4b6zN1xXksKpSonva8EQ/dyVQbe/rXzQcvaBWZJsrkO+m\n2RVZ\r\n=cZbh\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"16abb3f593407a70c2734e62020849fc81e6b732","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.0_1536736827779_0.6730105974935185","host":"s3://npm-registry-packages"}},"0.5.1-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"f0251db10eb5b1c61ef71dde58efe95f9117f303","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.0.tgz","fileCount":30,"integrity":"sha512-HZdipFw+wDoZW7R7E+dnw1ZdPwRbkHCeJWGY0Bk+ZauJtDfHuGWPriWHekn/iErSfZwYVuXMTxnMhiJIUzmpBA==","signatures":[{"sig":"MEYCIQDss0wDRu03DPtaK1jyhPTvz5kOOdcFPmfYzpZnUPPbmAIhAJR1xWnyrg4qMNw56UmcnQ8Pt7cwHd7XBSe2ppWogJMX","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":77284,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmL5fCRA9TVsSAnZWagAATh0QAIEjh4OdWiZ12r5lMYiN\nDlpGGDNdrz6TClC3FYM5gvzncAmlKvHAiBH8ZNGYQFxrY6UbKUZaLwo+JAdM\n+doSFq5KL6EM4NSOIbrk5oEZXNPcpi5XQUJsspGWHNYWLhzCAT6abopzTSOg\ny7nwDpX+TiATacLcHhJ+te6zEnbGmKrsaVVazw0AKWv9Yak/XnVAaTLpM3zr\nSi+T7nOT3TObKt8Dw3qKFxjhA1fDeflnQZdyhbIY71thhwfjI/3wvBjU3Kno\nWwgGlyxlJboWZPbhH1MMPrldzXZfj63MAVuIYWvvF1O83gmHSKOF2te18Gfy\nnrJGv1vbu+vybsF/j2D+kRCVKiUoXoPoSul0JLFh7B04fM03FuWrRWsljHMl\nE8v9urvI+oNU33zUAmpZAwsFcVQnuABHDb8ljkEPXDu8nhePPDa9VsJ+w6XT\nuNt5nwY/Ve0tX/NH9m2cDilPQZc2cyAJau6vw1TCQuw1wNzR1PcGMrG20uVn\nP8AlUtCfaNiGGbU77q7nPLnKepQCvQuMu3t2sRgU2Yz8iOh55fpW0kc4qZ5y\nU5+RFk1LmlC0Uv+GBmsVVj8sewdcUaCxb5FBbBlRffBDeFJhbZP5Wp5y6vUY\n9p+N0Nvmse1GpLZUhtxL0cacclanr+oISlmCzOuJ04N3pKXwDkoSyA0bix+S\nVIXx\r\n=3HxI\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"814f88a6da8cc5038f183eb25bcce3df199181ba","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.0_1536736862826_0.7089925445250049","host":"s3://npm-registry-packages"}},"0.5.1-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"275866f8d63500acb50423cd8329fe149459de0c","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.1.tgz","fileCount":40,"integrity":"sha512-AsMtIAGz+j5z0xUV7/LrOPaY7q38qKx84KGzMY1C8K/xoOYEmSofVoFgnIVa0XGASHJddSxSfbJiu/RAgkKz6A==","signatures":[{"sig":"MEUCIFoht1ztplO7JJXBoSA0Qi7vzzU/RJN1RjWLl+LxYL0OAiEAzI2/AkEX9hBStWIa0O0Ws9vUOmPtWQbtpFyBXq5fNaI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":238796,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbm1abCRA9TVsSAnZWagAA+vwP/3yoIEElE3xkYo9RGKpE\nxTvGFc42yY2CgYo2uFfCjDIDrk9X6ziXrIXXY9uFZJ5iEEWoeOWDlgNg3TSJ\nFyAuB8qZICFYbzailEsEGx1zWK/qwLr/OusV2NFv4/zHJFpMeBhy2HZ5gGK4\n478N1j2hT142sl0zvJ/A2Fev8MAm50Tfxf7SyjVzhL4hW4YEa4VetDb7HJ6Z\ncfLO2+9BnrRkmMJGImXiX53y81Nfo9w5w2XaoXqrr8wCDtIQe4bPZdyJ0qwD\nJc5nTQdBG6OkaExry1DPCDzBccCcX1GMnBaNcT1/qZQ+CJHrB8LDwJC1rgQp\nKYggAG3Rp/vpmy6Cu1Nw1f5g5NO19cY1mOVEkx0cme4CkP5IjIQyb8gMf4Rg\neKMRZ+CogtMejvsZbphI7rq+flFt0bgRid9jM5v9WsqcUNYgLgDD9psR5EAK\nPhcaxDtLxTL9fRMwklWb1MkKJevwI1ppoP8vF0kJ+DuitFa3H+4qtyCcK8Rv\nBFfnsN6g5qxBnoa0i4L2rlbOqQg475rG7kCq5Cnpuw1jotCpxPTflqj43odD\nYhDn5Af0tPY8yIINpNRaKDQW5RyVPcq+ff7rFkMAOmpBJhbmESP3vqV14F+E\nTuuSPQhR0x39NWuOD2pDsNIC3eanI0pvVodKKLXN7F1yVD61ycNjMOjCiLrc\nc1sC\r\n=Jg/B\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/parcel-plugin-htl)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"ba2c891e300d0a38c4c4a6d21f7894fd84ae93f0","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.1_1536906906922_0.37914526976571583","host":"s3://npm-registry-packages"}},"0.5.1-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"1aa2762b5c19088cb48a2a53007137830be6f0b0","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.2.tgz","fileCount":40,"integrity":"sha512-ds1k/XnYYmNb4jx3i/Slle3roUFW8hVHxX/j+aJYJcqgMhr/3ZmBXyATO2j9+ki/yzgZ3HVie6f1kFHuQTBu5w==","signatures":[{"sig":"MEUCIHzbrTuSDWRhp0YkBXA9RpKB+W77mAHKmmTN5Kv/UX2AAiEA+lI4qd7o7ewo96/Zvs2nAmjEUAUX3UuJEd4AjlkH+gE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":238798,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbn6/8CRA9TVsSAnZWagAAiBYP/RgFMm700oAQiQOsOaU6\n+LcZM7vqJ3C0L2RemyOAMi22sn24mxiCqR6B5LpoztQLHv3GcO6iKVSOTImN\nup8M/LWWo+2j09g9ZU157KXMX1Yu0qQ/0N7SZR7OKQKqkfTNJu0Ds54sTf0X\nyltVMkMjT5cw31HuvwTGb5TzL1fo2J3JDZhQS7nwqq0JzVAW6lzcjWHRgeZt\nWCJgur+AudmLkryiPknGaI8bw4UJE+NY/gSOpy3vNCRBr+ivraG+zOxtGgny\ncQetuVHXCVXJFqjzfIDJKal315D8Z6Ji2Zu/NQNUy1F/KEi8iY0qx4PwAZ86\no+2CNthgw5CPLjZcV6kRsUaQ2LIxB8Gc9EVVHWe4sSOlA/yPpYXHeB1P2R+q\nGaJfpoFA1hMLR9wrpIfr6lgK1mIIYqXncns60E5mHXnBI4jyXYtomTEuAvU4\npSa1XMrppBqReoAFp5Z01WMuGJYo60VOOH01GlukG9shuy9DtD23C4jW4LRd\n/5fyMcrpqLVWI0g5jhWmOF/a/lsuZgzB+0p9Rs8ISVIRJBLWFE5daKt6PeBs\n/LQdjMd99KGIEXXs4p4Btsc/QdPwOr+fJHWWmgu0Nh1J6Oa7i5BHNcjxe1eS\n0MSxZaIqP62QVcFxegGBzsOPn2HKUufDszpHTP93moYLHqvL8nRjIE4FQbD9\nLfhc\r\n=26nK\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"4df7e5e5f046bf9056eeca3af1703b1984810a6e","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.2_1537191931929_0.39008849322351624","host":"s3://npm-registry-packages"}},"0.5.1-pre.3":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"8a5b8e76f54fdddbfbe45ff8cda045fdccc63e3e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.3.tgz","fileCount":40,"integrity":"sha512-9f+bz2MuTyN2KN4Xu0ROiX709hoNqOAnzFe6SncQzBJ7UEffVcf99mp+iDpQAkAd7KYG/UYhDlBBv48+ZfrvyQ==","signatures":[{"sig":"MEUCID0Xo8cF6rS7UOlz7Vq2pTEwFhzl6JED/a5dAEtgM7OuAiEAvnjS4D4wp89nfnD1+T+b2kAtnNckgkcXnHPrIONjs3w=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":239657,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboGqxCRA9TVsSAnZWagAAze8P/2OE9RuNCNu8o3+MGYuI\nUtzCLGe8IpCvc3CQvCAHLxThbgCYBV7Y7yKP3xWVqO3nFL/4CdrwfpmPeBsP\nKIoQfkV/zv9SSFPTaM9T9QRsMF4wcfSpLvtMMO+d1Mh02zKhpiybpWYgZHrF\nnKXz9etC3vkpXzqzbTFF4+3HTXOwSfHiA9hSiOKXUiqjIbYUEA/uriG28FXP\ngUoxkBriwT110fezRmIhEiyegMA3tJkSM/ZpLhGneMYxJHaeuomg2rG9z2Ca\nrepdAmBEkakJEPR4RsO+9kG2IcuMcAYlOh648Q/0Dqx+JbcyOc5ebVSVQgPA\nAf5sePskTFRXrxSQ0Skw9n0hSOa5D2pLo0EbzPtT5yFTBPyzl9zFUqgPTNX1\nz2KxRXkVPJmlA1vSRA+yG3c/dtlwzrydrrC9HBqYx/5H+T57JyiuQZ+4TSeC\nSRjo5vznRdi+F2LJwb4eFjssDeguDAQEGR0oeBnihwkiVADoiSfabGTRFIks\nYMslIXtLPH0wYvPC+Dv0zJFCleAa0UhU6Kp6ZU+AUoptvqVy3GVfjGIUVsSU\n2bwQRjxHmRhTEuS4yLWwWPPT4E23T/9/MjV7Crz3E6WTrb/blLrHrTfx5nxo\nr1h7OP7Vyb5qvRSHAKq0lEHL0Wmm3ml5b2/JhtbNwbj4Rbf/Uh8ULEX1DkvY\nTuMq\r\n=HUtm\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"4ec0a138cdb7e39602bd231ec84d859aa025f658","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^4.19.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^1.2.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.3_1537239728400_0.030384458465635422","host":"s3://npm-registry-packages"}},"0.5.1-pre.4":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.4","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.4","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"bdee66e4607c23356cf5569e01b8a5413197a23e","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.4.tgz","fileCount":40,"integrity":"sha512-XPz1Y5Mg0UyPxz89IZeIAKLX1YeBl66vIGZUWfUwCOsi4OPaTfJ6Kg08NO+gl9+tKTzp3BMy0DfSXTaRYtNUeg==","signatures":[{"sig":"MEUCIQDNi40lnYcNHzfyDY0oADiSnJFFuHya6Hi0O9fsUKFunAIgb3BI8ceHxIjZx9XHCC6epSdhbJzzkxwkeRlPJ+uHaYE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":239656,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboIIeCRA9TVsSAnZWagAAfToP/2Rf18ah60paNj+bHeJA\nlDNVbDVcQT/qaXI3M+mq6YX8I0C5GPitktxPOuHXT3hnAzvE01thQjnt7NyN\naqQAKnF6r9xJRWvcO8qhv7UpCAR3SP9uVfVzXHERoKxBRRF9dgi+oDPpqmsz\nCKUufUS+RyI2eEbgZ+jBLGAAVAgidyvqZslKzNF1Asc5qR8gWnH8yhIfm+KB\nTxADh8FGbidFTxIN44UG/hgWYUpF0SdGGQlbCKNGurnTeRT4KavckGaQy5Vb\nT7jrA7ONV1Waevu2V/LFckiwkLpT/DTSUOEWVND3pEVHjb8BzfnkmLZvjlU8\n6ctNbOHXLI3LEx0KXTTwXAQmkic1l0xKFe6gz9UGNcMMYcMjwy4cqp63BB6n\nW8A6HsMh7uHIzZ6530Cn7tbIKXbAxNs7qrW8As9OCVVhO/LC5bmbYRIWESuc\n0IoMyaPLwUqpkDjGaKgocNEI6HE9wrepoKONSlwYqxcg/MWK10ARUbW9+Zv+\nsGimtZRyPFR9xxv4mXywrLSN1aRMlUgTewgcV8nrIQ8upNRDApJrDqjnZ8rS\nPC28MeByjocDMzTow8TA5CePbRUrh8v/0PDKJV0KCJDA/5nxKhxZQvezFnLY\nEvRjkyTUzDwG8X9MM/kkCtaAU9/k5/R8HjG5vQK5qgC2KrZQxQoRDciCmQAF\nH0nO\r\n=DQNH\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"9f2a1f08b95ee5df6194f7ce1b9216b85576fd62","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.4_1537245726109_0.6361947196339766","host":"s3://npm-registry-packages"}},"0.5.1-pre.5":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.5","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.5","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"57d855fc4622ec0bf1c5cab4020febd65e1428fc","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.5.tgz","fileCount":40,"integrity":"sha512-7Md1gPiwmT4YvDiyrVFxMHuv7MVe7Jojkm6sJGUJ1fqxMwk4l1azUqPdIuRkL1UfGAYgJNm+bod1yeSkcreP4w==","signatures":[{"sig":"MEUCIQCceOOMHSzlwpzHP/to3hj+GlAQWFCOpdWOV0Ovs9F50wIgQWctE60YM29AOGZbV45PwmZlSIxvbCQ2O7zsq/s62yE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":239585,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJboIMrCRA9TVsSAnZWagAA/k0P/Rk48kcilpXZb/DlhPUi\nFxrTj7dRg8qudclL4t/vei/NY4ypwrtyzB4QiOziATm6Z0YD52N9UFo+FSxm\ny/HoAeyMgjmN+2QlgzqYETWlQEruLWzd1H2+sd99nJTdgUS6liuK6qkZHihz\nyN1FQ5G/kFeFxjtuJBK0BT5a91fZElI4faDuY6uy21+eVW3CMcETuU2/4kHH\nLLaYv6+5+jLLB2Gbx8UwpDI4x8D7KqHoSDdfP6FiWDE6Nfwip9TINzyGG4I4\ntwf984G6KHnlWmyRBCC+vaQPv5y2KAqPKELyReLzt9Q3kQWUsswtHxSUWLoN\n+RiMyjexexfQGRC9ZxU44mXkFrcG5lkfSJnpYzuBqBfxcX2OqW9jovvJOrN/\nq4hOcfBmFYCk/onihOua7FVYS/JYvs6h0fTNBau9x8HyQ3REq9tM10DySPzt\nC5QMGylAXlwEZGjtXZXRQlaHAlxLNDo8iHMamIMecWD1MRbm+d1XitkVWbb6\nnMMqf6OehiEEnmqhKODnE3NmD5nOrA5wEOUU5aLL0h1TBeQGpfgsARzssO0A\n9aw/Py7C5aw3RH380laXS9jiYNt7JOrAPsyFUO1DXOpmMHd+dtCLW5yRhhBb\n/GA70edQzDOqVGZ1REzJQcZ74oOEg59rrlMIhQwg2stYS4eELlBt9Er6yqkU\nUgyF\r\n=d7NE\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"d4842eb4b4f77bc5ce9bb1b6b2f14e8cc6b8f4d5","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.5_1537245994918_0.5025440110914774","host":"s3://npm-registry-packages"}},"0.5.1-pre.6":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.6","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.6","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"cae8cfe0310940e35bf9b95a17afe3e7ba2d601b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.6.tgz","fileCount":42,"integrity":"sha512-W6dtAExi8rucgjqst9/E2PkNUPuASYhaOfbXPm2t3QUHlPP4Lc19B9OHZpJMPiZ8v81+N6iczRH5q/w21uJumw==","signatures":[{"sig":"MEYCIQC/cji+tyFWld2u7mfGjE2KEiC98YidcfZO70Og+AhS6QIhANHYc5aQ+ErVdJpL8HKnNMcAW6LkVO9kY0sf4k9NOejO","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":243466,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbpKhlCRA9TVsSAnZWagAAmr8P/jKn/lG/JPTncNRW9NeM\nrAI6g7zqbvWERg6mu8EPnu1ji64Rr+fe10UBaZRwOIqgkKxlLyis8y28e8wO\n4k1nGFc9jU4f9MvD4jN2fMDjqLzFSkVGA34PKUK6lkZz22r7CyEwywlFAMFJ\nHUu9gtziB3naMqStL7W+GzuHIGMa9FV1LkNDLvqYBGVMwjvslM+/20+KLu4d\n9wIoHHZ/iFbap/In3RWrCbdSWExGo+f5Bf+/A7XyPphfLMkzwNeXBG1X9mBx\nn6FdefW/yfet/4GlvJdrLCi9lwOpUPxvDE//pbo5qoYUeCv4NIW6Y4swCpdB\ng3vPmTkqG0a428igIBx95+2GN2izzghnmvNGVU8e1Ab/PLCRxDq1HkZvv6MU\nvwE6pFqRze0jy+sJOALwWlo3oelZzuMsWvZ7KACK46uqDwz5OLwDZboDt1uH\nBxA5r+bUqrpquvBJuqJ1IWyCcOpcXmuQeYkqPKcEvVX+7a4wBlxtuKN0iFM3\npGjUPNm0oWtvsKamY2w3zyfEX55bYPLPrlx/0H/koFNQ77/fyUilVeyhSLUs\nrluS1SFXnkj3IZSoa2BhATQvNopr3udMjkN+wWnBl/SfmkBuFZNIQFFEsaiP\nGrtwPa53eib51txtQFqefPtBMAE8cr8+msKfcOhRinR1CdF+TCqcYrddzh4M\nexq4\r\n=XiQs\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"a646f3f00744809135f9f58c3390cd522d3a892d","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-filter":"^1.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.2.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.6_1537517669231_0.9363580740881972","host":"s3://npm-registry-packages"}},"0.5.1-pre.7":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.7","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.7","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"cb1ca54e49450f98ea29ef9c6ca25b47f79f954a","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.7.tgz","fileCount":54,"integrity":"sha512-GdU88a+w4JlcKDKuAICyJ/cnKVosR8KSj7U2/xTtEimktsDKaUnDxhVGm6mSaqOg4lP2g89fewvTzdpTVl6HeQ==","signatures":[{"sig":"MEQCIEf3g2Go2a18iXttF4DHTkGiT7yowqMc5NN29BKlLsWoAiAcicxG+K+X+rV1Sq6gGyzVYfASsdjnXl7ymtW8yJcMtg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":773609,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqI3oCRA9TVsSAnZWagAAapEP+wYS8l6BYOPqN1ZVHyDV\n8cQDezeGi6zBmsvrwRbiJqMN5hR4B01yU8/NEhdLAFEmhOtgi88vXiXzF2/H\nJG8rz/ErlL5vCfePvg99vLXyZUqCkvhEO2sbYrK2g2wIApMT6Tf/qRSde/X5\npSLFt889XGSs4rqweIjSptkCSjIT7QMiwQeghe2PM4Jpbmczs3zddbacoZCs\nzc2YsuppHDFYpeFQTnUOMyRYHLKYw1DLYkufnduzZuQnOkz6vq3cJWJ4YFVS\nQP/pA1RnraIO1IP1fOIcRzPg9y/kkkfFpogl3+WPnGR5/VvcIeV1EsNymEQF\nt3Q8s/9+M1fkgUoTNglRK/n/vqMEZoauNTr+uEXQLQuPd+hsOvx5LjTfxptR\nOmtwopBNjwwvXBLfhfVCu959dOdtRJtKPsn3c0JhsYa9WJ4/S37INdg5/HOE\nyWmkpyWDDvGvG9Xy4nWnDCyXisWfONtWmuusVsOE3StFiqY/mLfO3Dcdu56S\nOiqwvdb3z/RA8Lh51VlwSdIpdXkUZ57oxP7VFtL+YtfV/k+XpBQpxeRrR5FH\nwpfYvSBLEnrdJzRsO0Q/YuUJbk1cUqNl5LYrGlKZ6T977IdkiC3FHGXzXCox\njBilNZGfLdqW8pq0Fz85QzbHpmaRFpO2eYU5/q8vpyjL3iH9qlc2itDQyoDR\nJETa\r\n=ccUu\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n- `htast`: the HTML AST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"9f51b51a92c68864cd4b3b13d006b584e65c938d","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.7_1537773031657_0.8158138808484141","host":"s3://npm-registry-packages"}},"0.5.1-pre.8":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.8","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.8","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"be6343a3c037aec5560a13d85d00b7e0051a3794","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.8.tgz","fileCount":54,"integrity":"sha512-9aC5ESxv4izgBg6lZUAFSUcm+NE81WTFqcmvJOorG9JTHISNeb4wrok7NwXU4dwZjuL1G4d2Lywdqyzeqx52FA==","signatures":[{"sig":"MEUCIQCsvuMbqgMrdhyeMJut7BZ4M28f4QpeSn/iRVPXHKCbeAIgbOdi6lyWa9rDyit5btoX7FLWt70lax2DzMV6mqSmtpc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":775674,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqJTTCRA9TVsSAnZWagAANPYP/RdILM+LfzvcZly6ElrD\nBD//fN8ZbpZAQJa0Cl1PbJ+fZUYHD4Hu1LvEe+Sav7yXmnJb27YWuWydow1M\nx7EzCsrGAHPYHWxGfkEg5hlJhX5RsT1kxjCCYd8MFukfOHN4WcRYtdWakV14\nGkwYtrKM5bJHzf8/SIzspZ/RkzZXihF1WyJGqqqz4lQFVx+8UZ4NETplcXhV\n2zVzoQVasAAjZuOxNMPaXeOgdDMbs2S1jexhkAKJ9Gzzjcch+P2znnE30EEm\n54JgYGBw1f9t7CCyp0pam1mFdTUT9RnIWpTPKgJ7YlpmGxWJ7rGYPB4gu+5l\nuYOYYJUN41h2rNePD8hVaceRumsTfe8E5VGNuAh8Lc35yPDWIts5ctTo7OuR\n7G8KjRjn66kR5mCBaPsV8i6jgRLjQFKb5lS2nItYw1PmIQn8ewTKI2RaF4aP\n5v6a6pnr7/9L2WKd/BZflkpJRc6+z/SgOlOEZ4A3zFjBPpr63yM1mtHibOki\nesKDTbreCX2uZOawTJrqaxncLj4HSfdTTFDb3mEywi9wErEkNW4cYmLUe3Qr\nqK1H+RZTQKzTGUFYxiRedIbIJevRd8A5c074Q1lxZDnYfA0vNk1r84P8YZif\nH9ZYe+efn/tSSrVT6CYDXRezev9lNdjvm//YklAl1yU8hKlQffPMRW4058rr\nMVZG\r\n=MuK5\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `sections[]`: The main sections of the document, as an enhanced MDAST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`.\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"df07eaa20a1ce12c9551deafe0450c0e548a55b0","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.8_1537774802723_0.6198183678262206","host":"s3://npm-registry-packages"}},"0.5.1-pre.9":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.9","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.9","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"dce896db987325e5c20628d0a2fcac61d1f4eec9","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.9.tgz","fileCount":54,"integrity":"sha512-pFjQ9EeJlNjJ+4YrG+3gIHITof1EkMyh5yJQ4qeNOzUXErB63zu1eJjwaPPm+8AdEi0YQwQOqo+XYVwV7XR/cw==","signatures":[{"sig":"MEYCIQDFOFjEk8tKG12IQfu8iK8MKH1qsGGdSG8u+jgZ/6tV4AIhAIdAniWGwTZdhrrpIIR7F8uqI7v1tvhU3BDGUPs55hk3","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":775976,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbqRCQCRA9TVsSAnZWagAAOiYP/Rd0+5tJXSfIubWAK0iM\nwAYADG0rSQblsSAc+4cr7ELTPvhn+GrCnL51+qNve7JYJEPttTHUxiXJHDLl\n67wUx6ETrpfq91B/EoM7KA7ZvIQTCa/rmpE2CwDogsvPcVNvbx1EpL+RI/QX\nDP+tQ7aP2N25NQ7m9sB63Poz2/W2aJrlLaQ9wLd12Bupne8MgOwEhQfPsIxm\nL75yUZmSLrAychySnHv7uw8u3yRkKObRa7AgJPq0RZRFTQePu2Il9dGyg7P8\n1gnx5wi1pzkSa7T4oeeHw1vq446439bGD4WLy91enTPwyl7G1QsfEm/3pDn/\noc2TjlEDz3FvNGPMJh9NWsK+WtJPOUh453+6CRoNMnB3HbzxHeK1Nlw0XkaG\nlyQgpRDhxzBp+EbHJe/sF5UEAUXdpwywFOiwqCgdPPQznOlBJ3fuBY8+VGPG\ndntjaeA3diZIMmRbBQ37ZVxypdzCJHvxxW34t0jdsz10oLPV55mVJ/MtEJax\nzkrmttpHowRAYNtPiUzBKtnrvz15+ZHFpSP0StqxiyPiDbFEgG5A6/azV/WB\nWOp1kp2Aif6y3JzcGZVm161XhV2ipdvPb75JXTfv/87Q8+vXP6a8YsbLkoN3\npQ6Jqneo1uqyqKFl8uZdwXBJafTW7k01R8x8V5ULMDgfBqjVthMd96iJekjF\nAkWl\r\n=qlZG\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `sections[]`: The main sections of the document, as an enhanced MDAST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`.\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n","gitHead":"42fb168e721b1d2f40e9ca192ccbf0963454203a","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.9_1537806480092_0.9147453459922734","host":"s3://npm-registry-packages"}},"0.5.1-pre.10":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.10","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.10","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"8a8a6d89fa17af86461416e0ef84084b14008d98","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.10.tgz","fileCount":59,"integrity":"sha512-uXBRoHZ9EqU7xjIr9i3LnCBHiqwQDsE8FX0TZCQE+Nw7z8hq46V8AUfzwXvzvTyK/TqLOSYf4sOauHt9Czxmcw==","signatures":[{"sig":"MEQCIDaRXHrJBAH/D4d/y7PF7QRiNHifyvGqOHKz1Jwx5WyvAiA06CJxvp3q0UM+0Pg38vV4386UnY9rqqhTw+PpaQQgWA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":788667,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrKC7CRA9TVsSAnZWagAA/EwP/j+Nqx53pg6x/b3j1Kx3\nMwwPf4Ty1VH03BS1WcYhr/Hdk6RtbR1obyszkwEgigR20WVWPVr5TWWrI6rZ\n73uzDy4DR3TlkNAOjlQfMpwAlsk2rYsSyqAuKvTs2k1WBwcF20Lpi5jqnE9V\nNBgCZX+y/bC/rr5l7WhCJtnBFVDfOPcDoV2C21HoQUbVi5MjLDvENnoG4ttY\nFfAJf14BRFfMZIsCmnBbYbBCOpLDTUByuG2G5friPbt/j8wTnszt5NXNZoEL\nGsDNzEXyt+TaNhl8C2uH4sNhpf7NE/ddnZTeBoNWlXtIMzeffowzzJeBKdyQ\nus08Z4kJgdVSrh/uStKc9IhM9oP1ZCKGTQerA4kO2S2mWRpiOr0r32kg8YxI\nxnwMB9byL7SPLqTS/X3SbLAkRP8GRltWHoUHqbWSsioB+wA+YPOYFqHc3HrE\nURwvAULtBcBODJRIqylfRM4EzYCz4RkuV2Usk5x84dgafY0iMuYuOk97bpRt\nO3g/58Y/t+na7wGUM/xieoV0rN7UKDMhSdmIdCVqHFwA1oHanF8rGMcgCCQd\npg41tXCRGm+3oeeGy8bZfgHkw3ZtFJNpWNxipSNslq8ejl/vA/p0iT1yflKE\ngF/tciz4/8ZQINIjKpM9mE3AOnATbAUSytJSUZYa77GV0d4hpeaUdy3RWSZG\n3pfR\r\n=0rmD\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `sections[]`: The main sections of the document, as an enhanced MDAST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one","gitHead":"44941273b3fa3d991bc0b48f99297a54f6c7992e","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.10_1538039994978_0.2514247600389832","host":"s3://npm-registry-packages"}},"0.5.1-pre.11":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.11","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.11","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"152235bc280946940ceec292ff73010e60e4e531","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.11.tgz","fileCount":59,"integrity":"sha512-kJgMg4GvZL5Q2iJZg17VhWVaj8LOEeF8DzOEppKNW41mamh59HU5Sprv4GvMMze74BR2VnUaNB4BlNA9GHZcFg==","signatures":[{"sig":"MEUCIQCLl8cwmmRPXGsDI5HINvGru6AmvRUewF7wPbzmvJOJigIgde3bBOgXLhMreedIvMm01J0xgwpkpp7SpQjqU7/XdI0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":789953,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrNHmCRA9TVsSAnZWagAA+OcP/2fhTCBU4pGspfp9AXfp\neVS/I0O9KaegsP4sNzQjz4vsNUTVmvfDyZFE01SmPmyqhvYbK4VaPXgvVK0q\nBE3qzLIi2XMpR69v47QAR/a67AlWNSdMN0agWxGs+6QkrOgY0bAYezN8sc50\npC2X/IxMG5QeRI8xYxuJ5KmLe3CpLUrJeUXOPlp93EWSy7cNvUrexPAK7KpV\nSeL90YajjWdXAYaXJps0cqu7y95k9KKZJ/Wav+Q3UAyTyDbqoGffYHfveWFo\nHQVuVjM+eRemOrGbRxRDybXWTOguC50RkmPK1cXA6VFlC1zup3dwuBdIeYET\nj8ztyVGVUHpFOsgVxNDbeDmJLpYaEGvWe1nWMeSMTeCos3c3kEdzdvjaZbax\n1NTSfsSw3Ymf1iDCI1JWwE4Lfm+E9eFlJteKf+CqrzYdrnbEoCMghVh6mh10\npF77mYYO5+qTeZp9FJg53PNAufCrhjyqsglssBRL3/feTKGo7VYEA+uks6pY\nmXRnTsnnyCe3DBkWPA5EUX0WSVs1OZa251CyYeVOF7HwrNDO652un/5OtAd/\nPjjSeMGDdnbtUp6PJmTBpL3LLcFiflM5AgWB9kSJOZHDiS7PMC1Fu3/bJe4i\nLS5VxXpl+g8eI6O81353ie8vXiSK59eHg/mq8muhzVeLI6NvTw9Q6tOlPE89\n4TPr\r\n=vbJF\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `sections[]`: The main sections of the document, as an enhanced MDAST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one","gitHead":"8785e6bf8cd5e391e1c19b5006e85a2deaf2b3eb","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.11_1538052581736_0.09329676810301923","host":"s3://npm-registry-packages"}},"0.5.1-pre.12":{"name":"@adobe/hypermedia-pipeline","version":"0.5.1-pre.12","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.5.1-pre.12","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"e427328623f223e2a721ce33ff3b60630ebf9bd2","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.5.1-pre.12.tgz","fileCount":59,"integrity":"sha512-C/opDT5BJRLhvrisyMuWR//D4WfVbPM+CThDBvlbZ2pz5gNxEV5UNPmYlMwjX4IURnrzc+pjS/DCLp2cnwLGIQ==","signatures":[{"sig":"MEUCIQCTSSSkK8l15jIl91cuZuX9TLcVVOuOkAppjtVyEyc45AIgYvO1vnP9iOs5wC58JyMHlludljT8wNsDGa6x9G/SOIE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":789958,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrN8LCRA9TVsSAnZWagAABgoP/0JAnMZq3j+0hXMlEc/N\nu0aBJlDM1y9QLDO7zpOK40RWPn+EI5Tl6PyYAKvP5K2Dq++G7PLiFYho/Wc4\nCGm4d3Ocr3Gaaf/spYvaSAGsKoLFPIdQI0Pef7tgkJHi+r/iRx3l6x302251\n1XQi0UdpIqOik0nKQpiGOWbMvDtVPT4DX0m0S4rzbhmXfhUP1C5L9O/vJ2kb\ntGaTCc1iElsFYSpDKltQvQMuDhdpb9AGWVGfleRMsrw//VMfUdOxfxRR4iSs\n/A+i24f648Ou/yTum/FYq7ouj/33LN6OuPIGLQG5zWz/1aUCd7DFio577JxH\n6/LE262gqSiZ3RbObZyiAE/PD4/lU5XabUHjgJho3+JeE8OFaAMFvxJ5x5mv\nMjs8cUN6BEVreC3FRB17o8W0AXtLq7/HxBcL9s+g0vxk33lA6bPHvTa5bX1B\nJw9SWJ3/u5RKgi3CLOFNS6tlx1Hw+c2ZiGuhyUbAZcdf/epOOgEYPLzKeQHH\nn7gUAuOkM/BOSNkqHP8myEgNCe5AGikBV3S4IGmHNb0xdPo1Z4+fjb7akJu3\nWkyP2XDT9An7XO7XGLuKaNtIpiBzkJ88tf5SyX/xxPPgV7VfEZbjYNtQZfJM\nbGqKRKIskWzMxdkYLSZ5xS+nxHndhi2EeBq9eqZsBCyvrFR0Mq6WNseIxmwo\nYH6d\r\n=S61R\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .pre(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .post(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.pre(require('some-module'))` or as `.post(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `sections[]`: The main sections of the document, as an enhanced MDAST\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one","gitHead":"07a360ad426222e7e1e597fdef9046bbc8d135bd","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.0","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.5.1-pre.12_1538055945946_0.47698306208280683","host":"s3://npm-registry-packages"}},"0.6.0":{"name":"@adobe/hypermedia-pipeline","version":"0.6.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"dde63e7921529dd0261bd1195177cd15335ac5a5","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.0.tgz","fileCount":85,"integrity":"sha512-xXy0Kof1qUBSd2fxMT4HdrTIxbu0pGhjns4TZPEt5cuUVK392YGNCABS1bz22fMTnz32b4sJfNw2aMrHLuAN1w==","signatures":[{"sig":"MEYCIQCPFYwkbExpB2WtchbL0MFLf3j0WNqtynVeN3I/19j3PQIhAPNgvvWraSLHTQ12QGlBrQ0aytjtukOQ9XVJFYMI40a0","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":909240,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvC7aCRA9TVsSAnZWagAACQUP/RNOKGc2+zzP8LpQNhEa\n5TcZLUQtr0sFKfJWq2urtbAsMpXh1WBuYNjgQwQ7rCteNdWIERy2P4gbgDXZ\naQ1RgWV8Jr4lvSwL1tx5OgYBnNv9LA+zzHV4QcFlOIJzQvNwveJBNxo4dQAp\niu4RJzeV37rsRuw3CiGrObE4eKzwW8OU4FzRY6vQpWfO3QT5KgSZ5Astl71+\n2fK8ZNWXdBioGjMxkKQJgGTrTX1sP+V6bbYISJ3QEMG7LOg9QAg3IEeAusDo\nv038Pio/1YiJA5mZsILfa0jPFJgG3hUy13Zx3ZN/YIqZpauAFPx/ruMZM2qL\nHYdM18BKad4CimADPsOs50pg7XoL8mlFR7dlC0sGdq3DDgIetxTjXZ5aoMYc\nBlLnPYV7qaHZzGCOTWmZQCzHYZiqNJf3+GgyYq8DzfP3p09uaPcNsL1QDMgU\nNtB69D7lZb0BViuswFLfVlh5o8JKLB2wQ5UoR31ylDZXEdtFDLnKvT4R7tLp\nLpB/tA1a+gg9idhpCQsX8jt1Vw9cqM1niftEhB8aScpJLPw/pWy7xn1wxfK2\n1xn7M2o6zPKpAQFm77Dnst7OZoZfUOUjocoeD9+ubnyMh9vzvs9yvJW/xBC2\nrYXL3Foau1Y6NJJUmRYNU8hrgNnq6UjtgJIChj/mraKt7Bc6t528JB2sGsKN\nWChW\r\n=wRY3\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"gitHead":"28e08b435c4f774c148aaf193b72998afea04ad6","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.0_1539059417723_0.8430770274200661","host":"s3://npm-registry-packages"}},"0.6.1-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"6e482c13c1df4d643c5fed524d66b3adbc4c6a10","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.0.tgz","fileCount":75,"integrity":"sha512-VrLjZTjr7X4Zq7Nvag21ouXXmcz4XXt5QhZJ0HrTZtgUdZmdNQv6R8rpQaB/blnBnooofguaZQjouCbouQ8UYw==","signatures":[{"sig":"MEUCIQCcANdaA+GsTI2cHGSQl/s3sErAi2NddRrZaBpOkqPGkwIgO8h9vdCKZzcn9aDSIXK/qel08ItJCEoDVOrAmKPgulg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":860870,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvC8aCRA9TVsSAnZWagAAIvQP/19Bx7Gz3h2ceAlKEDd/\nrBCqky8uP5HYTKXV55VxmAbi1Pm5NLQuzxl2VyUfP+OeBzVPGsJPiEd9FHTO\nDi1TQlyhP2eFf74lKERNgB0RfLhwgJvRtGD/Z8G16JTle7TscWkZkVd76Q4K\nUXvHyfL5RYFx9TySbEcnZmM59SMY3eOw7gQJzFrx5HhhAfmb18hlLLyr1IRi\nE3QLDVJ2G6BAz3TfX4MdzG8xkp2YTGKhcrtw66ErsmyEs87x2eJDWqLicQXp\n59D8j23QKDxl75R71+vlveGweZ2CppJCu1ePB9FW9a9m/RWGeRn4HriXV6XM\nfoS6pWH1Pnrc7IFp7QuPFG3oE1abNXaC1UIN29L8kcLHuv1U1cDcbewI9R2m\nIHrxTUMGm/trmMpmHeHbhw/LmFy5IWxStt5JMy9Pn/h/oYSWAd+iFxK2PUgd\nXSjzmb8Td9s45Cm4mfbmJl23CIVz01gpzuaYXGQ4Kxvu/gGjxJ82pBQJgjVX\nVJP1USGnnYduheuQKcBIcLlB64W3A8yNwASOM1fhtkBdFDPtdQegbhb6nUDQ\nxkvZsTPo7tG1mXqLt99CTtktjO8HD4Tbn0qbuoJOdKYPPECmQ2DDo0u/8Ptv\nmsFKY0VtwdaTmAvfzbD4dqpHrmh1QuUYG5FWbfv0cIOOSP/EwbTrBAnmWl5o\n39x/\r\n=wycB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"ecf89b97a3dc9c39deacdbaf4aad83586df61420","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","typedoc":"^0.12.0","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","typedoc-plugin-markdown":"^1.1.15"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.0_1539059481679_0.14084189987070128","host":"s3://npm-registry-packages"}},"0.6.1-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ff210bcc6957d349bc3fb818982dc84f8b7252cc","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.1.tgz","fileCount":75,"integrity":"sha512-7mVzz8VVckNEdixO60h5JLms9XHLIoTV61kjN1+uA4SzRF5kX8B3BPthrd3SSythd/AkiJcpx9N9B4At2QQkAg==","signatures":[{"sig":"MEYCIQCtpUzN3QQL3TeEjRhfhmpEsc6ALVZKchMYFN8Q74tMAAIhAOnpnLy6jp2MfO1+juMk1Y4V20JqPFihUg5jvlTqbf18","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":860802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvj62CRA9TVsSAnZWagAApeEP/jtJciblAOsgKp4u15k+\nwJGbxdr+7cp5InDliB6eGxWLpbpTujS5M27/pEHVljZYm+2qACzvSFH/VSHj\n+9F94KzKofIymBEdoNCuZMxoeK9OINXjducVppCi+Cmqa6qx+58VLVTGmSnM\n5+yg6BqjA3e0ZlgxdNweilrTRqlAIIQVT4zqY2qb8MAtrXCUEl6+bYS4wjdk\nx55T7gLGe8mEAn6P9UsLQPkHgN7FrrXyHVcfU0yZa5aELhREEHcAgph6nY27\n1IGLZd790BzMtadcLQrITO21V8wDnE8FpqYcrlkGBnamjKcRI3GqkTM80wSq\nz8AvtI8bO3g1uhaxZVbEIW8kVz+Xf27IXpdgT2+ONWIDIayZ/nr6UD1ud2GO\nOBb8okM3IZI3KXnbdGfrWo+35lIIYBXbB4WGAD4Zi1kFrqaKA+Cgl25Oqamw\nMyvL65SOSJbfGkbmkcOnqZInFqVK5bYlMkK8iuJF4hJsvaaTrwN0G35z47FF\n/7vY+uJZvZDvHN3WFN2L5H4BrsiIwuqwm9NV7kEFRsva5VAkVR3oVjthJs/Q\nsTVMx+ccA6zXp1px72kP8JrUfU0aC7ijBE2lP+kwUzEoo8lQBGKL0gS+brKm\nhXBoDEf5e2ogQ21EoW935G37tO/p/WIUDLGRBGlB1eA9DX5sth0/aCzJ/T7a\nQdx5\r\n=Cq4u\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"8a322d58956d01e25a73f7084d146b325d75a1c6","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.1_1539194549463_0.43838621136958333","host":"s3://npm-registry-packages"}},"0.6.1-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"808af153c7b1aad3cd08bb96068801c552c7a322","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.2.tgz","fileCount":75,"integrity":"sha512-0GGcMW1R7v1e+W3doTiTEy2Wz+ybd7K7gaaYmYfeQtwmJJFIIOWQEWAZGbm/b7ltiog6scAeWfm2WyNzaDzSZA==","signatures":[{"sig":"MEQCIBO6qRuydJ/ZKmFtMOJ5sKuOAmI94pipPbth1B3a2uH2AiBwKlU+wPDh+f++n/mZpDwxWqVuUjtkwWojirzkMSCFDQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":860785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvsv3CRA9TVsSAnZWagAAHtQQAJgjmd+99TWTgYO1Gkk1\npeNyTz3fA4B2IcHhkV4TLKaTvjg2As3Xu5F+909mmVBt2mRgdKwC1zEz8qlp\nULllvrL/+IM54y9nNj8fhvwKpXkDLdm2B77/1ZZ0VFx8DNVxQpvmfh2jUe4J\nhk+HytYm4oamSvQAeQ0CEmgwzVKEKEJohVeSyEvQIQzFtPUBejXzWy0UsY23\nNbQS3w9nld6WyjfRW9DfddlEfF9oqyv3FMmMK8WgouLDt2NYI8vvIbWGepex\nrlzeYp8713gWO28nSWXY3WdYQZV6X/lXNl4efVjYthVqvOXKQdnjMSMEfjOz\nA10pGrCC/pMjdVRXC1EdskrE9bI4LhOdBXOyUmXbfjZZ6bEj9dhGomlWPt0U\nb/gBXJUjN44m6k60rjIH4gcE+Sbbe69Ebm3M8XCziQnjKgkGUCb+BJXHLbVd\ngvG/nS2iNCYhXkSgjTPOCZmwpbpB//9UjdhlmADKrnXCKnhj6e9lxJ8MTOVO\nmgbsC8k1gQVJew2PllaxhztB3KNVR3tl7MyYz4Dz2Ix9QUVPjkZNIL0HSvUD\nYaeQTvA7rIdWwSNFxNYxUU4N7S6Hg/Ry2hwVCnlXQbrcNdLlBao/VLUUhkEd\nddqM6+X4EVekG0fnlCtzYGrDPxGf+KVUpz6aSK97iaQ+PERjax0hlu2zCd2B\nksXM\r\n=6sAE\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"0cda84b7a1ec6131f3daee643039ca3f2cb52ff1","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.2_1539230710944_0.3913909535676874","host":"s3://npm-registry-packages"}},"0.6.1-pre.3":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"4671daed3522ccb8f359466a8e72973ded8a1ec9","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.3.tgz","fileCount":75,"integrity":"sha512-6JyLXu4GLmGohJ581DHidTD3/fAlmEI91xTIJK5Zdzo6E27mpphOzHPO/xQfU8u3IjSpFBVzqf5g3QVcNwJ63g==","signatures":[{"sig":"MEUCIEG7LfsM2iETSDI7Tq7m7cCSn3GpTvJ4bd0MXVfZRTiIAiEA1D6YyVWbD92/q6jDKvVa/QIpc3WTgAuP6sizy5sYD4A=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":863420,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvxKuCRA9TVsSAnZWagAA1aEQAIAt5yrzfa9QvcBJCR/Y\nqMVuK5s8wRvlclGP4DDqaX8GS9wZfUvxNHPnnDjOZVmqlNjniCeVnl0BegKH\nt3JYQhafxSi43twiXYIxU0Wa6XzD9rSh1fOUh7K26O/hR1vpg0tFvu3WzoPD\nPMgEM43Ieeq687UxeV2ZvtF16A8TDFX78MWcTqilGN4s1X5yX8+iNZG+Knl2\nWXuEVcol5WKJfkcrqDIXIt5A5swjSGQ5n1nztsI1AcARHst49R7rBSk2scwQ\nk2VGYdGwukbBv/NnqDgWaSl7b9JKJpT1643z75L026nkLd0Y/iKukH1X6fyr\nCP1V0wg+gQPm4Lvb6KqquiKFe9JcDd+j09y6oAw/IzToJK2ihrqHAh5BBeN5\nVjpdLt1TZM34Uok5+YD8M/d1K9YgVMmiQDzNYl6FYrJ1qjQ+qaMbqzTJKnUo\nxeRvym1ZtqMJ8xvsPFItPiP0/3/7XeasnzGpLOj/5jWz9NPQuXHqHoPaL5Sb\n6zep2zuKwDTwrjQe4CGWXbhcldV39zc0i70timwijy0BeQTXydVQjLZZaM9+\n/h/ZaxjvDiGKnzZ7G02cOLKmLxh/B5NdNUlJrI1kiPlRPah4k+Rscpq+C8L1\nCK3c5djrqANE1ngNv29qmXWqEm+LMb8qoZ8i9YgdWUfDPZZ58smff0pAWFvl\n/PpA\r\n=ZvV3\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"dc5d34e5bb8840e1254900bb4b5786f98ed240ae","scripts":{"lint":"npx eslint .","test":"nyc mocha","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.3_1539248813392_0.6878858556764977","host":"s3://npm-registry-packages"}},"0.6.1-pre.4":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.4","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.4","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"3712ee9fe15ba8f7d73afd11e7e5dd64fae8b4a4","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.4.tgz","fileCount":119,"integrity":"sha512-hBqdjHhO9weGhfIXi8vvpaABkBNSA7zEsgroFkycuOlfSHrB0Hr01JPu2rgrf4ofeAQpshpIMmMwBiPMmp4XDQ==","signatures":[{"sig":"MEUCIQD61Nk0FeMJMJB1Chi+tPvTROwNTeDz5figiFXgVWTDWAIgCpij+XaPHlQ8PnV5sLmZE53b38Egiq5JiKehR5g1Z4U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":959178,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvxQPCRA9TVsSAnZWagAA4TgP/03v9QH9SX+fo4aoNoIQ\nFRU4OClnmqR3xdlVcTMQbXJAD0JxiTJTFFJXpwjE7SxnpJsJup0/eVXAZLZj\nb0TFn2p5bBOCxYYNz5L4w6jn4L8sX1k/W6oFIbyP3C2nTgfQaIHZr57ShldD\nvXRrPFkSA9zR3EyPrjqVZgjKU7TbdVHSD8nywVbnhq0CA8S9cLzmxAGys5LW\n3OxRxUL6Mp9gepv6IP4m9bc0tC6Hiv7qiuDx760zy6tNPoYUh2hWM/675VwK\nUDEx/kUrx/JRkywiItC+ThtGrJdMjMltgf8bUfRFyrk4Ri7sM17hr/spnUAp\nX26mmL0ltizJze1mGxDy7aSlI53GYYyCQi0THbB3SVLhJK+9J+mList/XJtO\nT5Sbxcazpl2o/eKA+g9PJvNLAxU0SIUmEk+jHnhPAep9pJBHMPR0EdQoC4g2\nB67KspBqAtjC5fzGo4S2BZCvPT/HDaNe7YXQYYr47oGKnRF3w+e15ilaOz8s\n+EhS33Raoc7cDK/ZQRBG4B8xvZTpL/Gj38vH8bNrxvs67dSVnmWA4jGWZR2V\niqaOiPpRnUI5S0w6iYM0hg4VdaW/QzWbzPiC2Tc/g4nZQy6M4FcWfbbLpfH4\nI2vA6knMTW8yCZBS/lgs5nmPs6oF1OggEUDe9m0FoRjNf3cFVC1qrlJLo812\nSeb9\r\n=qQMn\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"827527ab41f696f560cb9d54dfd4e02e778c1c19","scripts":{"docs":"npx jsonschema2md -d src -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^5.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.4_1539249166609_0.09416732467445721","host":"s3://npm-registry-packages"}},"0.6.1-pre.5":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.5","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.5","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"93ecb93b8423f6f905e774116b5659a4af68ed77","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.5.tgz","fileCount":119,"integrity":"sha512-N/C6w6sQ0/gBVu5THl0aOn6/NeIv3io5mj2KlL8heHxjWNYZaMJ9qzMQX3OEZqgof9c3RWNg60MpXHoBohEgnw==","signatures":[{"sig":"MEUCICGOnz0o9cboun5lnYyBCxsfw1nCAcc/pcfEQhTFNnTNAiEAhcRC1kUNp1nko+Ah19Ko8/KxmqipmhYDuZwfse8aZMc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":959568,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzzITCRA9TVsSAnZWagAAFhIQAJ7jlFl6C1oVRvrLyP68\nUZxvTp1SEfkC1Zq3/3ZE024JSDxXTUup8W+lxGj+WlQcm/GfTzQUK48brnZ8\ntH3laTARVkR3xCuTQrnf+jPD5vJdqcE+DoP/1NBTmqT9CQ7uxW0EGLTkP0We\nGDpGJIf31z6klNojkwIBQ/KbfhvFFjtdDONqwAW72UEeuSwFEWNhSQJ/AnV2\njtwMqtTuqDoXGbikqLR4HnYZ/oSvSMA/+QlGMZvkHaFvadobg9Nto7kfjzZb\nplkKTvWFDIdvEuV15tlgbU1+TH4iR9d8wahw/RSovGPN/eukqCYTUQJF3sCz\n0hqK02kJ4E7Pw1btaE7bnblVPvnRX+RCTfDPP/Dc+n/nZb4Cjgcw9/yjdZw4\n/zImWg2hHKdI+T/+N2WgB0u8eHFqzPhwLtDJEgT83vu96HsoVvfqTRgnoLuj\n7XaRkyAQ5P6gwPvMlWHr/Tpm6UwjM9KxHDT44hW/S5UWXrwq2Jksf2S+7pux\nvYSMrjFTGWh1CNnaHE2Ld4Wgol7UAPvNGqviopgdxJGH7kF4L4muzdDAp9n1\nT2Ue9fz9PvbLHfvCMuEd7Dsvl3SEaZWdW5WI2/h6qc5Zv47L1PQqRviN0vLp\nmhShy9xuXS++G1ohrQfwip8low9Z4x6rt3ICY/51DEHLJSvFPeT72hQq+4mV\npJHp\r\n=AmIx\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"a95d45741589f3076a977a009db4541fbc29ffbf","scripts":{"docs":"npx jsonschema2md -d src -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.5_1540305427107_0.9174105454973036","host":"s3://npm-registry-packages"}},"0.6.1-pre.6":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.6","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.6","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"07cdc5532634d8ce56c7f807574d62a90aef157b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.6.tgz","fileCount":120,"integrity":"sha512-RUqvbq9S4sowF9ust2hTNn74wzryeVXRhEE88Lip+O68kWlP5e7g3ic9TlhGgTdIRBIrdQedTAQ4xCS29NPQmg==","signatures":[{"sig":"MEUCIDA7cwbpfvxcSgQpdhdvfS5LgvGZRlz/7O93ExcxDR/CAiEAp23NWv/q/V+YzqqaHiODrX7UNC+HQfd2VoLX+ANMZw4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":959640,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0FCfCRA9TVsSAnZWagAAgFIP/3enSsap0LkgSgCgCJeg\nlQkmON9ijTaii9TOrFQZz8ZxMCtvmfVOs18xdBOJ/lcGpZJr8Z1+My7Uh8bN\nUa44Y4DJHVTeC2Cdwhd65CCmdoS1tXz0dKegKV/FXoQTOW+uPPa5ZHoPZtA7\nfL8CgVSUuJHDumON62XxTPDWtdO9+UUeAbyf7ApmAWvKU0tyeLVlMl+vqu/6\nj4i13O8QGRjhdr1cG7SwvLU8WlLe/79YtWSDklgBOynqj63OP/kWX7lyjFEQ\nPj9ueSy/Fc/WTncL5G+Hb6ljqsp+JE0/JX3mbPt0+9NrbMccxoGXZENdXwGP\nnn38hopIg1vJdbjfO/U1VkCRASH2CGcY0nduFaiv51UxLAIuOPTT21PJfaMu\nfgHYa+S/5Rrt6SPgA97eMUmtkGAx86+B4Oz0jExKJIDPpTgxf/RURwtFQP71\nA8lDl/jacj2llcgAE3ODCl2m6s0DHnkoNbGQYEOP/ySQ6jfCsyY3EFYAqVEj\nxrGuo1AswBLPBQj7mUS0Rdme5oV2zq4+dk5eA8GHgUReIO2oAb4iYjwrmxf5\nwmNUUwC2Ad7fTPCNM8UaJX/kPxXTUouTH87qpfEFcp/0zb+8Iyg2FjEHoUG2\nDrobQTkW9sL3AzsW0msuKneV96IMLnDK3PXX5lAoX7Ufrm7DWUP59BVXdtle\n+vdQ\r\n=TMbq\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"9d2c6ddabf682349cd868ea1cfd30ebd770651a9","scripts":{"docs":"npx jsonschema2md -d src -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.6_1540378782295_0.2790330731649362","host":"s3://npm-registry-packages"}},"0.6.1-pre.7":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.7","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.7","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"444d28c26cb2224c1bbef8155529c3c6f7aba972","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.7.tgz","fileCount":120,"integrity":"sha512-r8t8LdVawL0/4pjiDoVokis5eRqBVuWpNViGsTNHa1b/U2EFgTlsuOvQ95gfwSpVjWKYksPzjaWQYgF271u53g==","signatures":[{"sig":"MEUCIQD5Addwvldz4o62LbsuPOOEP53H7rwFWl7c58uI45J0xgIgBcjxsirVzktczUcZdWTQV0QZYp5dA4VAOxsaW5DLt3Y=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":959641,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0FECCRA9TVsSAnZWagAADdMP/jAn+a+rStJKL27Xzei1\ndc4VUZaWcya2BBDEvlxU7Hrd3OK+621XS8PvDyvuaBOc4USBwHO7WHe3Re3H\n7DJP+oLerMTTHdOvDnI4BA5xM4VtN61GH4Yd2P/Qz0T/vZgKiuZ2hskx2THF\nFS8b8ni5y7BhwOHSFrjgEh9SNkCJFDroiplT0hEnset4ZJkgKn75VKEE1PQK\nWWwvTrg1NsQoGzGEk+xs9z9E9IURD+2Cqs6WxqZiFF+dD6MRcYRIzfqzt8i+\nahrNNUPcJoRHrbsod5lds/9MFoUbA6yv2PCr7XwB0GYMQhdLvWbCXXVWSpaC\nB/gNBWmncAsZSXriQVEihojII0i4Gf6fVWA74LygK6moaar7o0yKOicLA7cB\naCLSX9q61Wc9eW01hLqRC2wtZZcpNobyK5bMbsUmpz1VIbDAV/9Btq/Swqk+\n0gNJb70imWtVZlBUoXhmPBlCqHxs0wIFg3qn3Cd8KuY9KQ/Z4POibRq6/EP7\njJQFaj3GnYoMVEWpAttC5556jSDF/ihk+RD4OBY5ye7wUBT1ju41CQnYjY7c\nJhHyPTZovysGnHNkGJRmjzXgFgz8qhHm/uhJaRFdEudQCypU71UIqt3hdcHK\nVNr5L16QRwj0GVgtOlUSk7ptTq7ycSDQb7vBiGc9NZ+KyyWIh50oYNxCNT5Q\n846D\r\n=CTDq\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is neccessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"92be16c37c20bae5b3b3252809484f72c428231a","scripts":{"docs":"npx jsonschema2md -d src -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.7_1540378881318_0.7238273408036868","host":"s3://npm-registry-packages"}},"0.6.1-pre.8":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.8","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.8","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"eb450445cde18974efab69d79adf9e59dd72231d","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.8.tgz","fileCount":120,"integrity":"sha512-7mBbrcnPyBFcAwrmNoteWCqM66//9Xr/sqiqAqbjWmeGElYKy8t0wBfqZ9IJQ36lx63oXJDpQgJm2ZNxvbLm0w==","signatures":[{"sig":"MEUCIQDesOmaAZBRxpoAyPVQFL5acyQJnkh5G/zadhg4nlDFngIgZLcSJWJ/MxwSTdEgdlzsIDCsPj2r/E5YyCEZw0ur8+Q=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":959641,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2PQ6CRA9TVsSAnZWagAAcAwP/1imNAezGWH85HnEi3FH\nQrTo8AOWX1fpvJ/OWEKMUlhXLIvFtOoFWqZKHqwJhhFNYL9t43wIsPFvtOPn\nMLhFBj6Bk7Hliz7mh2zmhFe0u09HqBwbb7cwpXlo5ecuQy2Znp0P3UZ3xA+C\nPuFljQF+mRmLvlmthMJFPG1HEcMiDyRdjmr+3ao6GCco9Wm7f5sqsdIGrYbC\nW1POWQimk+4sQ/lSuIRyRfVFj6QehzGWzEZmpNMJbV2df/cXyl7sTBlRCB89\nHcUtdAgxpe7Tzat938rWfIXzbTn9yCOoc3/r9Na5LeQ8By5kjSOiKPZAUg2b\nXw6B0f1RqvsmeC5F8lNnRPlJta4ngqKTmXKJmajFLvxAtSQ3fgMd7HMqDvk9\nQGPGSLb8o3UfVHiOJq5rMGYBZmh5OFi3aGYs/SD169zb8YILrPoFv16Zpmmb\n08xcPq1HeGyKkD3XPAfdXdlfxRC1sJdO4Vr+s51a89x7xKaxfF1/j/oHYc/g\nXqwZS2Q6EsBDloeqgv9gzgXSllXBlqWszHTkNOYY+6fMp3s0xnV9SNzmOS/m\no4FzJT0jHMognpu9J+2GpB6Bl8ILQa/iu4n6Zgx5+Pywy+2ywRE37/XitOP0\nI9C571+U3TjjKumVDQE1vIf/fuU0JN8+XBcuyt2/N5vF3mx0MrTl4WuASV2h\nkmbU\r\n=6AT9\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"e5ecf225b99f69452d38ae2997c75cd7eedb7c66","scripts":{"docs":"npx jsonschema2md -d src -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.8_1540944953817_0.7191660483667084","host":"s3://npm-registry-packages"}},"0.6.1-pre.9":{"name":"@adobe/hypermedia-pipeline","version":"0.6.1-pre.9","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.6.1-pre.9","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"90c8cdd93a67a9bb7c2c4782d87bf61e88fe9fb2","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.6.1-pre.9.tgz","fileCount":120,"integrity":"sha512-9pc7DvcTk7iSPRd91VdNS8XWkMubuJ/z5MBCTasZyba7+bRpu+YFl6hYih38Swj2x81HLDtpO9olHSTEHI0Fgg==","signatures":[{"sig":"MEUCIFUlQIQ3tXuq3bHeB0zax+XcxkmAf32ImkiUzNJW7lTmAiEAwPY/6F3Y56z3AVrY8kFNh9ht60gZjubxfMEnC31iq4U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":970906,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2TbcCRA9TVsSAnZWagAAvFYP/1mw3/xvh2kBEuw6b1dH\nRSQL+dDXibTaTafEMeoN+6pNzVWbq4aP0qfm6oh6mcDglv8Eee5zI/HE8Y3F\nCKrqHojTCcqMaHjUM6v5lcZ3BfaE/DZ1gR+kuOqMi0IClRYwfkCsYzAOQsVB\nNfoAxI5bsyHJBph9qls13owqpIAWRwblGaCydJO5TaI0zR6ufIbVSmldKRNb\nL+Gk67gHUsuvJheOx50DAWCk4qR/jmi/0KcnTgsKpamzI35OJiOQ13ZQ5GuA\n1PwE7kkp/VakZYYN0sRibsQV0dw0J4p2PzGHhb6GLWlmr0rGH24XQTVZoNgi\nZ8TrVk0idIaKyDyoorfTQ1E4398kHo99ynFrM1QQh7hywJAeu2iUnl35RQK4\nVEKgdQgMw4opgzGeMfzHl9fR4bcgyVjV+UXObU9cIAs4u+2qai9Z4xqM62Vo\ny93z0uzbZgtjsCYM5vXmRxQz0yJiv8jURv4h7qgq1dD18guMa6MLVrcyjjse\nL80yZ2HbwXMGKS1TjqHlkr0hjz2z6a+17k5PD/g4CiJnj1jePP1TWYGbcIIE\nWNXkQ4t1Hq+C1W3YXFRF1vvVuMqsj77BGl0rx9/bcIrQTI4zfIxqsB6jARhX\nUHDccd1zLbg7Cu8rtyVcQYfHOMWIyo4MQ7KdDAnqB1hMLFUEx73QQOmZZ/h8\nBrav\r\n=JiUg\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"1fdf86ca56b1389f4ccc73d67f0f43efcd41a8ed","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.6.1-pre.9_1540962011263_0.13735508106680472","host":"s3://npm-registry-packages"}},"0.7.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ce43a4ca93b590babd26e5a30dc505cf85521a25","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.0.tgz","fileCount":130,"integrity":"sha512-ZV2a/6h5iFWDW+/NoBtu/4YCo7oFd7oKLqVf0nXyxYhCEDiG0JlwW8zLVbxDo/j1UkLTdfAqefOflH2/cfqydw==","signatures":[{"sig":"MEUCIQCdgK/HEcVzmZmnkhjedV5tXLDFGSr9RqXGz1QHITd0sgIgKAvT9PG45tv2SJFPQi8tTpqmqePHp/B7IKLpz87h+EY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1020673,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2TerCRA9TVsSAnZWagAAbSYP/1xf9wHWYKndAtWbAad/\nA/OV1wSIXyApnia2/I3PoZXwM1z/4AFatmUHTUwYsEUEp6/+UnAml9QCeEY9\n8+Fq/4rFWIbvSvW7rLmpDcZhydXu9jtoxPN8UyChWJb084MbCfpCnAv2kQSa\nNLDVG9SFu5ivLn7ASeNmP7QibU4iovrPUpOeLibyZkagW1GcQT47t2Nbcd1r\nM4pMG/TseRBuGxv0gvUfeJHGmvg/AZpw9naTrr/QsavXG7Nd9J/WC/a6jtqC\nY24ve3SQ8PXQxh/KXPO583c8fsnpbYwTaj5ktMiLiiSuaGZmu08MK+Jm5xew\ncB6RewQVLTGRxinrV4ONsrem8JvKIVJzxsfEmQePWs+WyOdkp0IFAw57awM9\nRTahu2J0PYEtcSXsTJZkQKTHo3zoSC5/wrcop7FNZoW8AFqpgMy5qlYzhnNK\nnFuWlCMHwWak20hrP+M7Cnk4uAPIy92Nrnw6H+aMsS9q/xvMcE4FEjSzpwoz\npkQcTSwokVlfs0Ic0uuU57Sq7eIR+FT7F0dwO85DB6aBWJ8KAMiraXpO8ONs\no7wqhH91/EiqeNMq1NbYoY9joJ2YYpzxdnZaXe/F5FVpO9rTIt3Svvr4SBLJ\nHj9mUWlbsV/smhMCHqHG9NaIg9g9yBmGKF3gIo00kxaA00jhbfmNeuCdnV3U\nK4S9\r\n=YdyG\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"0a4bbb8908811864c792d3eb20e07f1ed4f6c247","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.0_1540962219049_0.18131426860276623","host":"s3://npm-registry-packages"}},"0.7.1-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.1-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.1-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"5c4fe56603d12a025e74ce8109ed3bd0a08b454b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.1-pre.0.tgz","fileCount":120,"integrity":"sha512-ozeTumhWwTHQrdpjVE21sUsZaQByb50uKs8YDtTub3PmIFkuWcIy13VzZn5WbEaHurQt2EplfRDBNhKFzKdAtw==","signatures":[{"sig":"MEYCIQD0gTlOiOlBHYgpB7YDlA8AdoCvE6x8TvGn5TzDDdMGlQIhAM+g9yiltOC9iRoTN2q7C4RKY56vZjmyw8Bpj0CzOm8N","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":970340,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2TfjCRA9TVsSAnZWagAAf/IP/iV9iY8vweBlzmLEw7Wl\nEJHR8574KIBI4zcUTJdKDdKoaMTp8u5Kip67ROe5LwpL5H6Dpo2yodxU0zR3\nkFUvfEesyon429eqDgyHmsneflQO3fdItEfdNf8A9YVFDGZC0q1kOF3Acodp\no1aMiUy5dBbbtRmSOvpBPslbp32Bp1+aQPL2UKynBBDbU4CblvX84t+RfXdC\nb1QdPKS11LH5ErOFUJF0gWkZpsxJri5/VuL+ddkTO54kphynSN3K5AQ3fd1f\nglZnRyifCnoZYQUqnzOwIygD48JtzFkgakY3hbIjrpRG19nfLiuujJvXbSRK\n3w5woDQ/L08AkvQGeuw88RwgsaW9XsGzwgHUgEANWuhyYxZ8avfgyjGWbjlw\nCipbTwgKsoAoWFuiqsmIfDfwatAAnhsuMce8XdwWw46U13HPN1HUkKXS4jVp\nP7KIQZOotBPKNeC1DrTXjyLGj6ZHOBGk8SvGoK8YkVia4AXordCmTZ7Xd+JS\ngYQyt9RUU2cxyaIqWTLa3N7cApc+wEodOp+TYoMcqOgTjKZZxjeoHEPTwY9q\n+XpZdTlYcKPUM4VI6M4oOskOHSlr+dExwjhdEI7Q27iQW50lScIo0dFBMY3e\nPB8JzOONWDMaiA+I2vJD2hn1osfnYcB4UkbU9WUhz40H3E07gBhnXJN1LfzO\nFJma\r\n=pBC0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"dedb6542876e82c875cb32e43542e22de609e324","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.1-pre.0_1540962274468_0.4142549418814234","host":"s3://npm-registry-packages"}},"0.7.1-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.1-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.1-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"4cb530393efaa5bcb2f23098d1f970f932f4aeeb","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.1-pre.1.tgz","fileCount":120,"integrity":"sha512-BjFlljuSveQLfLgul6YwEMW8s2ZAzsseRTTLwLi/pWpNcpP9usEGtvo0hU3ljRvRs5VGECNQNbfHRxPhdSqSFA==","signatures":[{"sig":"MEYCIQD4eNpFdObMh91GGGuD0P9L2p+CdCN+7+xy6BnVV2wAKwIhANc29e0ryLwx1UyfiAiFY9wJlsf5/gmKR8/TEwZQ5BFy","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":969907,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2VRCCRA9TVsSAnZWagAAGscP/2EBvkCLyI/1Ele6kYBd\nTHEtnCuGWLMePJOXezJBVciBvyfxTkIRpsSvi5BwIc5Sn/seAjcaV1EUulur\n8bk8gtm3I7YwqCk7jeB68PbCF76UG4Id5A3pfggszl8J9pIfLgpi0OKaNvSF\n6bBCKXLgSaY8OFyRDVxhMZuU4M1Jlel12Tl4tjPaXVue3Yh2rr8KmlnGn5Bv\nXtt1srHpfapasUfC938dZDAPzd9FX5Ch6rKXKw+0ZUFigzHMZQYbgFctFeB+\n3xHYbPDKXpQ064JzaBlwff6ejJSd9vaROFjTHvN2aTYaJdy9tzWQVmD8854O\niNmMJsSudk9aWKYGy47pzhSCozXyU3vJ0ETPd9qLskFobB5YqrQD8lDfxnfK\n4wNiQ7FxBsZUS69idqrgRJ9tGo3iw/VfUBHUW7h0Y+8CDO4o2bi3WV3WmqXn\nypVdTbzGRhhgJ43G0O7wVRf5yIRiOGGF5haxWP+TfLSJv79hzMsb7vaS4ZG6\n2iunopTfxKo3A99H7qW+1px56VXHY++5y+p6cahDLHpOXvAbrvBNc7AXhm5+\n9yE6WwuTWLLFU5FZ65kBayxxNpXDpezkzXOfaAGaBUee4Z+R1av7sBnJRR21\ngDjKLbYVijpl6wbZ/ugkxKVS5qjy0PFBSXdkpZOnQgo/Bsw8InvminA9Sh6s\nw4rH\r\n=251C\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"db6115a389e4b6e6219b08adfa1d70e7c18ba5d6","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.1-pre.1_1540969537705_0.8070115923095988","host":"s3://npm-registry-packages"}},"0.7.2-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"1c827fffb28fe79691b41a66dd8cb66a0f205837","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.0.tgz","fileCount":120,"integrity":"sha512-9Xie01pLL8PAGBLlVdhOCqkv/zZ7h1jcn1WOo5Ep3dX6UvJLBNIoChd4RPBVYlCsYgtXIWz0GnEPTaa6hvIiag==","signatures":[{"sig":"MEUCIQCo8AQUfz4gBqzH/QllYYmKGtGoHU1MXouqiOKt3oLbwAIgdOtoAJtixypghpk0oNp6+IhVQpy8FYUi9iUdA9BrYGQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":969907,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2VVlCRA9TVsSAnZWagAAU58P/i9KkYfd+FkS0wkELf90\n71sjANNokUaMU6VLT+Xi+T7CamMLx5sIfgooOt48d4TSCta7qZu20sZKGf/l\nO7AdlZ7drlmU5uWuyzw5t6xbfVT8xNGdYSkkNcOkce+2h2zkhEj9hqRpH52R\nkcGMx3rpzpDniQiN1Z48ka4vx4wehqHZgWXsTc3OkRwDhsTsYXFjnQT+xApS\nYd87RnLz1cSR8sd62yfcnhKzBZvjXygg5itqg8WQ9w1bfW/zkhIjKT4NeTY6\nboMAQsnaRJ7lvA5macVBB2j0KVUfExSEA+NwW65eukdFpyHVyTIigvvjsCVc\npizyPWlwChhBljRu0w23SGGVPMJHoMTdtdbYMJnK/PEy6wzRBmvF/rDOi5n0\noA/qkH72Y3Y6eo/nTi2zIVrDaFcLTTOiEsdFnEnSej8XCkpQoN+FPC9l1nUE\nEwYYMzjU+FrCIZXLBqtf31lQtWbTnZG8Q/YCDDQ6jBllTC3q/V8VPqUJ4QEw\nh5VFjD+w+qEoHPFGwcKpeMqXJgYwZAXRdGQqIwBOHLPs9Rq4DYD1NwWYAEiU\nOjZoB4jsvd0xcvTv9C+YIMzziFAeFjsBFXtCuQfz3H01E5YlT+GHpXis93JH\nXn4jwFRn5YH325AMnLODfNwNGVMDGGgNsf8j53FqjGldHDcwsbervMUeyGIB\nLw4m\r\n=sCPi\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"285b7085a386f18a335c563ff67e30bc46f86a8e","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.0_1540969828266_0.8814814827565651","host":"s3://npm-registry-packages"}},"0.7.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"e7d893b76671c900017e5431954651155ea1d88f","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.1.tgz","fileCount":130,"integrity":"sha512-6lZULdVXJgNybGRh8wI09kQhRlyPWhpIlybDh2Pn0xAEZcSFHVGEakVPIg+0cXe0LkoOoLATupnGJ0jXYWIJXQ==","signatures":[{"sig":"MEUCIQC+1utdalTh6AN6LYCy5PU1jzy6tlneDvdOS3s9zW8EqgIgH7D55BM358dWdlDbPdHNQz2fRNUdANioZFxEWMZM0C4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1022826,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2VVwCRA9TVsSAnZWagAA/14P/3s0DPfPVPRBy8E1i2/o\na8wbgYc6qfm1AZUywEaJZO6XMnuFglhnkFp0criQAbecFsVnRy2QKZrr/IwM\nqepGD3h3NEwKb8DjxDQDab5icG9j5S+0pPXJbWDB3sMqRhoBXs74aDqS8Ps5\njt3aH7fGSXsDzoYzxBB9yj4uc+NZkeyPzbhzI1YdAUkAJGzrUQ2/upaYVaFZ\nh85ck6P0LrQwT/Lb+b+OoSpc7wQgPDtLWranGklBu8xifvYRhLuDcyjZHJpt\nHDeDxo5WOabzU0lIkGifdfOXkNJJSyuLCJMohG1CCAgV/TXuTwBuOuf/n6cZ\n5HjB3sguV6h1M1ol8ZKRqSS+BKg3y8K8/ggy2MX46akWAD/arYjUbP8tib+8\ndYve7SXYpwzP+3nxkZTYz3pqRAsEBisjd7jJ1CgA+mzdU4Ov1Oufe3qQZU7P\n95hp3c+4qwRx1DUWKpmaZhn/3O4NiXSTxTV+DqPDJr6Je/q7pU0J1odlS0ax\n5edUiZyZSF1dJyv0KR/RdxC13UpxaUxIqe6Kvtmcy4jeUZMa+xCTXZdRlG1s\nUrEb8pnEr5r3CYGedGdhYLynZGq/L7C3TG13Ibb3rnFWaknTZsdC4A22w3wn\nfNjKRETNGj21MQLxTOfJU/GGAizOGpGFuU0hm/vZrStAzqIXdfpvExxgPQwA\nc9g6\r\n=4IYa\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"63ee6205d80e2b6f5eca292b06f0c4cce0b905ae","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.1_1540969839455_0.9874204216580271","host":"s3://npm-registry-packages"}},"0.7.2-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"293000d47a896c0427f2dc9ac9011a1e689dfa11","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.1.tgz","fileCount":120,"integrity":"sha512-KVNdgB1w2QqaT6g2e4o9P9oLPxnx7aSoZg3Ed1FNaKBOdqQrrxCE6/S/fEnbrvxaDAuX3zYF/oLIOWR8cmENFg==","signatures":[{"sig":"MEUCIFGbq8UXAghJpFSTD6DWYsidwZ5PKChqnP5B6WC3JJDRAiEAptyAV+AcCmzDah9gchAj2qZvCYZN4mcs+EFcYU/AUck=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":969966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2VhKCRA9TVsSAnZWagAAaQ4P/02qkLCpoAtwCwre+ORZ\njzVaugaBdzC0zaQsDPiC3uxb5nSkbK8RUvD4vb0e5LTxESdi6hxoWGkHhNLi\nK6upNF2jVHYCk6TC7dADfx7p4862tfdKKYxVNNj7sWk6WRXTP1OslasNePCs\nGxsaP9ltx3j4d1DpXiCSnHqfvT4HciDNpVys2yxOIbvgYGF09Zm8o8cVm7HD\nSZNXCJKO3b5ADOrHpQ+5Q/mXe+wG6I0eILg3MrCwugYbY2/xCOr7jJ0kU0E/\nr78mk2lVJ1ZPYPxwKak11RGwORICLDraA2xRcrTbNxVTscg/x2LjhfwYerOr\nhciVO4Bjzo6UYEYwOOWmoGD7wgmB4Gsg3yHCG7nnAPVcbZxEaFN1MEEdbrwG\nVHwmGqJKUJyB/7UNIeGAfhenqnk3snBg0CRyFeg+Cpc4d/qHxHpgOK//RSUh\nO/CUx5MLa6raG3BmralPwHjXOGu7IsKrQtm+UlgHowUhiYvKLxtuIu6i+hf/\njuaceRCQAaR/VK5MzN77LYg0x0JCKKGY7mFqOPbQ5et4MbVBcTM2zsylDwN6\n0CHpIwOKxo1Rt3xV5D6CDpHesdIb4fsNWoYM18DAUhqtKv0wGaNH428AXl+Q\n150h+uxVmD9suIBY4RIMFny0AUq0BLxrBFTeHUMUz+VnonIq2ittPCu+JpHP\nw7Sm\r\n=+Wak\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"37c5ce3b500137093f6cf2aff5252daf956e0824","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","bluebird":"^3.5.1","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","tmp-promise":"^1.0.5","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","request-promise":"^4.2.2","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.1_1540970569308_0.11720499076857904","host":"s3://npm-registry-packages"}},"0.7.2-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"4a697608f0c22940ef8c4017ad3a771fa56442cd","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.2.tgz","fileCount":120,"integrity":"sha512-9OUzT923xYKtZ7y7xUygUSRmCZuC81GNz5rSuhu01HSXFAdIyd0yqXRPJ692qioU2DiO1HuJ8B9fAldCSrtN3Q==","signatures":[{"sig":"MEQCIHMFX04ceoDCoxjE/QCzT8WYD0bCDZg5Yag3QEQsnqfXAiBD3ikq07VCkXq3cr56NrcP5tT/VIZK8j+DcLXxBpXOCw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":970322,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb2rIoCRA9TVsSAnZWagAAWBkP/i3PcO8CafT0/SnPiOwB\nDtCCo+HfNv1949H2rsUC2yf91io0ZC6IjEYZ0mvfpkWO0D5N6LiglGy8UX+j\nUNmUN4Ge+uTG0pWkEU5euq2+9aYjn8I8YzxZmA2ocSxrHosLzesCBNuFbVQX\nQS2R64cGCu6IEQx+k/qVnbMJozDQFYfRMB3Ag37xRp48UXXoBSBpB/Lg1gsX\nvQGsPqiKpBgD5xRvmrvSuNdr+dkNsRF8Yq2+pAs0bCGUAXAVK99v9nSyrlV4\nnBbi5vMMTh6rjFIDNvgD2ers5Z8gLVXE7GR/uX1QsuivKmmwz8ajLJfgacrL\n+LDK4nXE9tg2W/oUYB0eeDlCWwFQjWbWo5Cy9rT5cPeaPVlr42C3zl+hZ/NL\nIPLq6i1o6udvrngh1bk/8YzytuDvkJwxzPebR6mZFCIZN+xGazq96JvUxEvE\nXO08nfxoA338kBs8E5zeKPrXuqFGZdxAkLmEAalZarEYMxVP0c6vSQD5evQD\nSb4vrdlfMcZ6uaartRnBKG/WZQH2HbYBsgE0t4/bN1jY+U4p+R6wOUJivan1\nJeBmk/x6cGdKoBUhRxBy3wqs4nIyL/xJNPxjpBZXRYdki2L43lnsYIM3cDTt\nZA/hdh6/GoxYFksZ2lN1s8dHHyye97jhPqmS8bySDMWL8fqShDUtRe4joODF\nzy+j\r\n=NJAF\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"8304986cad31896ab36a2d4d1be181a91dcb2166","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.2_1541059112003_0.24926508428675875","host":"s3://npm-registry-packages"}},"0.7.2-pre.3":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"77ca7f342580f8790b4df216eb8b8b85b741f668","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.3.tgz","fileCount":121,"integrity":"sha512-Pj1Jay6iQGOUFHWdCdvhzlLshLhfLsnRGFlN8fBzKgrW7/h71Vy5T9myIwWAa3nG8NvW5Y5yLPsPHnpkU6HwjQ==","signatures":[{"sig":"MEYCIQDz9dF0kPe1HRAMsQXGO1RiIObJoMf0KX6BG8H0lXsHFQIhAL9iymwt9zVVg7sXX19f+jfcm7AyMU/EnieEsnvvw5aT","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3EvGCRA9TVsSAnZWagAA7K4P+QGnP5a6OJj7rT005Uy9\nS9xG4N8dyDOt+UUeathK477uCTIjlttvZHeCCkCyUlXobeZWLozGvItmuC1b\npsVx7ach4EBiyjIqWiPxx5tJfyzg/8FiJI2Nh1wJArV05lNf8zFaZUMOp2U5\nTTPuL6tPAJ4rb6PNVT1ZrKxsdcZ7w0I2EVXn3rwUQyAJTNciXj0PI8RsnxUb\n2dWEnEpvxdYmpzkIVEHwmHostkq1wQQA1n4i2W6gl15L3bMqxNznLWjgiirx\nm0FgbO0UYJMLDJsPHjQ7LzJ6AKeDsMvgsUkVO5WuzKd0aZscxXBEbZhW1jaX\n7D1wLHbxPTxj6ryeNXvnWnTgY3rrpuYeie0uMIDYCiS/ocM1HreADN8L1r7T\neiFBNFqrYaeo+0AIfQuJNmjzfjmxU3LmwEWH1BU+liA9SToY/GUg+MnENDPc\n+rreXNxGxKaTrcFe2IHIpKMA9yc0lbfVDZrl4fM31NAsvD7XaPbrmbwXd9M6\ncBwG6LHe1mECBg/njsHUB7jNuLFeS5Ib1Quw5dkQXio/v7KD5Fpb4M8eyHsj\nP4xxUS9Bpj6zydbPiLwLv46v8LXIWq5xT1+sz7Y288wnfk3kTO4kenZ1+uwe\noOyhZiKEpPZ8cV7o/jTsEKqiOgzP1mma0fUWg5OkO+anux7FjqUYnDewnsGV\n+yWn\r\n=Hjcx\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"6a7bc1901074eb99b442bd5dd8100cdba0dcb9dc","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.3_1541163974146_0.4055075286317882","host":"s3://npm-registry-packages"}},"0.7.2-pre.4":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.4","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.4","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"a7b6358b2fbec95cb75a5e98464f00d049453f68","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.4.tgz","fileCount":121,"integrity":"sha512-sH257363595l5gXeMOjqDffTXHyw2jYoiJLM5joB8sv4aOu6o8FUU0364bSCkkYW/VN/nTtT6/35LWUjbbSNaw==","signatures":[{"sig":"MEUCIBgrDuM/HO+QmQdDSxxIZmLM5b5yShL6BGizpdOkk36uAiEAkY9lxhQGyMvY86MQUo2FrcVzwaxNEeEzmcvIONFZCzs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484479,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FD9CRA9TVsSAnZWagAAbDcP/RO9KIwbHp7kLiF17bdv\nfh0oclMli23dQEdgbvfcmNhE4+bgWrkkz8is9XEr6Dsat2T7BWifXQyZuQq5\n3rwxgjRMLHcX1jH0RflUzGsYgfKbGG5cqPK2jOmX7WNwg2eUvTJztlgc0k9o\nOEGjPI6JAoCDAUcXsAVm/rS04NxXgr1W1tjN0hgpH6xLPSLfyS6V3QAApfC/\nRjMhEZcdtwMpjx9mS0ub5+D94j6BiQvC/s6cdLdQJYEPE23btkg9DVjfKpiL\nl4P0ru/U2lPUYxnTRoFs8vmtmGSb/mH81f7jnIah7OcKq4g4oQwa/uPy22QZ\nAFoJI8Mb5Nx/0VA2IR8x9FarMvduFeFFl4rUxMf5yZL3tBFHHlo89gb2izAN\nClOTPfuDGqZiMR+q3NP1RMMihCHC24phb2lbXPhsgbz7Sm0ZhB8KR0FsfrcV\nPIkLU+74zqW/qX8BvyPnBkejOO1+sw2iS7vmL9hkq2mEExaUXBBxe4VvWq7T\nujPQKM0H+oZ0FT3WlKFHn/IrhlmH05eAfVZ1ygEaNSp4W4wRb9UToEiOOnka\n+t/b90hVbiafKA01aNNvsK/WvTc3YbZvC5Myf7z8qOL3FDotHs3/5sJze4VQ\nM+D+isONPvvAccXrKmSKH5+bLnv45le1rFmLRkhOVHLsP+Z4MIDuzi5wO5Bt\n+bDB\r\n=2oGA\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"c48f8d3362a052e4ae6f5c284159c7c5c35b2921","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.4_1541165308399_0.7768526380693437","host":"s3://npm-registry-packages"}},"0.7.2-pre.7":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.7","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.7","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"56f63389d5dd6afda3bef460165b6702d8cc098c","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.7.tgz","fileCount":121,"integrity":"sha512-BZo/lvxtYpVBtlrsZrcWsEZAGFhrCptUMKsKW4YUFP++OkuqQENnQPlTUroKlUc+emqmAx9v1HwwrApMbIfWVA==","signatures":[{"sig":"MEYCIQDQzlRuqGekllOP5c5bTWJmSQjj03bN9MysTJ1eXf/5tAIhAM1ROtd5kDGeMjqHfqj69FUbKxeIGq2gq9hIo0uVoz1q","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484869,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FK0CRA9TVsSAnZWagAAWNYP/jw3GzfFhIKWsFaB7uQK\n+sirkLjO+KvbbhyyfFhgP2LB/JNm9au9myrkmMssisxUtzOHWuCMeXD6psYT\neZ2T2iC0HXsrtwajZWFXcHjymuucYkFb1qZT0FOAWybCp5vaqltYXpr0sMfM\nZLav1ssCjhdO3gAXA0Bh9WlyR+JKhUcm26CeE7e++90piYxWThqzHVDpUQWm\n+2qCuohfsC/4W76paebUIpCoKyvj70bZRvmpIapYJUX3TArSFcoJmqKCWwco\nHEyrG/N3hBHlBzr1rGtsjM5qd2YaijOGDF9CWhjFICo48z8Br0obE17F2rsk\n5S1iY7Gw0qa8vSMF/mVyt8ZL1jpBmpIeIqBu6jEdLak5uahKFeJkK2XBLM9F\nRK+vKoIXTOaqlgsWhcHisVWNUL8ahACVMxupxhOaFw1IxBv4mpFQqzxMPcNi\n25jaRFv8NSXIa+y98mmqvzmD8yyBGec6xjRYqPLd/t8swQyewPouHp45UUAM\nKA5RZC0EPhMWOiKKFAygmX60/NYxjBKvfDyQWWWET5ajjv9i56gxaCaXjA7s\nSP1Ad5vazpzjxTcpBUtD386STcM1eNAXcVzi2gd7lUlV52icUzXhcuia+H/z\nFCZlvOKdFlqIfU6Y6NBi0P19m0Mifu5Jpyfgn/QHzTaDBYHS0s6Fd9mo7dNU\nLhhq\r\n=MofI\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"803b59bbb4290efa68d46c43618e4c8b1f4ae81f","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.7_1541165747457_0.7654110333212503","host":"s3://npm-registry-packages"}},"0.7.2-pre.8":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.8","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.8","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"7c531bd3c34b6d4afc956550e0b3d217564c82e4","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.8.tgz","fileCount":121,"integrity":"sha512-KiCiQrNcZ8OqgQRCrXAvw2KVadjScxgzcRrNtBkyDm6WhIeA6vUqeyiSqgGWgMnhWhtBr+RfKXUEtq0ABrdncQ==","signatures":[{"sig":"MEQCIDxo8TbUSNIjkxDsborS/+80hjQ423a3u9PZZj3KxUhMAiAWJSDSnoPH0+7Farn1de6b4Vw9izAMTkznztm91zpYYg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484881,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FNiCRA9TVsSAnZWagAAlu0P+gOIK7l8E7gJTDmOr3cM\nT2mLBwJ1qe9ciaQjGO1eQGP1JzTGLXDMEVuzHIDYDyFdVKIeTnk1V6PzPSre\nE//TpPsHDB5Zp5yf++kPAYkkr8AD64GFChiuf/KupHLy2fiM98cb9dGOnaCX\nM2SdC7O3tty6U3FGa+AWRzHWtUTzrfArWYT/LJFOfSddIBJAApAElH3nZtr0\n6FHKZulprW9juDZLwPKNMIpuTDcemqZmw6H3Ydn+kygE1dfLEzgVC1TRMDNk\nvO332jrZYUCJxlHcK6BhRIZvwtfHyIXf0gFgHXgqzJfkUmUKE5kU81WuUIJ0\nUj7063QkGD8PRqKfSlkktye5EhsmzpL/WPZXWCZesWNuguYEs6CwSB2XJa2q\ncua1CtyrS4Sp1fNzkk4yF9kMpRJAjovNBzcl9StqW4XPdeXq2t21BRitMlsV\nPs6O/YrgayO1AqrA6PPVVmAoucoBZriUn5fI803IVYmE37Ufe3cpkgkl3mho\nsCTXZT7oN9gzKh6ihrGwEyyHmKnQX13nnl+tZhkPia9U8KrBvryvoXijZd/r\npbCOMZ+wLUqONZeZatr7kBApGzYtI3/awyvAPi40hvBDktIVrWByW8iblo1Y\nzY0IGjRFJuhtGPFnm0TBtJ1LmefbO8cgIfNBYo2h1BUJieDcJvG/2VQFtkLQ\nc+b1\r\n=AlUn\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"17f9363286fd880b9d5527eca4123d6f920b23a0","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.8_1541165921308_0.8991767121438488","host":"s3://npm-registry-packages"}},"0.7.2-pre.9":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.9","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.9","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ba9b51d78c23cd41a66beed10be3fa6c2df33544","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.9.tgz","fileCount":121,"integrity":"sha512-P9LR3xL4XmrsVJIau96AX8TcW0+r+Ah1U0ude8sIlyAhIfDw4n/Z9NfWmz+xHDqlCTuO7SXbwa+9gYfNv+yelA==","signatures":[{"sig":"MEUCIQCQcA5RMocwpr/Dayz+xwws7tAT7+tdwQYkhAD9eXu2jgIgWxIITJ4yZFSve+BU1vB0aJrTdikdB4yjMbwx4d1YCgw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484881,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FRcCRA9TVsSAnZWagAAPIsP/AoG8QGueHDNRcqKAiB8\nOXZYmCdNMgyPQAnEXbL8l24t+UolNV/fdU8SfBrxIeZoRSA5F1TZLRz7WywI\nAGJ73LCRs9caCo72ovbMu1+2Oiqx1T8cy5Y5IPIn/zaTZmMOry64Ox5Q8jvi\n9KttEMuanPj71RjQb762gc27pMVjU3zZCfU8Q3lMtuFnOECWtvlEnmZHHiQA\nefoZCBA1nqmb3Mp/nsZyohzVErpu2opN5iu2eKNyYdWMIq0Ahn9/8nx+KtZX\ndSWcPgsZUtrkF8ec4J5ZS4Vt4QoaLoK5COwDhbs8F7Fta8urAht+O8nIwILG\n3J0QD/DDMJxgxgJmZcbgQWOSZcjwRUCtlGl1fncod9puMaMi1v23q5fFmg51\nkpa4XPUNAvGgciEU4iNwHrtN8LCDLxdyHNyQ2XrIVbBKZAMPXn4pqYqCQJ6A\nagt78C2i0hg9xSCoDp2ZU+wj9ZkDQgpnCCapqZ1KlTcqspq2l5zckjp2g4lV\nYlv8cKQu/KnZD6V4N3uhcF+DodrI1FbCFalVSuEnzTmPuT47MtFLIpjruoAi\n9AM4l6KVB/FLU/mrJBu+WIICVhKEIsNz8UgaAL3jj4C1U529d/xvidQej+s3\n9TmOYuJw5De3kx+3Zh1eHq93HocSZ3hM5LLN9NjqvUCtVJ3MqKpQQVpUxfqi\ni8NC\r\n=6o40\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"1a142f408350a0c8b34f41ab1107bd014e1e4b15","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.9_1541166172097_0.5913529112696971","host":"s3://npm-registry-packages"}},"0.7.2-pre.10":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.10","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.10","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d2f81d708e5ffd8a635eef64c839e8aa3e1e72a6","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.10.tgz","fileCount":121,"integrity":"sha512-bpLhNbjlAE3Vr4IhS5xmVq2l3nyinoc1AqKGwMo9N9+5lrvV5lWO9EyDe83PEh6TNqTTjxQhIrBQAWVl2ce//A==","signatures":[{"sig":"MEQCIGoSrgJ+aNUOHI0wRhcoRbnxtTJt6bJqAtkc69LN2hI9AiAaYg5B1gtQhToGTE5VU9p84sy/sVL6MLY2S4BB9Bd/vQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484896,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FS/CRA9TVsSAnZWagAAl5MP/i6jxyp8l5l4mZwJFMqT\nWZSo5yY1Onzj77kk7DV0mVjdozcsLvkbcs6A6Z5/i2DYaYKDr4AVsd0LzYXM\nvbWUm2+AYMSKXRS2E64vivDi4lOBPjRlcWYvpDsJ39uE3lxhQpNJgmpDVBBi\nXEh9WFS11x6TLXLJHH/bbTPBX+4vGuENSyajJ1ICBlKdN4+tEih2X6L32N9u\nldSXsWAHmsugNNnHACxzN4+DRVQbUZBR7PVW0tNTeAQmagaiWbZPJOBFBOvB\nYAkUvcqNLWxv3558SQbaL7v4Cqrx8uDCy8Bj5eoePolmLWysdi3ogSIu7Ywx\nfRYMIM1AN+8AR21RpncNqgG3J9BYfB36SeW/n4V/aW+3b6gabv10ylqbg0UP\ngUN/XMV2Yn8LoSOW8shjuXT5Iayuyf9Qo2if4c95ojJY9Ujp50nK3wmOyiT+\n7Rz0gPzJUCQdu41LVyRADvUpTygNiWFHi1ROijwcJy5qrtbsPXWOT4PN+iUQ\nT/sdJKW6rNe9F5AKHoBwTAd29pKHxn97iRKD69BUSKHQjEiKxYXhCE+bIukZ\ndhvS2xcqO2+rceBoMZYkgzjKh8tkAQIXQsm6CwKqbBAmSy9fqEPSMsxguuBY\nVHs5Doj5eioNRg/I8ub/DnJSTaDsknXRcXyUoFRxrfYJdgGvkYSJVi+L3Jkw\ne5ZI\r\n=12NZ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"39a0324b6db4f31c6aee25973a560cc29ccaa05f","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.10_1541166270730_0.00021066502550670663","host":"s3://npm-registry-packages"}},"0.7.2-pre.11":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.11","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.11","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d94b97d9462fda7c75c77ff4ca82106a08fe17f1","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.11.tgz","fileCount":121,"integrity":"sha512-eqhWsNy/z83yuKmql9jefov/55tA4IOLhggFoykCO6c2E/5KtllSZudIz7ihp5FFb8RF0n9Z/xxwd9MXiGh90A==","signatures":[{"sig":"MEUCIAb23fvWp2anS98telN/dj787VkEYvvEpHLwG50MplhvAiEAlxMEXbsgrypPjhuHMEuCtS+E5o0jNsj7gzxinGvzwbc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484908,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FX2CRA9TVsSAnZWagAAXscP/31K6QuGkaIzYX93JP56\njsNNJZ7W3MM8A45Yf/pge4VbBOXz8l0AiPvAPj4lFT+IPr3PsDCtt/OgOreU\nE14uSkLB939RGxaO/ZrwP/hdOKqAbm3r7g3iX2I/xHxV96rHFW7+Ifx7oCHh\nrSq00w58HmDgYeQp9U4my1kdHCkUF1c3bl+mZGvhCerNbCv2LdDwIWYcqLYx\nrdhTQHJ/M0k1RxsjvF4svHW3mn3HLT1R+VIh9MWk+zrbOkkcif+n0JwnIlGE\ng51+sTW5jArhh+cxhtaFNdHk0KkZiL67KxXtO90xQoupjJk9wsQKv85ZMbdx\nuj87dWPeeqMEJAysjmC5v04lNiwwHF7Ncw4ug5eJb5rSxiGTsnCh+twUssXC\nHi7zlW6KmWauwMpxDObU2w8nkEUT3W/tFbL8KNvuQTuAkWLJh2IcdYsY2hkK\ntqy83IfVi0daNeBBEarPlG2DCKXc+hR5Lrzs2RZ9j4c8+ODbcG9OsYIb2s0k\nhN6tft0bB7zr1H8Lwr2ZLx98pvaMwweB2OevtvFWZ0O2CLGDqLpCLzb9LXMn\nXgg4G372qMebV2i+J90K+zhZ4zpPIZWAKxtElwAOik96QMulb3DBI/9jxj0T\nJl1RUCR86pG8uIbK7RwFQikaNXBSRQIWASqY3jTGxEJROwJhj4M+PsGUeB0n\nuC5s\r\n=m6UO\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"3b498fb698cdba7e1bc3e305b958f1a94672ce29","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.11_1541166581898_0.8793996502074388","host":"s3://npm-registry-packages"}},"0.7.2-pre.12":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.12","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.12","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"19ba4815960600fc0472484def5e28f6282eb76b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.12.tgz","fileCount":126,"integrity":"sha512-sYgql+KkCuqo/i5Lcr3PTPXgBgQUg6vJCbeZfcM8sROEbscjNVtt6LkKQ8u3DSg+qRA+Nw/th/NyvWlk56a1Hw==","signatures":[{"sig":"MEUCIQCil0hkjamS/cdIUrOKF2T7Wb0F66A7VCG9WwS9p4flUgIgJ7S2d4i9LEh9mi1JPMihDiLa5rbuBmElDA/cUvbiQgo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":522242,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3FlQCRA9TVsSAnZWagAA+/EP/R/ftetW91rhgzBRwbAP\njgG+GphoptKb9QpVmoEooDKI6xa0KFnMvWWomu23utV+kVg/etHO1LoLK4e2\nAH3ShnAgPpdT0faVqghNGG51Cd8erseRHEqVMLOYblXF+HfOs0ANCoLv6w7g\nIwe3tbnKpPGnyIbGr6Y2NuQ6MxFXiqyO6OU2t+auW+659xLD0U04Pq0N3tMp\njlQHLA+a6RxmCVEtewE7P+PR09onS19Okui3vkl9rWgfKC7xumJA6dEj6g0I\nCXN1ckPHWS0q+cJrjDPuCtESca7fzJtI4EjnvvqIiUH8lao4yqYE4tTkkeqQ\nFr5bz7MNx73+1gE8HnOhgVQ/sWf56sb5DFIO+S7ki2qyk7joKcv6j+hk9g8E\nuLEjedRv5WwhiFnIOcPnRM2kUhZuRVcJ0jjFnqbx3beHPdhvhom4Nn97IVxX\nabW7YG1xbVCMJ15JVlwXQSVnRXfLFOVjzn/Y5xvR8AVjE6zp6tuX71QCr0WK\nQyN0i2XOmrUiFuVHxe0UGuxxGrDWjLg3WyC+hQDNeNFcHqGUtgV0kvgv7nye\nu3hxCXRXo8lstwZE/Tq1Q4Obxpd6d2Sxm9EFvmgOkxLgujZpW4nRUn/x/gWa\nQ6Puky7uenBuVE/yvZ1ZgXBfceJ5nQxWgRGexSSQOWgeCk3qQI6LJEs37wO9\n05O7\r\n=3W1c\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `params`: a map of parameters that are interpreted at runtime\n- `secrets`: a map of protected configuration parameters like API keys that should be handled with care. By convention, all keys in `secret` are in ALL_CAPS_SNAKE_CASE.\n- `logger`: a [Winston](https://www.github.com/winstonjs/winston) logger\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n// helper functions and log\nconst { adaptOWRequest, adaptOWResponse, log } = require('@adobe/hypermedia-pipeline/src/defaults/default.js');\n\nmodule.exports.pipe = function(cont, params, secrets, logger = log) {\n    logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adaptOWRequest)   // optional: turns OpenWhisk-style arguments into a proper payload\n        .once(cont)            // required: execute the continuation function\n        .after(adaptOWResponse) // optional: turns the Payload into an OpenWhisk-style response\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request`, `context`, and `content` properties of the payload into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\nmodule.exports.pre = (cont, payload) => {\n    const {request, content, context, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, context, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `context`\n- `error`\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\n### The `context` object\n\nTBD: used for stuff that is neither content, request, or response\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"9f3384e4c09377a3974c1d802b488c4009a6056b","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.12_1541167439797_0.3317514406590474","host":"s3://npm-registry-packages"}},"0.7.2-pre.13":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2-pre.13","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2-pre.13","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"89058f7e8d96338f217ebfee1a524dd4a5c052cb","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2-pre.13.tgz","fileCount":128,"integrity":"sha512-Zk5rNIl2yOTVIPX0zrQuTAPHAdktwuCOp41ePTk9EKOeH5X/byrSlW2374xhGOsHnbyK/YYmenSaA/jCDgnuuw==","signatures":[{"sig":"MEQCIEtQ0jINNY4aD91BQi15zUwpA82K9EOvy6a/zRTBmeS1AiBtxXvNv4rQauOyQ9TH2Q4SQA7JL0x+wSh1exteYmkcxg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":534685,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb38ceCRA9TVsSAnZWagAAJxYP/RbTDoXLGq86VAU/IAJC\nJXR0vyPSY3nYRYg5CiHNV5k3q0TSPVd00HjYZaarGoijHF62UHQ5/zUHgqHW\nzySomYM2fAl0jwq4lTIU5a8QpBnWfiadOaZdWLoFdvQ1eB8GNkhm48NmDYm4\n9NTOvTyLTSX2DoIZmhrWIP7YQqN4L5mGxAiFCPZ4OWVp+sHJiY2bjYZbNoPT\n7U/vPVdh8P03VpBgA4R0qEhx9rfOatuV3D4O55qZm2EfnVAYjdN6tIudB80m\n/Se+mQuCKOszrkyNnYHWC7cAcZkcGpUBOh+QNoyvlWdtjMg8zUEqz4K61o3N\nKcHd9N0MdHAufvarjGRauPXmAAstZ3b8IgkMLr1Ci5/xBXDnJGuO3OaSeLLP\nWUQ/ndiaeEIZ0o7ybqnAJdlDYkxpD1DxDG9UPRFBrJE2BGlvbb3Id5KxcAIV\nExVRU0JAZBx7D5Df6iMPIAXlKVeJeVinb4BTp+6e99wT85aDLwWlaN6T2sA0\nQNzE7zZbzFy6s31LDpeaKvHID+2A85PNI6ESgSO46CsULxNVZlFVvuG1R3cf\nX4VI+Ji2HiHqQQ9eh6UkXX8vonVsMBWpr714RsIEa1vCuMSTAukJ4TEjwSh5\nn24SHXgesqPxbjfmf8hseyp/Hk/Xh6vcQKzN8jqw2VyqlUtJ84k49vC7hsew\nCh51\r\n=Zp9J\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"e98adb5dbfb08f3aab7dd96e083be8adbd71a303","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2-pre.13_1541392157756_0.6838250106791528","host":"s3://npm-registry-packages"}},"0.7.2":{"name":"@adobe/hypermedia-pipeline","version":"0.7.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"0efa58ec6a56195f3f663733b97d55b7e0336156","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.2.tgz","fileCount":138,"integrity":"sha512-v7wDmcxV36TaNGBr9xapQP7bKiR0CHI5AWJSltJN/QR69t3rdaZw/S5si7eDyPa0VMn/JAYUZILN71k9SHTd0A==","signatures":[{"sig":"MEYCIQCBFHwTlexKORRhkd18dNv7BKGq0eJceLNRYL0YBSE9ZwIhAL/UUgPF7BY0TR30zPBxYAoRgzK76+N36M4Bv4YCnCb4","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":586795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb38ejCRA9TVsSAnZWagAANocP/Rd9NkGN4kLp0TzvHMHh\nCwAa3p0YH/lPsmSy1kK29qKc0gCH/qYCt7RBr8NhGmAGGHpFcXaXcICRoW+y\nWvjvSlTjJh73ddiex9AYFkYFEn+9YOZQmcur+EtSrrsWUIZDcsOvLCvxAQJI\nWxzhY+QtbopdREo+ZV2ghj4YMLAaUByaVUw35AIZ8aDAWyQtGfQgJG3NbGbO\nkRcoSfkpxvOTZKTrXnh1LX+oJJ0cIUEDnUd5a2WUWEL4MJDrUOp/gPJS1gl7\nsKRoidgvBqcdBgqkzjB3H8p9VmzHd2SJYFAFnSEsAhz1+i3MaPj8Rcg3TZot\nKOCtZtzLWZPRc6x69Q74fy9pZjkkXngldHZh3U8I7m2aHkxZ2APhMZsuYhQZ\ne9lRgjx+IvQzMGZHlCSVQex/KOD3rn/gRlIzP+i/Phw7HhxdMhTh7fVU+wkI\nxXgzpTmwmhwpDdOngvZVJl4V6tJVSXQObH4arT3wZoskCY0EGbbYUzBBQrY5\nEa/ZtXKwUVCSYfPiX1iRkKkp6naBsd4FtqxxcLK2f6ROz61UxppYfQkC7A9j\nbapaXFbBAPw1FznPA+vY86p41fD47QHaSenymwl3SJ+dDkdQiVrQ4n92YRpp\nPcB9qvhUEM4y0Xw+qd+6KA33YtXQ59+rR1ghw3wJNsf/VuUB/AzdykoQJmuf\nPSVq\r\n=/nDV\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"130dd3b0a7b4075d8cc398c789cd83d77e743441","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.2_1541392290358_0.0925311732663825","host":"s3://npm-registry-packages"}},"0.7.3-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.3-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.3-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"751d6136b07ec599f2815336716c14cdc60aa2cb","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.3-pre.0.tgz","fileCount":128,"integrity":"sha512-xzEnYg4Jgcbf6I6BIq3Fx9GJx+MWZ94hNncltQZuz473WhbZ87l++UfgNeyUqzg+8H5dDHuaKsJfCDMeFoWsdA==","signatures":[{"sig":"MEYCIQDI65mpmYFSA7v/5ogc8FVwk1TB1rHYJf67rCF5pQFnhAIhAOcoKyrT9A129P4wQRYY4LLg+0Uv0VRGaAQz2DQ9ruo2","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":534684,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb38fSCRA9TVsSAnZWagAA4/8QAJ3RM0ME9mM5pRsayDKn\n+Ab2phdlWQyChK5kooByYuRf7TAhrdJqJWQ794fXIhfCXeBBiVezgn+Na2lz\ntAo90upDo213qDsFeTbHH27M9UvGShqb1HAf0M6oO7sS9ZZ5LxluEsaVFv4n\nxMiqNZ1TYfuffB/mmCt0VvIe9c+HZoA5kF01hQ0LOVDRr2ttpUXoSfZDXZ66\nfTjhI3+yuFmuKgBcIBsyxicPzO7Iy1frns61o/rifc/kxWboxukWO4y4Ec4j\nN97oIHfVjinQVqU+7ypV4RJtsxQDAFhEMR5IeA+1AoSdmtwR+c1TSShoSN1l\nCKwosdZWEFe1GmlwU4nrQb/RiuNMWI7DrS4iobwbPH3CUPYyioFTSllg+BZ8\nfkXjYI24P151bA1fGsTD2ii1omKgdlGVuhZJtcst+P6lVM3LSeeNTix3EaJM\nBzU+d3v6BXC/kP8ul/54vDn+cbJMVT37egze1faHq5xwrR6RzoybwzIoGze0\nlbLKgjlGPJtUidGLyl3zEwiFjCAlmcuTXZQshE9ps78kn5+apyxw9c5UoGK6\nYGPHa7ckJozuELcyGcVsc2i1JRF1flvWlWO3DWWBVUvaGW58q3OEYrDcMeWp\nJAuuKD3lLOeblqolpQttF+eGoZsZ+5u6HXIW2Qc2fbo4P8KNWchNE5xdZaGG\nmuWs\r\n=GpkE\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"aa9ca114512b08eec3a336cb7a2aed35b9299794","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.3-pre.0_1541392337899_0.4723629198309911","host":"s3://npm-registry-packages"}},"0.7.3-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.3-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.3-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"2889b4bdf22b727e9ef29fac9ed429138815c376","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.3-pre.1.tgz","fileCount":128,"integrity":"sha512-JJWYPWh8wBHakmpPsKWofsWFw5ZIMJGd1ooBGEybiuhfvQtDETjlaGvUWcCrVp3Hpu60by7VjlpUUnADiDJ1yw==","signatures":[{"sig":"MEYCIQCTRW0fFWwVgdLCG7egqECtYd9MKnSQAcEeC7WbtfgZUwIhANmvjb4fPILqZ0h2sGIKuq4ktskxSqtu9lfTotYzdBWJ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":534902,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4PhlCRA9TVsSAnZWagAA2IcP/igYixNoMgTJFfWHbYnh\nwR7t0w06LFqx3L5yIlw+pvd9vzyqLxe/TmCC7M9JHM3GmcMuFBrOGajL3Sxv\n9PWaSQsFpzWB0rWl7N/qT8wwlYnIFNklPkcePdbHuqGOR/fCmXrJRAK+UZLU\nqof7YFcKNKzhsseSHtfmkspTprO5Cijnp5mPN0QUizjxahvmyjWCGSRbaiUD\nGwNb1mJ1aNCEyeNc8Ju+yzv+Jvey6r6SGHceLhmuSODJOwIPHZIrnIUC2KxO\nYL5FRlPGo6RG0cxcpVUfMgeonVPJPTVl+ONYw5vRL4+GBv+U5GCqrIAN16M3\nw1noQPDSEFe2UUYfhxzTlhlMpEoaB3lGLEdzWzFUDKA7gK6YMAB+S9PUy+Ob\nyG2R4B1wOy9kKvslXnioOsicEzBMioNHs498K4ZCg/nxXBZ2uKJFc8uKn+7W\nh/ZdQ0BdmL3g6ZQgAtXM9tn5kh7JhY8hZdSAbXtk0CRelVaSIO/7AV9s6808\nLPweKbZtaR72lfUaHifCY7ClHSeLBw7BOQqn7Jvo79O+S58escQIk4P7Anao\n/YelmZP2+d2U2LMN3F1cFSronB6b512PWlSAIPF8sBStp8/9/fjpDWDpbfB4\ndObgKsE5z/yJ4rlmHX3BELlaz83Q6NOn66SC1vSTIXXykv4eK/a6eJSbRrT3\ndFNw\r\n=i3Xr\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"e5ac5edea5605bec0ba1da8b5b6618372a111402","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.3-pre.1_1541470308306_0.08893475224078706","host":"s3://npm-registry-packages"}},"0.7.3":{"name":"@adobe/hypermedia-pipeline","version":"0.7.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"1123f46215f49f318a94c0301a9e50a40dbbd90b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.3.tgz","fileCount":138,"integrity":"sha512-4A81+4jqbCofX/X41bJc7AyLb1BOPeZIGX8N3zqYZGssxDc3h6HqyVX0nmchBSxFriUp9mlQUGEt/tYeVz7bWA==","signatures":[{"sig":"MEQCIHdxcjdSdaWvbOpowcfoRAhw3LN3lDMPJK+0/2LbG6X4AiAyuX7eikYuYEF8YmvepG1i8ruk4V/S3dKbn6CrM5wNXA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":588527,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4PoaCRA9TVsSAnZWagAAcScP/iOHAgensNsKGWdbfCiK\nN7XLzTy21eorvPJbqHgdUaziiYCO+X4ur2rdgl7Bd/8bs/Sk/S0JAVQNRdWo\nzv9EEFDHMrHGW12u0XeDuXtUJwglSZYEPJWv4apKtBVVmQu+VijrapM0pbWY\ntftzoSoMVNL/fGmb5Lmz4HEZQ0kFsC5KScZyQV5xmonjAptLEHYcNxby6kl/\nKw0gUB14c5lxdPykURZVvDzF/sK+tTmIukX7Z+Qi8t3CqjG6bPuK2EwCYBtV\nG9mWqkLfdFyGBZPeu8sdSGRHX910hcEDqBDmM2UmHWICwQz6HTEl+SqvQwif\nmpeQaaOHBAA5mwnLB6AnZ4zIklNrDinO1IqD8hrbodwmBQZzDrvTWReZJLRR\niDNjwTapOSHLxoqjx+jqxOahCGHoPxdG6d21kzw73pIUThrrAeY8BRiJRNDy\ndxB5umv8XxTOBDOm/4zmqwNXbI9o3RRx7sMUKdMy2Z+H0pYYZNF64UnM1Yme\nUOSJpqt5t/Qa+mVpKBxF+WuOQs5ShULhwYRw8kOqKvcvklq6Cc+aHtAY6t8J\nOco6ql5MfL7gVTjOCK7jwYaU2VK9gIem0FEU7Gn9hxrsa8fn2UH//ochvaCh\nuAZGd5WuWiIU2Y5t4FlyMP795ldjJin3AwaMHJUh0KntIpi/gmDrlyr18jFH\nUE19\r\n=tXSb\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"13f1e801e0cc054fabeda34db27848c288d6a4da","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"tripod","email":"tripod@bocanegra.ch"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.11.3","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.3_1541470745138_0.8585642340109876","host":"s3://npm-registry-packages"}},"0.7.4-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.4-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.4-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"5fe88121f723509e2fb563b6c88c0b4f1a50e244","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.4-pre.0.tgz","fileCount":128,"integrity":"sha512-xaw/e/sG/Yq91j1Yjyur9JyG+NjwPeydYYr2YGs9M1arE9jfqv6mez85mwPUPX3LrRirFZxSscJaeH8pSrOyJA==","signatures":[{"sig":"MEQCIBa4z1Sv1U8YanmKWgmNBKSVqxlnzq/VjfOKSEjlWhp/AiA2Xah+SoTIO7dPeyciJNlWkPN22DxJirqthCQJ0ZfpKw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":534902,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4PpICRA9TVsSAnZWagAAEVQP/38y6iIqqzvZwknMC6jE\nLAI00zvqQ4lSlvD7m32PjCXooaTv6JR+i5SLOWlxGV0rPlDaqtciS8NYp67q\nniVzyOHVh33Ddvsz94lzPOVsTVdd43J+Yz0cXj7xIXAOtFM/Sj2mXUxXHypp\nNsVt4/8QDz6mypk9dLSCW+GbDKZqU8n+YQR/11WMN/uQ2KeUdMvNQgaXdQdF\n+LCgycfWFVzs7rQa5pTsPjh6kp//k9Kwgh3ElhhTAW2MChp+rwRc+urcyYgD\njSBdJ+vf4xJX6KU5ii/OY7a97Yea/EBDZAcrVCMXsRrznlk7eZxxD8eRap8w\nriQmOCiL7dI9BHEBqiC1lWUYYWfdCuRJsLCAuQlwk5tfnJeSKYJy1T+PiB/g\nk6NwSaAMsawB3LX/7DhLYFKDG3aaa/pyGiq7c66lb+YEhvUs+qPpQ22Kyzjm\nB0BTeWJve28FcgsmrFw7szwA1ExQFuhdDR2Dnt3TfvTEGpYgJ3jvmLD1rz1N\nIbH0Y7vjU18pklk0BVzFHVG1YnI6DTytre8AUX4yM/YWIBs/R1no070U4o6w\ndU1awLyP01OlKBPsrIdUdknvjA6GlJGiUYt+Bw4n3yHv0sZy+CNR3sTqe8FL\nGYTcfjpTKvx3g/eVYC3c+oEymYjL+g6J83JqJZB9nPAUI7knzScU4cfPbcT0\n0qeO\r\n=OJ10\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"8fe8844d2ade2e06c6c3a0ad51352561a12fd361","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.4-pre.0_1541470791532_0.3245508511120567","host":"s3://npm-registry-packages"}},"0.7.4-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.4-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.4-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"bdeca1d7493d4abb322af020602a7cd79257a46b","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.4-pre.1.tgz","fileCount":128,"integrity":"sha512-HWOMLfsImqxaWRVc4btCCUrCnxqfRmwlMfHc8SvvNRlsjB83dBZSXcGKZiUH9BlJ1X1hSxD16LNbv8oawRHzLw==","signatures":[{"sig":"MEQCIGQkjOiF5YePX8GrNfBBq6HPxjMLXGYeMNtbno90iv8FAiAPNDl4W2RJHVtL5d+c+py6Jn/xuCnI76fQwrpM9Xd9sg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":534912,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4aHNCRA9TVsSAnZWagAANqAQAIFr9mAUh3Rs2AI4y62x\nQkVQaIGbmlxUEzzUeOB8PeYgNDPFSAKuqDGeHWMId3kOc4wJLT4IL87PxH4w\nkEcL8OUw0rHaWcxnjkZM9CjwsmK/dyByBclAnhAfkjIMKQY7G1iObC83bCJv\nBQWOHwjsLDpLIBTJJWL9sRDU13JOON8sufHW02fUxzlQxEcsqDjnnxOMyLB6\nz8Z/+YkJEtCN9iKcuH3Ec9i4tUbdNzZu8hk47joE7SEV/M1VUMAizdfsap26\nmYmTqyWE0wG51pwbyFuBH3irlbWWUGmWCobqkryAl89qC6t1UfM2f4Tx4NVJ\naJVJq/niYrEqUWNnEvS6l7RzdfQHgGkXsFRIbPiRvYsKivRlUUoXYs2+960l\nBFWCFe3YctP9edlYu7833T0FkIlC6NtB4YatLaALK8PQ5gJpnP+YPg1B2Jqg\nikr/fFmM26yUikZkHERlhqSdZtIGRtjfDtuQ9SRZGCWrVt0pXnwUfIRrzm50\nHQlKGRB7aZVRQmOBvwRecTrR/Z4+oiAsI0gR1We7XbA7F+B/558YGDbWgDoI\nbVuiH/KrxzX3CeJnV9QSTCAHjj/ff05/iL0/4pWyhb99n458aF3et2S6fwZE\n/RlXpHO5sDhEfTwtTl6UTckAakzZ1psgKw6rVQ8uqw0dFW/z2MbKXv7HNd4Y\nn28G\r\n=TVmw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"f18b29d06f7fdc2d6642cb487b35ecdc00202ef2","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.4-pre.1_1541513677036_0.6276706139639046","host":"s3://npm-registry-packages"}},"0.7.4":{"name":"@adobe/hypermedia-pipeline","version":"0.7.4","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.4","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"eb9a19c1f6bee9b223f3e7ad41f3998b6919daec","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.4.tgz","fileCount":128,"integrity":"sha512-kYyFin1YohEoh1EE8+pxw0VCMOwkBTrrX8Rzn4bgLyO60rcGn4FsPynlTLvbA1Hpe3BknKE0CiuSnCDszL6wAQ==","signatures":[{"sig":"MEUCID3JK2wa8ncMGn7Z+JSxzBikCo7GBHsPMheziuMb7WvfAiEA3vc5kls4vu0v3e6CQHWeGr36gl+1hP5tYgbZzD7hMHw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":535196,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4aZCCRA9TVsSAnZWagAAGXwP/RwxmU7bHSlS6tHtUIFg\nfT/7Fyzg3qYoqEyAFNRPXC2LnIl7aWdotniiDQzG0wwWKZLcXrP4xXD4/gHF\nlhFkBWE0dgJ/PaA0ujcrL5dIqsPbKhlE4CrdnzEUhpBOcFBbrLrAWu13Otbw\nvUVox99+AvLNaDMl5bys281BPrx/4SCSqNQStO/xlJQZ3NxKoXiLESL3d7As\nLmKy2I71bIHz0LJt2dMhn1L/h98QDHw0ibVoiKaoFoQXfkOMLeVpwGsJLNKY\nc4yes8CtH0/aLkEj4AQI8MgA3LFkoZ5pKdxXOtJ50uDdaZUtOlbDk9uPaC6U\nMFkVqspJlrxZUpGj8hvmSABvBn42BBi41s+5kc17/HzrAvKNq9FHtIequ/gO\nyi68OXv4YYG3JIDAz4qs2rXLGH80JjArsDcXWe0jIJh1thsZK9rnd+7YpC8E\nimB2tb7M4ocAmtgAngt+hYPJGNShjSwH4q4Qzadh+wJ7EvEm2wHFM1FOI9B9\nYMOdEZqYaBJipqcDO1/UgWo3YG5QgbK3wYhcTz8dYQBuH+8pDetByQ4Vhqcp\n84ecqlZjiIoZMzY35dInh/HIMD9ilTjaow5WhERd70WlWsAx//DO09v8w1Vc\nvVi1Cgq+QHo7Rq6u/fX1aYIKZl5RrTULP+jimK+PApM3R1Bl9njqH6uAPoPN\n1KHc\r\n=EoMT\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"74497fe81d2854097e4481d55b142403dfac12b6","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"kptdobe","email":"kptdobe@gmail.com"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.1","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.4_1541514817941_0.20065479710853507","host":"s3://npm-registry-packages"}},"0.7.5-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.7.5-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.5-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"fe80f89e64f065b56fc68c586bffe46e8dad4e01","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.5-pre.0.tgz","fileCount":128,"integrity":"sha512-OZRU581drOSOYfHzkBI9xeHUBHYeMerhncvQ/HdDbnH25bqgk6OYkYNzBunOcdjT5XR5Oa8ZkLLoXnv11bmgWw==","signatures":[{"sig":"MEUCIB4stINfkl4WrIm+oezypwchsXv3+Rc+MPFi8mko6BbNAiEA044CC7bJPGm+tp6ZkV5Gdvnyj/a2tBsTvofzoKuOU8k=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":535202,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4aaTCRA9TVsSAnZWagAAL04P/iUbTsFPmsBG6v94yRHI\n9bC2eTq6GZ4ePnLQqU2QcitiBt3OJ+Lj8p7uEQVGoRstGXL8W7TdjOeV7Mwf\nWxKnX7WJ7YJlW0/mDzL3QnXVGtJ4hMoCirVYQgKYZ5jjvP6gXjM64mh5Mbji\nlkRHcw7a388SYj+6avz+G2+ISFQDSBrdOdkitIFdD7/c0T/JBp0eli8xsM0n\nGR0ZM45/PCl2fzOR2V5aDeYIFsN08o3OtllmXoUVD8SuDUiF0xZRUf2q5KO1\nnpHwLY8K16pMlKJwXlNRXnceYzywcM3+OOaV8yMBafiS+OtITAoCOFOpx+Ys\nadGsoOVvyp6WF838o0w6hudZWCh9hi7PJaXo3/UYPsESuRlGMyq61T4bdZCR\njxlY980jjLOup/yceSgBJYYOKSYSvrbIAg2Vji4gLpRUGW7LsWFjnpIbi9HE\nLVqK1NopmZsdvJz3hUOAmrxevXRlTqNoJzF9/bWRtA3mfmbWZ8HTWMffxMsI\nUlfQwpposXeX5nNJ2ZCIuETABWLbSm2jXxL9VVNNCKn01Db97Hzr/iXDKzi8\nAmaEcIW5R3DIJPXaOXEh7rX5c/qfWvwofs2d0FHd3KsSA0RXJMgcFOrGPLaM\nn75Wa6X8zVYX3IuQhSeevBmbxHpOI7zLFZ1ofKOd7ltkl5cxOjzyEJdiLfJc\nKxv5\r\n=TTMA\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"d13b4a607fb23b4a50e04a2affe0d5b4f65d6733","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","tmp":"0.0.33","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.5-pre.0_1541514898837_0.14071878720887265","host":"s3://npm-registry-packages"}},"0.7.5-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.7.5-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.5-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"ceb10af3af325e3324eec4abe87e1b43b0cd5380","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.5-pre.1.tgz","fileCount":128,"integrity":"sha512-epWoUeWue1RHqVbU0Qd/xDRMby6ZDoNm1XgLF5vR1SVePMz6lE1A6K8zD79yjPm8GMhvAvW6mmKJRiQHGlonGw==","signatures":[{"sig":"MEQCICmsUIRar6NH+5zhAJel9ykKjZQXHeVBN2qS68t0xHhKAiAEBiVEw6RLwEO2rjV7NweCnxJXUIYbtUgifjWywpMMjQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":535895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb44j7CRA9TVsSAnZWagAAKokP/jQh3v/21RFOmf9jc4Yu\n7uX/paWT/gr9zNznMCQvy5t8zNRRq98h1JfaqQIEE82HEkmBbffduBaGh0iW\nW9eOEKPSydyc5OzDITiCFUoK8aSadp3jd/p0NiuGKAA2Nc6mGWPnRWkuSsZP\nzp+aCwsk7jf+ViNfd+mO8SS7OniNCoBDPDAk6oKhzwBdhMdmjKj7DOEvNNvH\nfOLbBRuwj6N4sLXo4kkEeUWQO0Lb+F7YUUZXNOvc2iNZzXeTUxG9h/x+Umez\n1NSz6Kj4q0C7/Suoef7E3yj2VeLySswFHr17y/uzYyxG7o2g3u2hf4vED2Mr\nweuV7x4I81edextYlWrfptoGKLnUK21EvQI5fsTl5FGQRyf576c3oVFZHbyv\n61xtxnjqMlVyCRlu/f9b955PidU0S2+li1jIOwk5IiVj6fZ6HiZ1tZRg/xGW\nM7m8KpFUE0o6470CiN0fYFTjNZ3hhVTEXhH7EkGMVJ760AnYKvqmyjlpZpyy\nh+j5cL+RWpmMo3jz/Vbe5KOWOePSi1/jq1zJ4NXjal58RXjJn6k846YcA45B\nGHCvrbPoBxcPjvi0sSnGthA1L28TjgNmGL64Jkh2dZm+7FTMSwLB8jn2n8da\nckiDO42OviZt23gY9nfocE9ef2Sv+T9Ccn6xsDmM1xMZE10tJuebZqT9eogQ\nPbio\r\n=qKik\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"e6c5bf9fbee27d48aaf45e1b695bb89c8fb4ba9d","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^12.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^5.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^4.0.1","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^5.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.5-pre.1_1541638394924_0.6545001485116377","host":"s3://npm-registry-packages"}},"0.7.5-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.7.5-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.5-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d4cf452a9204b1b0ba280e331c80d3d8cf7d22db","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.5-pre.2.tgz","fileCount":128,"integrity":"sha512-7ydmB2fXyGVCoZr2xGLidhEqV1sypNrRBRXRz+VyK3EGRQ9EILbsnMI0jPUSF8mSjgcnwHxgg3TWidz8ErpsJA==","signatures":[{"sig":"MEQCID5TLdeJq8jkooZTFv9rJbCp5ALyo5ZFgl7lGMpV1C6YAiBXLxjYGnenUbQ8SAI1m8TA3iuuJdJjSX5ZQRCb1/YpIw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":535895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5ERaCRA9TVsSAnZWagAAmfUP/R8Bc1Q7LbJ0VEGYUyKx\nKLMaKJs0JVGxKmcWcWLF1JCr4TBkhZwkCiiUt2fSXKU2KnTQaNpb8puV8P8y\nkS0ZT6EO3g8G6jAWv9+FAilcZme+V9u9/tW2fZYKDftWpdwJQ181XkjTpX0U\no6LXJYbsvG3Cuv/lAUA1/sE3U70PhaC4R1v0CMu3SN/tmYUTYpsCu1yhHmRN\n4bWaROd89qnlMUVNKjKnRnV01MWgbKykk9Tr5LlddsLtRefnHvN/PWBEwfsU\n2RVNYMUzsdFeIMgk6L+tpr0QA5bn37InyLzKcwAVqT6fB4g3euNX4Zm8lbO2\npv80twFZSGTqYKYgiCfsUDefhoGNhqthGlEZmlG22l1TzUL/8EgsBnOd7E4s\nU8tvVKZkoIg2/7d8Xj3pDAzrCcncMxgMktsjOK6Cb56gxAS/KhszCilxmuIv\ntlpys5rCd/q9cz3pO8HSFY97KfplUUGP3lSLfuJw6QmaCiRMRmZiw7oHqxrW\nUgKUQICWI3g/9oRDYO6todBjpdIFJKfMWrknBBgdMXH+GzDsQ6vd656lep5L\nitXiAjLo4qYnvwBdWp3KlvsmMy+E7oNj3thwvuCqZi4b8KG626ijfQIFzfze\n2sXRLXRF7Q+BoUPJIj/dv3yzbgeP3AxF43g3uJDufZxVlo6lIgvZHhpxvY1Q\nyc/3\r\n=7PhY\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"63d024ca93c592897fd2e804eb7639d9e25d5d34","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.5-pre.2_1541686361734_0.5883580742447436","host":"s3://npm-registry-packages"}},"0.7.5-pre.3":{"name":"@adobe/hypermedia-pipeline","version":"0.7.5-pre.3","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.7.5-pre.3","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"55d692bf7b14c87c89e4e7c226e066974d04fc74","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.7.5-pre.3.tgz","fileCount":130,"integrity":"sha512-uLtXkfZJ/zsWh6nPWSpQd9dvmM0BUtT3Qnoxs3a1qIYQfVtRQSsnIGaplLrw2ejmrIzoZoALxRcQfwsiwhJDvg==","signatures":[{"sig":"MEUCIDIVP1TS0tQTVnL6jaByIlYRd3ouVLaZhNBiz5py69bgAiEAr9zSvyS3MGuAt8PytLOtits3nPfsO/pVnlEGUofg4yc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":540603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb6aMwCRA9TVsSAnZWagAAt1QP/1DCl8AfTCaM5Tcslql7\n1BB1uMEvLY2veu6HxkK8HF0N37oOqhxhXzA4+evJ7dLQcV8ZIKXYQLyTyFIZ\ngRVQ5qoIiwSg2o2NC9u38vDYbWTfDwjZcX+Qa+Q6Melq6yVZ2j1Vhc/4Y1p7\n6QjMWVd5plDVOWOQCNzI1/2fAwdhcJT92sZ7pSKpPL1eLXSno8NlWEnRtI3U\nrRjrVu2bgUBSaxC9HZC7e/ic7StKxSTD8TroC/PSMgvTU5LmkjN2y+Jn/Qzx\noNvFNUqnwb7IWoFrwc/Id11zM9p3P1AP+GEAy1/24JwwrZuTrWusPkfQfxe7\nnP14lj2MZ3wXwUVBPXhzI7e1AVpx0NOcHFgYyC+F2jhNQQp/qu1EPf2T943q\nfIuzMNS0i4+0fNdiV6u/cYxu2Jleo2HK3HZhAlI9F3cNCN+pmMSgMYYKdAWm\n6YMp/eX6gQj8hz4vSMSu6A2vnXkkaPbwzwyG6h8dYjO01iJvEFyPUiUWeQBh\n0ZiLQfJT4rApjhAwpeIr8PywyLZYRUj3pUIdFNJBEIXhKCrEzlyQtLGsBqxr\nQcsCrs+173iZFu1qweSxDBFEpopxAmEPvyiufK6pm6BgBGkLPF5nfqllmYmk\nqK3ZaR6wcWYl0R8hht5L4OCvmQWHZ89Dpia1RgeT7oyr6Hh7X4xy7YBNge4i\nKmWH\r\n=sta7\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"19ef2fd14a1fb7b8cc03139df658fe884ed96156","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^2.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","rehype-parse":"^5.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^1.5.0","mdast-util-to-hast":"^3.0.1","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.7.5-pre.3_1542038319279_0.5448056646013759","host":"s3://npm-registry-packages"}},"0.8.1-pre.0":{"name":"@adobe/hypermedia-pipeline","version":"0.8.1-pre.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.8.1-pre.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"purplecabbage","email":"purplecabbage@gmail.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"d2cf476248bb12f0549821b1b737979eaba6570c","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.8.1-pre.0.tgz","fileCount":139,"integrity":"sha512-5jA4eYuXGm8iEe3DrYVDWewgpNX0Gv5pfxK8jS7t4CGESZ3gFTyMjrJQxsg38VJ9XuCilKcTLgAD0A8XPiXcqA==","signatures":[{"sig":"MEUCIDhCczXw04RnITY16t1FbbvojEovn2HJicfdgIaV4RdxAiEA23u/9y2qoeHe4V7eh2wgRt80HzZ5jMo0ZhSfxfcitsY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":576733,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9TyCCRA9TVsSAnZWagAACg4QAKT71TjCd7DyvO3MHGR2\nKTGCEAD4rVnd5OPgTjYcAFew5bm5HnX4lXt2Wn1rAAyjJFN/b9wT/o+8/RJd\nah2xYDXl/7c/lMx8NKMZ+8qWVRMIb0P01OZcYKNWwOuuy0kEGN88EwuJcHje\nRwli/Cv8+9tLVL+Hy0jDVWhtpMW+AlvKMLAzLlheLSqJw8D0DqaaI7sIz7Hn\ncHcjynR9Xwil6sB4HmFu46pmOCxDza3La/uO1ZJJVh78PN9sKzp2mMhwfC/I\nfOTasDmf9y5Q1ACWlC4e+VDp4fSSUvTL0uX6mFcPAtdzyvLAY0gnVG61eC0u\nQl1MaeboOiWRImF0KVKDFLoWY+uWt9Ri2X/JV/1iWs5uElcORG0vjj3hhRju\nbQzUMSO3GLoELYUiqrKB8IcYmw45JerPeWZsN0dDTjqjAzOTX6IQfNiCltOO\nD6f54lzuuHSXAAW51HtHtuVGYONMXOPUf5tfXFF3GUtEtkWYZM0jIGeBOcsA\n9JraXj1G5o7htfprgfUO8Ynv47qD/X2O/RGe5jPnPVfPf1ciCtH5X9vP32Ok\netD9KHp9l68TFYR0WhHlqUWHE1c9FhfFoyf1DG/BmNa3o+TAsHs1kBWe5pKC\nSfyu1KFnlh54mYJFILXXe6ob5bkQS1o+CSRGDOv+vM/2pmifuxxej9Ltze1G\n8vZU\r\n=QlYg\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"e00fcf9ef03f1f163d4ba6e9cd3b99c358dacde9","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^3.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","object-hash":"^1.3.1","rehype-parse":"^6.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^2.0.0","mdast-util-to-hast":"^4.0.0","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.8.1-pre.0_1542798466025_0.5491007091189677","host":"s3://npm-registry-packages"}},"0.8.0":{"name":"@adobe/hypermedia-pipeline","version":"0.8.0","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.8.0","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"purplecabbage","email":"purplecabbage@gmail.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"9e4e094690c647e31ea817f073647b40c992fa73","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.8.0.tgz","fileCount":139,"integrity":"sha512-CObt+QP2w/v4dnnI9lUqltOdeY5D9xYKJXzw2p0hzW7U1OsR/86oVIgVeNmcfSGWcVUcppV3EGaSEKdQ3ZdPyQ==","signatures":[{"sig":"MEYCIQDGZ2j2ewoNg942sQB9+B1IfDoNxXWWyEJFGJcH5iVuEQIhAMji1roRXU5RROjsFpkI9xR3CdPLsfQ3aNKFBr7py4GB","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":576727,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh1v8ICRA9TVsSAnZWagAAK3oP+wep440SBjaRHDoGsAXX\ntp8E018ByXf0ZVPD9BrJNPZWjpjL37iMVzCcJg8gPueX0w8vyV7SIEo5fsNN\npisQb+2YHR3Et+BrksbxsPwEz/qrHxVIXqxdnVlGqoyPtVlJzQoj7ID2253K\nvvM0OCkg8oU+tIY3ID+w/LHeo6GpPzSw3sVN7ylXGTAMZEbyU2X6CljcglVN\nItAZhyX9ts9yK11F7+mp2zPKRJssbT866pFfkpY0R9rErKG4WMc9dJhShmrn\nRemA4xwH5XRPMojV+Qb/UBQEZyDmcuQAhG37q2C3AnIcsiieyzWJ8kHqvqa9\n8foZ5IQ2xuWTS30H6oe7VllrCmZw4tFgf3kGDkSF8L3KMqXhF9Or8SRJ2Q0R\nBo7lT3BzdJwF10YZYLeFD+pNxaBUM2cFFBt9yCKboFnCEz/OJ2MbDrlLJGnm\nctaHNb85rQ5BRaN8+v9hOk06Js2ZxlwZlD1gjiXUOKxxAWqrK2FEbe+nKErs\n5kiw7NS6mOvGSLkdGkKguznDLvJ7i1z7tACELRhIhByLS0Do4CUF2TJ2ze5y\n4V51wiNQpwkHqxcNv5g1MVx6tR2psN234lrN5u0dCyqGoBAAPbb03qOQykxX\n/ntKxQro1wi52zpXsyiiEgJktBKlhxaTYFL+/V79k8nj++dhPaK4eiiEK3rm\n1HVt\r\n=Njiv\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","gitHead":"f1fc85c43688d2fecfc7e220715e9ca45d4bdfd6","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"5.6.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.9.4","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^3.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","object-hash":"^1.3.1","rehype-parse":"^6.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^2.0.0","mdast-util-to-hast":"^4.0.0","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.8.0_1542798498981_0.7121279591974783","host":"s3://npm-registry-packages"}},"0.8.1-pre.1":{"name":"@adobe/hypermedia-pipeline","version":"0.8.1-pre.1","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.8.1-pre.1","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"purplecabbage","email":"purplecabbage@gmail.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"272285133779c0c368c4722a78d344f1303888d3","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.8.1-pre.1.tgz","fileCount":139,"integrity":"sha512-ifQH8P3mhJuNg5GLA9aaVEwM/2zgBe1q3hX+EE8xPO5ZsXZICLK1W4OCffsqRaWG8j3fK0YglQhWK8aWD4wnUQ==","signatures":[{"sig":"MEUCIGYA8K60EW8MK2Wbk4vuKKqUCZMo1OEx+M/3jm6rA+6BAiEAluR6caB7MFy86hD+ngzdOiDJbWsLm4zg7X2EPNL5SxU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":576769,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9T24CRA9TVsSAnZWagAAs1YP/RTMT1LdZFq43ZN0Ju8i\n+AA2fHuIJGK4pwMIAYZm8CwiqCChWybKwHrIMsNW2LGwIalceAwWCXuuENFl\n81kKVM0usM3ZyDsinLmXpaEc68qnBeDonyiRkE/bBfBYNhW5u3QIXH7Y+kkf\njxxJi4F7uSlxmIj1AehSP/QvEqoFqzvDdubYrUOH9S2gWC7k1vKFWOxxCTXR\n/9zgCm6GhkVm2yd7T/5VpeQcvFTQp4qX8EKkFJQ5FakIyLCSkCL0J4FjHZFP\nTCROWaomAXB6AB8+963GLybO9ZcOP1VkneXoqpVKiAHcgjIjoklIMnCeb3o5\nkDHkPUm2C1DpIRwNmvV5pPz95bTlzBsbfnQmBvU6xL2SK125pWt0JSWoPRGh\nJZCRt1wi4M3Hpw6utpio9lrjZ9vuftuq5UVhqE4W7+ddH15sAiuQkLNmSVNq\nwueDgQa47vSD4TzOP9EXkJXphZipTzLldnPW1cbcoGWcaaYYZCE2fPhWkKzi\nnxTMV4MdaerHtD+0mQBmvQADXc9p+w0R/5hZkHQH/BiCxcE/an48qoUub/h8\nOq4YejzjXnBjIHzXYbu5mxewAu0Cpf2kwtyOz5kXWYEEUmp7Ahk5VGGH2vgS\nicwxixINA+HeEa+ZR78lI3w2yPzIwkkEu2aJGRmpv0xHmDjqS/bng0sLeOlU\n02Lt\r\n=KBxw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"3c5f0f1eaf3cdbfa7b8ad2a416e63842ffa9738b","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^3.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","object-hash":"^1.3.1","rehype-parse":"^6.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^2.0.0","mdast-util-to-hast":"^4.0.0","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.8.1-pre.1_1542798776082_0.1904485392270392","host":"s3://npm-registry-packages"}},"0.8.1-pre.2":{"name":"@adobe/hypermedia-pipeline","version":"0.8.1-pre.2","author":"","license":"Apache-2.0","_id":"@adobe/hypermedia-pipeline@0.8.1-pre.2","maintainers":[{"name":"abhinavsaraswat","email":"absarasw@adobe.com"},{"name":"adobe-activation","email":"Engineering-Admins@adobe.com"},{"name":"adobe-admin","email":"grp-opensourceoffice@adobe.com"},{"name":"adobe-behance","email":"sedunn@adobe.com"},{"name":"aemsites","email":"meyer@adobe.com"},{"name":"anjankaur","email":"anjankaur01.mkr@gmail.com"},{"name":"asteed","email":"andrewsteed@gmail.com"},{"name":"dpfister","email":"dominique.pfister@gmail.com"},{"name":"filmaj","email":"maj.fil@gmail.com"},{"name":"garthdb","email":"garthdb@gmail.com"},{"name":"jfkhoury","email":"jfkhoury@gmail.com"},{"name":"jileesh","email":"jileeshsathyan@gmail.com"},{"name":"kerrishotts","email":"kerrishotts@gmail.com"},{"name":"kptdobe","email":"kptdobe@gmail.com"},{"name":"krisnye","email":"krisnye@gmail.com"},{"name":"lazd","email":"lazdnet@gmail.com"},{"name":"macdonst","email":"simon.macdonald@gmail.com"},{"name":"marbec","email":"mabecker@adobe.com"},{"name":"purplecabbage","email":"purplecabbage@gmail.com"},{"name":"shazron","email":"shazron@gmail.com"},{"name":"stefan-guggisberg","email":"sg@adobe.com"},{"name":"stevegill","email":"stevengill97@gmail.com"},{"name":"target-admin","email":"ciocanu@adobe.com"},{"name":"trieloff","email":"lars@trieloff.net"},{"name":"tripod","email":"tripod@bocanegra.ch"}],"homepage":"https://github.com/adobe/hypermedia-pipeline#readme","bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"dist":{"shasum":"cb80180a164dd147eca06e2310a5dc378e4e371a","tarball":"https://registry.npmjs.org/@adobe/hypermedia-pipeline/-/hypermedia-pipeline-0.8.1-pre.2.tgz","fileCount":140,"integrity":"sha512-HiKm//WKjNrzWwCHEZerQbemV3ZKLaoU19QolCXmsLEDyrDHajOKrdJMNRuqmCWtF9YT0uu72CqkNcgOp6A65g==","signatures":[{"sig":"MEUCIEcZCP1wqG1MgpUZZz8FkBzg2noyI036pWjUgqxTppc0AiEA5f/utd+iRhNFGtBhX5CkNYftyuEMLUB5C/Hyd9vA5xs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":578703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb9sMrCRA9TVsSAnZWagAAxdwQAISBHAmETNJfY3rR0d/o\n+hJOV97QMW3yTNWa0wFDG5LDbUuiNN+zRTOfY77uSLiDpT6epFpNsqGQxQr/\nGK7Zuj/SBX1wnD8qvG6Z2E9Rq/CEnZ0+vTaXJlUGri39rDpho2ine41Hv765\nWNzLEhLwxas1gmDmbm6znSNdE4Xt+HtH00T9ufjyo1rehVvbXS5GqVYd4Sq5\nKyEmPKG+31GxaNVdd+znuNnRM+IMfipfqY7s3s7mg46D2Psoh5R3FKjOCbJ6\nMcGc3gL8vgRBJSnCx4cHFuJecn4Ld1j6pI8z/pKntYWmSPPHOekc6j/mr7f5\nZuSnIuN3f9m/4F2IQ7npeJVtYqkRktDeMuggNdAbOa3amLvdLeyKB6gnYu2W\nd1C9nqSWm9qJFsTp0tTtzVQ0cbHhI7kPRHngO/3Bld5t0pju2R+qzL+bKsav\ns/WGPOOBE2g5t+6qZ3mdK4f57qk8WuXS2KtuH382LQp++QuCzY0Uce2rj6zO\nmMIzKXZjNSgfjGsaGslLvCo3NjNiYONq3rbrwYlpi14mjou26Pu/GvZ5I7fV\nybWKB+rc3jnalzcl9RQo79lMBScbBbM3AgByh4IknrFmLxpeLp91EClo0xsK\nM9vZFibAEVC5sz8lIKRvPDEAKhToszvHXDEsxcC7Oam7WF6oA3wiBfFL850K\nrekE\r\n=IGdg\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","snyk":true,"types":"index.d.ts","readme":"# Hypermedia Pipeline\n\nThis project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.\n\nIt uses reducers and continuations to create a simple processing pipeline that can pre-and post-process HTML, JSON, and other hypermedia.\n\n# Status\n\n[![codecov](https://img.shields.io/codecov/c/github/adobe/hypermedia-pipeline.svg)](https://codecov.io/gh/adobe/hypermedia-pipeline)\n[![CircleCI](https://img.shields.io/circleci/project/github/adobe/hypermedia-pipeline.svg)](https://circleci.com/gh/adobe/hypermedia-pipeline)\n[![GitHub license](https://img.shields.io/github/license/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/adobe/hypermedia-pipeline.svg)](https://github.com/adobe/hypermedia-pipeline/issues)\n[![npm](https://img.shields.io/npm/dw/@adobe/hypermedia-pipeline.svg)](https://www.npmjs.com/package/@adobe/hypermedia-pipeline) [![Greenkeeper badge](https://badges.greenkeeper.io/adobe/hypermedia-pipeline.svg)](https://greenkeeper.io/)\n\n## Anatomy of a Pipeline\n\nA pipeline consists of following main parts:\n\n- pre-processing functions\n- the main response generating function\n- an optional wrapper function\n- post-processing functions\n- error handling functions\n\nEach step of the pipeline is processing a single payload object, that will slowly accumulate the `return` values of the functions above through `Object.assign`.\n\nSee below for the anatomy of a payload.\n\nTypically, there is one pipeline for each content type supported and pipeline are identified by file name, e.g.\n\n- `html.pipe.js` – creates HTML documents with the `text/html` content-type\n- `json.pipe.js` – creates JSON documents with the `application/json` content-type\n\n### Building a Pipeline\n\nA pipeline builder can be created by creating a CommonJS module that exports a function `pipe` which accepts following arguments and returns a Pipeline function.\n\n- `cont`: the main function that will be executed as a continuation of the pipeline\n- `payload`: the [payload](./docs/context.schema.md) (aka context) that is accumulated during the pipeline. \n- `action`: the [action](./docs/action.schema.md) that servers as holder for extra pipeline invocation argument.\n\nThis project's main entry provides a helper function for pipeline construction and a few helper functions, so that a basic pipeline can be constructed like this:\n\n```javascript\n// the pipeline itself\nconst pipeline = require(\"@adobe/hypermedia-pipeline\");\n\nmodule.exports.pipe = function(cont, context, action) {\n    action.logger.log(\"debug\", \"Constructing Custom Pipeline\");\n\n    return pipeline()\n        .before(adjustContent)\n        .once(cont)            // required: execute the continuation function\n        .after(cleanupContent)\n}\n```\n\nIn a typical pipeline, you will add additional processing steps as `.before(require('some-module'))` or as `.after(require('some-module'))`.\n\n### The Main Function\n\nThe main function is typically a pure function that converts the `request` and `content` properties of the `context` into a `response` object.\n\nIn most scenarios, the main function is compiled from a template in a templating language like HTL, JST, or JSX.\n\nTypically, there is one template (and thus one main function) for each content variation of the file type. Content variations are identified by a selector (the piece of the file name before the file extension, e.g. in `example.navigation.html` the selector would be `navigation`). If no selector is provided, the template is the default template for the pipeline.\n\nExamples of possible template names include:\n\n- `html.jsx` (compiled to `html.js`) – default for the HTML pipeline\n- `html.navigation.jst` (compiled to `html.navigation.js`) – renders the navigation\n- `dropdown.json.js` (not compiled) – creates pure JSON output\n- `dropdown.html.htl` (compiled to `dropdown.html.js`) – renders the dropdown component\n\n\n### (Optional) The Wrapper Function\n\nSometimes it is necessary to pre-process the payload in a template-specific fashion. This wrapper function (often called \"Pre-JS\" for brevity sake) allows the full transformation of the pipeline's payload.\n\nCompared to the pipeline-specific pre-processing functions which handle the request, content, and response, the focus of the wrapper function is implementing business logic needed for the main template function. This allows for a clean separation between:\n\n1. presentation (in the main function, often expressed in declarative templates)\n2. business logic (in the wrapper function, often expressed in imperative code)\n3. content-type specific implementation (in the pipeline, expressed in functional code)\n\nA simple implementation of a wrapper function would look like this:\n\n```javascript\n// All wrapper functions must export `pre`\n// The functions takes following arguments:\n// - `cont` (the continuation function, i.e. the main template function)\n// - `payload` (the payload of the pipeline)\n// - `action` (the action of the pipeline)\nmodule.exports.pre = (cont, payload, action) => {\n    const {request, content, response} = payload;\n    \n    // modifying the payload content before invoking the main function\n    content.hello = 'World';\n    const modifiedpayload = {request, content, response};\n\n    // invoking the main function with the new payload. Capturing the response\n    // payload for further modification\n\n    const responsepayload = cont(modifiedpayload, action);\n\n    // Adding a value to the payload response\n    const modifiedresponse = modifiedpayload.response;\n    modifiedresponse.hello = 'World';\n\n    return Object.assign(modifiedpayload, modifiedresponse);\n}\n```\n\n### Pre-Processing Functions\n\nPre-Processing functions are meant to:\n\n- parse and process request parameters\n- fetch and parse the requested content\n- transform the requested content\n\n### Post-Processing Functions\n\nPost-Processing functions are meant to:\n\n- process and transform the response\n\n### Error Handlers\n\nIn default state, the pipeline will process all normal functions but will skip `error handlers`  (`.error()`). But when the pipeline is in the _error state_, the normal processing functions are no longer executed until the end of the pipeline is reached or if the _error state_ is cleared. It will however, execute _error handlers_.\nThe pipeline execution is in an _error state_ if `context.error` is defined. This can happen with if a processing function throws an Exception, or if it sets the `context.error` object directly.\n\nExample:\n\n```js\nnew pipeline()\n  .before(doSomething)\n  .once(render)\n  .after(cleanup)\n  .error(handleError)\n  .after(done);\n```\n\nIf in the above example, the `doSomething` causes an error, subsequently, `render` and `cleanup` will not be invoked. but `handleError` will. If `handleError` clears the error state (i.e. sets `context.error = null`), the `done` function will be invoked again.\n\nIf in the above example, none of the functions causes an error, the `handleError` will never be invoked.\n\n## Anatomy of the Payload\n\nFollowing main properties exist:\n\n- `request`\n- `content`\n- `response`\n- `error`\n\nalso see [context schema](./docs/context.schema.md)\n\n### The `request` object\n\n- `params`: a map of request parameters\n- `headers`: a map of HTTP headers\n\nalso see [request schema](./docs/request.schema.md)\n\n### The `content` object\n\n- `body`: the unparsed content body as a `string`\n- `mdast`: the parsed [Markdown AST](https://github.com/syntax-tree/mdast)\n- `meta`: a map metadata properties, including\n  - `title`: title of the document\n  - `intro`: a plain-text introduction or description\n  - `type`: the content type of the document\n  - `image`: the URL of the first image in the document\n- `htast`: the HTML AST\n- `document`: a DOM-compatible [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) representation of the (HTML) document ([see below](#contentdocument-in-detail))\n- `sections[]`: The main sections of the document, as an enhanced MDAST ([see below](#contentsections-in-detail))\n- `html`: a string of the content rendered as HTML\n- `children`: an array of top-level elements of the HTML-rendered content\n\nalso see [content schema](./docs/content.schema.md)\n\n### `content.document` in Detail\n\nFor developers that prefer using the rendered HTML over the input Markdown AST, `content.document` provides a representation of the rendered HTML that is API-compatible to the `window.document` object you would find in a browser.\n\nThe most common way of using it is probably calling `content.document.innerHTML`, which gives the full HTML of the page, but other functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.querySelector`\n- `content.document.querySelectorAll`\n\nare also available. Please note that some functions like\n\n- `content.document.getElementsByClassName`\n- `content.document.getElementByID`\n\nare less useful because the HTML generated by the default pipeline does not inject class name or ID attributes.\n\nThe tooling for generating (Virtual) DOM nodes from Markdown AST is made available as a utility class, so that it can be used in custom `pre.js` scripts, and [described below](#generate-a-virtual-dom-with-utilsvdom).\n\n### `content.sections` in Detail\n\nThe default pipeline extracts sections from a Markdown document, using both \"thematic breaks\" like `***` or `---` and embedded YAML blocks as section markers. If no sections can be found in the document, the entire `content.mdast` will be identically to `content.sections[0]`.\n\n`content.sections` is an Array of `section` nodes, with `type` (String) and `children` (array of Node) properties. In addition, each section has a `types` attribute, which is an array of derived content types. Project Helix (and Hypermedia Pipeline) uses implied typing over declared content typing, which means it is not the task of the author to explicitly declare the content type of a section or document, but rather have the template interpret the contents of a section to understand the type of content it is dealing with.\n\nThe `types` property is an array of string values that describes the type of the section based on the occurrence of child nodes. This makes it easy to copy the value of `types` into the `class` attribute of an HTML element, so that CSS expressions matching types of sections can be written with ease. Following patterns of `type` values can be found:\n\n- `has-<type>`: for each type of content that occurs at least once in the section, e.g. has-heading\n- `is-<type>-only`: for sections that only have content of a single type, e.g. is-image-only\n- `is-<type-1>-<type-2>-<type3>`, `is-<type-1>-<type-2>`, and `is-<type-1>` for the top 3 most frequent types of children in the section. For instance a gallery with a heading and description would be `is-image-paragraph-heading`. You can infer additional types using [`utils.types`](#infer-content-types-with-utilstypes).\n\nEach section has additional content-derived metadata properties, in particular:\n\n- `title`: the value of the first headline in the section\n- `intro`: the value of the first paragraph in the section\n- `image`: the URL of the first image in the section\n- `meta`: the parsed YAML metadata of the section (as an object)\n\n\n\n### The `response` object\n\n- `body`: the unparsed response body as a `string`\n- `headers`: a map of HTTP response headers\n- `status`: the HTTP status code\n\nalso see [response schema](./docs/response.schema.md)\n\n### The `error` object\n\nThis object is only set when there has been an error during pipeline processing. Any step in the pipeline may set the `error` object. Subsequent steps should simply skip any processing if they encounter an `error` object.\n\nAlternatively, steps can attempt to handle the `error` object, for instance by generating a formatted error message and leaving it in `response.body`.\n\nThe only known property in `error` is\n\n- `message`: the error message\n\n## Utilities\n\n### Generate a Virtual DOM with `utils.vdom`\n\n`VDOM` is a helper class that transforms [MDAST](https://github.com/syntax-tree/mdast) Markdown into DOM nodes using customizable matcher functions or expressions. \n\nIt can be used in scenarios where:\n\n- you need to represent only a `section` of the document in HTML\n- you have made changes to `content.mdast` and want them reflected in HTML\n- you want to customize the HTML output for certain Markdown elements\n\n#### Getting Started\n\nLoad the `VDOM` helper through:\n\n```javascript\nconst VDOM = require('@adobe/hypermedia-pipeline').utils.vdom;\n```\n\n#### Simple Transformations\n\n```javascript\ncontent.document = new VDOM(content.mdast).getDocument();\n```\n\nThis replaces `content.document` with a re-rendered representation of the Markdown AST. It can be used when changes to `content.mdast` have been made.\n\n```javascript\ncontent.document = new VDOM(content.sections[0]).getDocument();\n```\n\nThis uses only the content of the first section to render the document.\n\n#### Matching Nodes\n\nNodes in the Markdown AST can be matched in two ways: either using a [select](https://www.npmjs.com/package/unist-util-select)-statement or using a predicate function.\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match('heading', () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nEvery node with the type `heading` will be rendered as `<h1>This text replaces your heading</h1>`;\n\n```javascript\nconst vdom = new VDOM(content.mdast);\nvdom.match(function test(node) {\n  return node.type === 'heading';\n}, () => '<h1>This text replaces your heading</h1>');\ncontent.document = vdom.getDocument();\n```\n\nInstead of the select-statement, you can also provide a function that returns `true` or `false`. The two examples above will have the same behavior.\n\n#### Creating DOM Nodes\n\nThe second argument to `match` is a node-generating function that should return one of the following three options:\n\n1. an [HAST](https://github.com/syntax-tree/hast) (Hypertext Abstract Syntax Tree) node\n2. a DOM [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node)\n3. a `String` containing HTML tags.\n\n```javascript\nvdom.match('link', (_, node) => {\n  return {\n    type: 'element',\n    tagName: 'a',\n    properties: {\n      href: node.url,\n      rel: 'nofollow'\n    },\n    children: [\n      {\n        type: 'text',\n        value: node.children.map(({ value }) => value)\n      }\n    ]\n  }\n}\n```\n\nAbove: injecting `rel=\"nofollow\"` using HTAST.\n\n```javascript\nconst h = require('hyperscript');\n\nvdom.match('link', (_, node) => h(\n    'a',\n    { href: node.url, rel: 'nofollow' },\n    node.children.map(({ value }) => value),\n  );\n```\n\nAbove: doing the same using [Hyperscript](https://github.com/hyperhype/hyperscript) (which creates DOM elements) is notably shorter.\n\n```javascript\nvdom.match('link', (_, node) => \n  `<a href=\"${node.url}\" rel=\"nofollow\">$(node.children.map(({ value }) => value)).join('')</a>`;\n```\n\nAbove: Plain `String`s can be constructed using String Templates in ES6 for the same result.\n\n#### Creating Responsive Images\n\nThe VDOM Utility is prepared to create `srcset` and `sizes` attributes for responsive images. By default, five different resolutions ranging from `480w` to `4096w` will be generated. To create truly effective responsive images, some knowledge of the desired layout of the page, and hence some configuration is required.\n\n`utils.vdom` provides two configuration options:\n\n1. Define what physical image widths are made available with `widths`\n2. Define which images get loaded with `sizes`\n\nBoth configuration options get passed to an optional `options` argument for the `VDOM` constructor:\n\n\n```javascript\nconst widths;\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\n`widths` is either an array of possible image widths (positive integer values) or a `widthpec` that looks like this:\n\n```javascript\nconst widths = {\n  from: 320,\n  to: 9600,\n  steps: 10\n};\nconst sizes;\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nResponsive images will be generated on the fly and only when requested, so the only cost involved with increasing the number of `steps` is the length of the resultant `srcset` attribute.\n\nIn order to define what images get loaded, the `sizes` attribute must be set. In HTML, sizes is a comma-separated list of pairs of media queries and length expressions. For `util.vdom`, the setting is an array of these pairs.\n\n```javascript\nconst widths;\nconst sizes = [\n  '(min-width: 36em) 33.3vw',\n  '(min-width: 48em) calc(.333 * (100vw - 12em))',\n  '100vw'\n];\ncontent.document = new VDOM(content.mdast, {widths, sizes}).getDocument();\n```\n\nThis gives you fine-grained control over the image widths that are made available and will get loaded by browsers based on the width of the browser window. With `util.vdom` you can have different settings per page- or section-type.\n\n### Infer Content Types with `utils.types`\n\nIn addition to the automatically inferred content types for each section, `utils.types` provides a `TypeMatcher` utility class that allows matching section content against a simple expression language and thus enrich the `section[].types` values.\n\n\n```javascript\nconst TypeMatcher = require('@adobe/hypermedia-pipeline').utils.types;\n\nconst matcher = new TypeMatcher(content.sections);\nmatcher.match('^heading', 'starts-with-heading');\ncontent.sections = matcher.process();\n```\n\nIn the example above, all sections that have a `heading` as the first child will get the value `starts-with-heading` appended to the `types` array. `^heading` is an example of the content expression language, which allows matching content against a simple regular expression-like syntax.\n\n##### Content Expression Language\n\n* `^heading` – the first element is a `heading`\n* `paragraph$` – the last element is a `paragraph`\n* `heading image+` – a `heading` followed by one or more `image`s\n* `heading? image` – an optional `heading` followed by one `image`\n* `heading paragraph* image` – a `heading` followed by any number of `paragraph`s (also no paragraphs at all), followed by an `image`\n* `(paragraph|list)` – a `paragraph` or a `list`\n* `^heading (image paragraph)+$` – one `heading`, followed by pairs of `image` and `paragraph`, but at least one\n\n### Inspecting the Pipeline Context\n\nWhen run in non-production, i.e. outside an OpenWhisk action, for example in `hlx up`, Pipeline Dumping is enabled. Pipeline Dumping allows developers to easily inspect the `Context` object of each step of the pipeline and can be used to debug pipeline functions and to generate realistic test cases.\n\nEach stage of the pipeline processing will create a file like `$PWD/logs/debug/context_dump_34161BE5KuR0nuFDp/context-20180902-1418-05.0635-step-2.json` inside the `debug` directory. These dumps will be removed when the `node` process ends, so that after stopping `hlx up` the `debug` directory will be clean again. The `-step-n` in the filename indicates the step in the pipeline that has been logged.\n\nA simple example might look like this:\n\nStep 0:\n```json\n{}\n```\n\nStep 1:\n```json\n{\n  \"request\": {}\n}\n```\n\nStep 2:\n```json\n{\n  \"request\": {},\n  \"content\": {\n    \"body\": \"---\\ntemplate: Medium\\n---\\n\\n# Bill, Welcome to the future\\n> Project Helix\\n\\n## Let's talk about Project Helix\\n![](./moscow/assets/IMG_0167.jpg)\\n\",\n    \"sources\": [\n      \"https://raw.githubusercontent.com/trieloff/soupdemo/master/hello.md\"\n    ]\n  }\n}\n```\n\nStep 3 (diff only):\n```diff\n@@ -1,6 +1,58 @@\n {\n   \"content\": {\n-    \"body\": \"Hello World\"\n+    \"body\": \"Hello World\",\n+    \"mdast\": {\n+      \"type\": \"root\",\n+      \"children\": [\n+        {\n+          \"type\": \"paragraph\",\n+          \"children\": [\n+            {\n+              \"type\": \"text\",\n+              \"value\": \"Hello World\",\n+              \"position\": {\n+                \"start\": {\n+                  \"line\": 1,\n+                  \"column\": 1,\n+                  \"offset\": 0\n+                },\n+                \"end\": {\n+                  \"line\": 1,\n+                  \"column\": 12,\n+                  \"offset\": 11\n+                },\n+                \"indent\": []\n+              }\n+            }\n+          ],\n+          \"position\": {\n+            \"start\": {\n+              \"line\": 1,\n+              \"column\": 1,\n+              \"offset\": 0\n+            },\n+            \"end\": {\n+              \"line\": 1,\n+              \"column\": 12,\n+              \"offset\": 11\n+            },\n+            \"indent\": []\n+          }\n+        }\n+      ],\n+      \"position\": {\n+        \"start\": {\n+          \"line\": 1,\n+          \"column\": 1,\n+          \"offset\": 0\n+        },\n+        \"end\": {\n+          \"line\": 1,\n+          \"column\": 12,\n+          \"offset\": 11\n+        }\n+      }\n+    }\n   },\n   \"request\": {}\n }\n```\n\nStep 5 (diff only):\n```diff\n@@ -52,7 +52,49 @@\n           \"offset\": 11\n         }\n       }\n-    }\n+    },\n+    \"sections\": [\n+      {\n+        \"type\": \"root\",\n+        \"children\": [\n+          {\n+            \"type\": \"paragraph\",\n+            \"children\": [\n+              {\n+                \"type\": \"text\",\n+                \"value\": \"Hello World\",\n+                \"position\": {\n+                  \"start\": {\n+                    \"line\": 1,\n+                    \"column\": 1,\n+                    \"offset\": 0\n+                  },\n+                  \"end\": {\n+                    \"line\": 1,\n+                    \"column\": 12,\n+                    \"offset\": 11\n+                  },\n+                  \"indent\": []\n+                }\n+              }\n+            ],\n+            \"position\": {\n+              \"start\": {\n+                \"line\": 1,\n+                \"column\": 1,\n+                \"offset\": 0\n+              },\n+              \"end\": {\n+                \"line\": 1,\n+                \"column\": 12,\n+                \"offset\": 11\n+              },\n+              \"indent\": []\n+            }\n+          }\n+        ]\n+      }\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 6 (diff only):\n ```diff\n@@ -92,9 +92,19 @@\n               \"indent\": []\n             }\n           }\n-        ]\n+        ],\n+        \"title\": \"Hello World\",\n+        \"types\": [\n+          \"has-paragraph\",\n+          \"is-paragraph-only\"\n+        ],\n+        \"intro\": \"Hello World\",\n+        \"meta\": {}\n       }\n-    ]\n+    ],\n+    \"meta\": {},\n+    \"title\": \"Hello World\",\n+    \"intro\": \"Hello World\"\n   },\n   \"request\": {}\n }\n ```\n\n Step 9 (diff only):\n\n ```diff\n @@ -169,7 +169,11 @@\n         \"search\": \"\",\n         \"hash\": \"\"\n       }\n-    }\n+    },\n+    \"html\": \"<p>Hello World</p>\",\n+    \"children\": [\n+      \"<p>Hello World</p>\"\n+    ]\n   },\n   \"request\": {}\n }\n ```\n\n Step 10 (diff only):\n\n ```diff\n @@ -175,5 +175,9 @@\n       \"<p>Hello World</p>\"\n     ]\n   },\n-  \"request\": {}\n+  \"request\": {},\n+  \"response\": {\n+    \"status\": 201,\n+    \"body\": \"<p>Hello World</p>\"\n+  }\n }\n ```\n","gitHead":"65dad1ebe52b64f6d5db8015960e6eb1b3f76176","scripts":{"docs":"npx jsonschema2md -d src/schemas -o docs","lint":"npx eslint . && npm run types","test":"nyc mocha","types":"npm run docs && node bin/schema2ts.js","prepare":"npm run snyk-protect","preversion":"npm test","postversion":"git push origin master --follow-tags","snyk-protect":"snyk protect","delete-git-tag":"git tag -d v$npm_package_version && git push origin :v$npm_package_version"},"_npmUser":{"name":"trieloff","email":"lars@trieloff.net"},"repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"_npmVersion":"6.4.0","description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","directories":{},"_nodeVersion":"8.12.0","dependencies":{"ajv":"^6.5.4","snyk":"^1.88.1","jsdom":"^13.0.0","mdurl":"^1.0.1","lodash":"^4.17.10","retext":"^6.0.0","uri-js":"^4.2.2","js-yaml":"^3.12.0","request":"^2.87.0","unified":"^7.0.0","winston":"^3.0.0","fs-extra":"^7.0.0","callsites":"^3.0.0","micromatch":"^3.1.10","hyperscript":"^2.0.2","object-hash":"^1.3.1","rehype-parse":"^6.0.0","remark-parse":"^6.0.0","remark-rehype":"^3.0.0","unist-util-map":"^1.0.4","hast-util-to-html":"^5.0.0","unist-util-select":"^2.0.0","mdast-util-to-hast":"^4.0.0","remark-frontmatter":"^1.3.0","retext-smartypants":"^3.0.1","hast-to-hyperscript":"^6.0.0","mdast-util-to-string":"^1.0.4","request-promise-native":"^1.0.5","json-schema-to-typescript":"^6.0.1","unist-util-find-all-between":"^1.0.2","@adobe/openwhisk-loggly-wrapper":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"nyc":"^13.0.1","mocha":"^5.2.0","eslint":"^5.6.1","codecov":"^3.0.2","istanbul":"^1.0.0-alpha.2","unist-util-inspect":"^4.1.3","eslint-plugin-react":"^7.11.0","@adobe/jsonschema2md":"^1.1.1-SNAPSHOT.236","eslint-config-airbnb":"^17.1.0","eslint-plugin-header":"^2.0.0","eslint-plugin-import":"^2.14.0","mocha-junit-reporter":"^1.17.0","eslint-plugin-jsx-a11y":"^6.1.1","unist-util-remove-position":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/hypermedia-pipeline_0.8.1-pre.2_1542898474978_0.6069982680553647","host":"s3://npm-registry-packages"}}},"time":{"created":"2018-06-28T11:04:32.814Z","modified":"2026-07-08T08:13:10.679Z","0.1.0":"2018-06-28T11:04:33.127Z","0.1.0-SNAPSHOT.14":"2018-06-28T11:09:11.609Z","0.1.0-SNAPSHOT.16":"2018-06-28T11:09:57.333Z","0.1.0-SNAPSHOT.18":"2018-06-29T02:06:56.494Z","0.1.0-SNAPSHOT.20":"2018-06-29T02:41:24.261Z","0.1.0-SNAPSHOT.22":"2018-06-29T02:51:09.742Z","0.1.0-SNAPSHOT.24":"2018-07-02T17:18:10.709Z","0.2.0-SNAPSHOT.26":"2018-07-02T17:40:45.891Z","0.3.0-class":"2018-07-03T12:57:39.748Z","0.3.1-class":"2018-07-03T14:30:54.779Z","0.3.2-SNAPSHOT.42":"2018-07-04T07:30:15.925Z","0.3.2-SNAPSHOT.44":"2018-07-04T07:53:07.909Z","0.3.2-SNAPSHOT.46":"2018-07-04T07:56:44.971Z","0.3.2-SNAPSHOT.48":"2018-07-04T08:00:27.907Z","0.3.2-SNAPSHOT.53":"2018-07-04T10:23:47.044Z","0.3.2-SNAPSHOT.57":"2018-07-05T09:49:57.761Z","0.3.2-SNAPSHOT.61":"2018-07-05T15:58:00.517Z","0.3.2-SNAPSHOT.66":"2018-07-05T16:06:27.377Z","0.3.2-SNAPSHOT.72":"2018-07-06T12:12:06.246Z","0.3.2-SNAPSHOT.74":"2018-07-06T12:13:39.038Z","0.3.2-SNAPSHOT.78":"2018-07-12T02:20:55.865Z","0.3.2-SNAPSHOT.85":"2018-07-18T18:56:26.039Z","0.3.2-SNAPSHOT.90":"2018-08-14T07:36:31.703Z","0.3.2-SNAPSHOT.93":"2018-08-14T14:25:44.558Z","0.3.2-SNAPSHOT.95":"2018-08-20T09:15:22.759Z","0.3.3-pre.0":"2018-08-24T01:19:05.703Z","0.3.3":"2018-08-24T01:21:34.586Z","0.3.4-pre.0":"2018-08-24T01:22:49.174Z","0.4.0-pre.1":"2018-09-06T05:37:21.310Z","0.4.0-pre.2":"2018-09-06T06:09:37.178Z","0.4.0":"2018-09-06T07:45:27.238Z","0.4.1-pre.0":"2018-09-06T07:46:40.893Z","0.5.0-pre.1":"2018-09-12T06:52:58.435Z","0.5.0":"2018-09-12T07:20:27.984Z","0.5.1-pre.0":"2018-09-12T07:21:02.970Z","0.5.1-pre.1":"2018-09-14T06:35:07.177Z","0.5.1-pre.2":"2018-09-17T13:45:32.034Z","0.5.1-pre.3":"2018-09-18T03:02:08.705Z","0.5.1-pre.4":"2018-09-18T04:42:06.230Z","0.5.1-pre.5":"2018-09-18T04:46:35.018Z","0.5.1-pre.6":"2018-09-21T08:14:29.387Z","0.5.1-pre.7":"2018-09-24T07:10:31.853Z","0.5.1-pre.8":"2018-09-24T07:40:02.868Z","0.5.1-pre.9":"2018-09-24T16:28:00.213Z","0.5.1-pre.10":"2018-09-27T09:19:55.184Z","0.5.1-pre.11":"2018-09-27T12:49:41.887Z","0.5.1-pre.12":"2018-09-27T13:45:46.475Z","0.6.0":"2018-10-09T04:30:17.874Z","0.6.1-pre.0":"2018-10-09T04:31:21.853Z","0.6.1-pre.1":"2018-10-10T18:02:29.609Z","0.6.1-pre.2":"2018-10-11T04:05:11.086Z","0.6.1-pre.3":"2018-10-11T09:06:53.553Z","0.6.1-pre.4":"2018-10-11T09:12:46.710Z","0.6.1-pre.5":"2018-10-23T14:37:07.298Z","0.6.1-pre.6":"2018-10-24T10:59:42.420Z","0.6.1-pre.7":"2018-10-24T11:01:21.485Z","0.6.1-pre.8":"2018-10-31T00:15:53.927Z","0.6.1-pre.9":"2018-10-31T05:00:11.389Z","0.7.0":"2018-10-31T05:03:39.202Z","0.7.1-pre.0":"2018-10-31T05:04:34.615Z","0.7.1-pre.1":"2018-10-31T07:05:37.817Z","0.7.2-pre.0":"2018-10-31T07:10:28.428Z","0.7.1":"2018-10-31T07:10:39.579Z","0.7.2-pre.1":"2018-10-31T07:22:49.461Z","0.7.2-pre.2":"2018-11-01T07:58:32.142Z","0.7.2-pre.3":"2018-11-02T13:06:14.245Z","0.7.2-pre.4":"2018-11-02T13:28:28.619Z","0.7.2-pre.7":"2018-11-02T13:35:47.599Z","0.7.2-pre.8":"2018-11-02T13:38:41.518Z","0.7.2-pre.9":"2018-11-02T13:42:52.225Z","0.7.2-pre.10":"2018-11-02T13:44:30.916Z","0.7.2-pre.11":"2018-11-02T13:49:42.056Z","0.7.2-pre.12":"2018-11-02T14:03:59.884Z","0.7.2-pre.13":"2018-11-05T04:29:17.947Z","0.7.2":"2018-11-05T04:31:30.578Z","0.7.3-pre.0":"2018-11-05T04:32:18.153Z","0.7.3-pre.1":"2018-11-06T02:11:48.490Z","0.7.3":"2018-11-06T02:19:05.720Z","0.7.4-pre.0":"2018-11-06T02:19:52.173Z","0.7.4-pre.1":"2018-11-06T14:14:37.166Z","0.7.4":"2018-11-06T14:33:38.092Z","0.7.5-pre.0":"2018-11-06T14:34:59.050Z","0.7.5-pre.1":"2018-11-08T00:53:15.161Z","0.7.5-pre.2":"2018-11-08T14:12:41.953Z","0.7.5-pre.3":"2018-11-12T15:58:39.447Z","0.8.1-pre.0":"2018-11-21T11:07:46.147Z","0.8.0":"2018-11-21T11:08:19.068Z","0.8.1-pre.1":"2018-11-21T11:12:56.200Z","0.8.1-pre.2":"2018-11-22T14:54:35.156Z"},"bugs":{"url":"https://github.com/adobe/hypermedia-pipeline/issues"},"license":"Apache-2.0","homepage":"https://github.com/adobe/hypermedia-pipeline#readme","repository":{"url":"git+https://github.com/adobe/hypermedia-pipeline.git","type":"git"},"description":"This project provides helper functions and default implementations for creating Hypermedia Processing Pipelines.","maintainers":[{"email":"mabecker@adobe.com","name":"marbec"},{"email":"tripod@bocanegra.ch","name":"tripod"},{"email":"garthdb@gmail.com","name":"garthdb"},{"email":"lazdnet@gmail.com","name":"lazd"},{"email":"grp-opensourceoffice@adobe.com","name":"adobe-admin"},{"email":"patrickfulton@gmail.com","name":"patrickfulton"},{"email":"lars@trieloff.net","name":"trieloff"},{"email":"krisnye@gmail.com","name":"krisnye"},{"email":"dcpfsdk@adobe.com","name":"dcpfsdk"},{"email":"natebaldwindesign@gmail.com","name":"natebaldwin"},{"email":"devongovett@gmail.com","name":"devongovett"},{"email":"danniintheus@gmail.com","name":"aspro83"},{"email":"symanovi@adobe.com","name":"symanovi"},{"email":"dominique.pfister@gmail.com","name":"dpfister"},{"email":"sg@adobe.com","name":"stefan-guggisberg"},{"email":"npm@rofe.com","name":"rofe"},{"email":"kptdobe@gmail.com","name":"kptdobe"},{"email":"halls@adobe.com","name":"adobehalls"},{"email":"bradjohn@adobe.com","name":"fullcolorcoder"},{"email":"djaeggi@adobe.com","name":"djaeggi"},{"email":"dylandepass@gmail.com","name":"dylandepass"},{"email":"mhaack@adobe.com","name":"mhaack"},{"email":"amol@adobe.com","name":"amol-anand"},{"email":"stopp@adobe.com","name":"stopp-adobe"},{"email":"namarora@adobe.com","name":"namarora"},{"email":"doten@adobe.com","name":"doten"},{"email":"schmidt@adobe.com","name":"duh_schmidt"},{"email":"astha.bhargava23@gmail.com","name":"asthabh23"},{"email":"zouhir.dahbi@outlook.com","name":"zdahbi"},{"email":"tuicu@adobe.com","name":"tuicu"},{"email":"fmeschbe@adobe.com","name":"fmeschbe"},{"email":"mgedell@gmail.com","name":"maxakuru"},{"email":"vhosu@adobe.com","name":"vhosu"}],"readme":"","readmeFilename":""}